zstd-ruby 1.3.1.1 → 1.3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/ext/zstdruby/libzstd/.gitignore +1 -0
- data/ext/zstdruby/libzstd/Makefile +40 -26
- data/ext/zstdruby/libzstd/README.md +68 -45
- data/ext/zstdruby/libzstd/common/bitstream.h +35 -23
- data/ext/zstdruby/libzstd/common/compiler.h +1 -0
- data/ext/zstdruby/libzstd/common/error_private.c +4 -2
- data/ext/zstdruby/libzstd/common/error_private.h +4 -4
- data/ext/zstdruby/libzstd/common/fse.h +1 -1
- data/ext/zstdruby/libzstd/common/huf.h +1 -1
- data/ext/zstdruby/libzstd/common/mem.h +1 -0
- data/ext/zstdruby/libzstd/common/pool.c +61 -46
- data/ext/zstdruby/libzstd/common/pool.h +4 -0
- data/ext/zstdruby/libzstd/common/threading.c +11 -15
- data/ext/zstdruby/libzstd/common/threading.h +52 -32
- data/ext/zstdruby/libzstd/common/zstd_common.c +2 -2
- data/ext/zstdruby/libzstd/common/zstd_errors.h +3 -1
- data/ext/zstdruby/libzstd/common/zstd_internal.h +95 -21
- data/ext/zstdruby/libzstd/compress/fse_compress.c +3 -1
- data/ext/zstdruby/libzstd/compress/huf_compress.c +4 -3
- data/ext/zstdruby/libzstd/compress/zstd_compress.c +922 -2102
- data/ext/zstdruby/libzstd/compress/zstd_compress.h +307 -0
- data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +308 -0
- data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +28 -0
- data/ext/zstdruby/libzstd/compress/zstd_fast.c +242 -0
- data/ext/zstdruby/libzstd/compress/zstd_fast.h +30 -0
- data/ext/zstdruby/libzstd/compress/zstd_lazy.c +749 -0
- data/ext/zstdruby/libzstd/compress/zstd_lazy.h +38 -0
- data/ext/zstdruby/libzstd/compress/zstd_ldm.c +707 -0
- data/ext/zstdruby/libzstd/compress/zstd_ldm.h +67 -0
- data/ext/zstdruby/libzstd/compress/zstd_opt.c +957 -0
- data/ext/zstdruby/libzstd/compress/zstd_opt.h +14 -922
- data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +210 -133
- data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +20 -3
- data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +373 -196
- data/ext/zstdruby/libzstd/deprecated/zbuff.h +1 -0
- data/ext/zstdruby/libzstd/deprecated/zbuff_common.c +1 -0
- data/ext/zstdruby/libzstd/deprecated/zbuff_compress.c +1 -0
- data/ext/zstdruby/libzstd/deprecated/zbuff_decompress.c +1 -0
- data/ext/zstdruby/libzstd/dictBuilder/cover.c +33 -22
- data/ext/zstdruby/libzstd/dictBuilder/zdict.c +8 -5
- data/ext/zstdruby/libzstd/dictBuilder/zdict.h +1 -0
- data/ext/zstdruby/libzstd/dll/example/Makefile +5 -5
- data/ext/zstdruby/libzstd/legacy/zstd_legacy.h +1 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v01.c +1 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v01.h +1 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v02.c +1 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v02.h +1 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v03.c +1 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v03.h +1 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v04.c +1 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v04.h +1 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v05.c +1 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v05.h +1 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v06.c +1 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v06.h +1 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v07.c +1 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v07.h +1 -0
- data/ext/zstdruby/libzstd/zstd.h +366 -118
- data/lib/zstd-ruby/version.rb +1 -1
- metadata +11 -1
@@ -5,6 +5,7 @@
|
|
5
5
|
* This source code is licensed under both the BSD-style license (found in the
|
6
6
|
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
7
7
|
* in the COPYING file in the root directory of this source tree).
|
8
|
+
* You may select, at your option, one of the above-listed licenses.
|
8
9
|
*/
|
9
10
|
|
10
11
|
|
@@ -15,8 +16,7 @@
|
|
15
16
|
#include <stdlib.h> /* malloc, calloc, free */
|
16
17
|
#include <string.h> /* memset */
|
17
18
|
#include "error_private.h"
|
18
|
-
#
|
19
|
-
#include "zstd.h"
|
19
|
+
#include "zstd_internal.h"
|
20
20
|
|
21
21
|
|
22
22
|
/*-****************************************
|
@@ -5,6 +5,7 @@
|
|
5
5
|
* This source code is licensed under both the BSD-style license (found in the
|
6
6
|
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
7
7
|
* in the COPYING file in the root directory of this source tree).
|
8
|
+
* You may select, at your option, one of the above-listed licenses.
|
8
9
|
*/
|
9
10
|
|
10
11
|
#ifndef ZSTD_ERRORS_H_398273423
|
@@ -62,9 +63,10 @@ typedef enum {
|
|
62
63
|
ZSTD_error_memory_allocation = 64,
|
63
64
|
ZSTD_error_dstSize_tooSmall = 70,
|
64
65
|
ZSTD_error_srcSize_wrong = 72,
|
66
|
+
/* following error codes are not stable and may be removed or changed in a future version */
|
65
67
|
ZSTD_error_frameIndex_tooLarge = 100,
|
66
68
|
ZSTD_error_seekableIO = 102,
|
67
|
-
ZSTD_error_maxCode = 120 /* never EVER use this value directly, it
|
69
|
+
ZSTD_error_maxCode = 120 /* never EVER use this value directly, it can change in future versions! Use ZSTD_isError() instead */
|
68
70
|
} ZSTD_ErrorCode;
|
69
71
|
|
70
72
|
/*! ZSTD_getErrorCode() :
|
@@ -5,6 +5,7 @@
|
|
5
5
|
* This source code is licensed under both the BSD-style license (found in the
|
6
6
|
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
7
7
|
* in the COPYING file in the root directory of this source tree).
|
8
|
+
* You may select, at your option, one of the above-listed licenses.
|
8
9
|
*/
|
9
10
|
|
10
11
|
#ifndef ZSTD_CCOMMON_H_MODULE
|
@@ -29,6 +30,11 @@
|
|
29
30
|
#include "xxhash.h" /* XXH_reset, update, digest */
|
30
31
|
|
31
32
|
|
33
|
+
#if defined (__cplusplus)
|
34
|
+
extern "C" {
|
35
|
+
#endif
|
36
|
+
|
37
|
+
|
32
38
|
/*-*************************************
|
33
39
|
* Debug
|
34
40
|
***************************************/
|
@@ -96,9 +102,13 @@ static const U32 repStartValue[ZSTD_REP_NUM] = { 1, 4, 8 };
|
|
96
102
|
#define BIT0 1
|
97
103
|
|
98
104
|
#define ZSTD_WINDOWLOG_ABSOLUTEMIN 10
|
105
|
+
#define ZSTD_WINDOWLOG_DEFAULTMAX 27 /* Default maximum allowed window log */
|
99
106
|
static const size_t ZSTD_fcs_fieldSize[4] = { 0, 2, 4, 8 };
|
100
107
|
static const size_t ZSTD_did_fieldSize[4] = { 0, 1, 2, 4 };
|
101
108
|
|
109
|
+
#define ZSTD_FRAMEIDSIZE 4
|
110
|
+
static const size_t ZSTD_frameIdSize = ZSTD_FRAMEIDSIZE; /* magic number size */
|
111
|
+
|
102
112
|
#define ZSTD_BLOCKHEADERSIZE 3 /* C standard doesn't allow `static const` variable to be init using another `static const` variable */
|
103
113
|
static const size_t ZSTD_blockHeaderSize = ZSTD_BLOCKHEADERSIZE;
|
104
114
|
typedef enum { bt_raw, bt_rle, bt_compressed, bt_reserved } blockType_e;
|
@@ -117,7 +127,8 @@ typedef enum { set_basic, set_rle, set_compressed, set_repeat } symbolEncodingTy
|
|
117
127
|
#define MaxLit ((1<<Litbits) - 1)
|
118
128
|
#define MaxML 52
|
119
129
|
#define MaxLL 35
|
120
|
-
#define
|
130
|
+
#define DefaultMaxOff 28
|
131
|
+
#define MaxOff 31
|
121
132
|
#define MaxSeq MAX(MaxLL, MaxML) /* Assumption : MaxOff < MaxLL,MaxML */
|
122
133
|
#define MLFSELog 9
|
123
134
|
#define LLFSELog 9
|
@@ -143,8 +154,8 @@ static const S16 ML_defaultNorm[MaxML+1] = { 1, 4, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1,
|
|
143
154
|
#define ML_DEFAULTNORMLOG 6 /* for static allocation */
|
144
155
|
static const U32 ML_defaultNormLog = ML_DEFAULTNORMLOG;
|
145
156
|
|
146
|
-
static const S16 OF_defaultNorm[
|
147
|
-
|
157
|
+
static const S16 OF_defaultNorm[DefaultMaxOff+1] = { 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
|
158
|
+
1, 1, 1, 1, 1, 1, 1, 1,-1,-1,-1,-1,-1 };
|
148
159
|
#define OF_DEFAULTNORMLOG 5 /* for static allocation */
|
149
160
|
static const U32 OF_defaultNormLog = OF_DEFAULTNORMLOG;
|
150
161
|
|
@@ -243,6 +254,26 @@ typedef struct {
|
|
243
254
|
const BYTE* cachedLiterals;
|
244
255
|
} optState_t;
|
245
256
|
|
257
|
+
typedef struct {
|
258
|
+
U32 offset;
|
259
|
+
U32 checksum;
|
260
|
+
} ldmEntry_t;
|
261
|
+
|
262
|
+
typedef struct {
|
263
|
+
ldmEntry_t* hashTable;
|
264
|
+
BYTE* bucketOffsets; /* Next position in bucket to insert entry */
|
265
|
+
U64 hashPower; /* Used to compute the rolling hash.
|
266
|
+
* Depends on ldmParams.minMatchLength */
|
267
|
+
} ldmState_t;
|
268
|
+
|
269
|
+
typedef struct {
|
270
|
+
U32 enableLdm; /* 1 if enable long distance matching */
|
271
|
+
U32 hashLog; /* Log size of hashTable */
|
272
|
+
U32 bucketSizeLog; /* Log bucket size for collision resolution, at most 8 */
|
273
|
+
U32 minMatchLength; /* Minimum match length */
|
274
|
+
U32 hashEveryLog; /* Log number of entries to skip */
|
275
|
+
} ldmParams_t;
|
276
|
+
|
246
277
|
typedef struct {
|
247
278
|
U32 hufCTable[HUF_CTABLE_SIZE_U32(255)];
|
248
279
|
FSE_CTable offcodeCTable[FSE_CTABLE_SIZE_U32(OffFSELog, MaxOff)];
|
@@ -255,6 +286,28 @@ typedef struct {
|
|
255
286
|
FSE_repeat litlength_repeatMode;
|
256
287
|
} ZSTD_entropyCTables_t;
|
257
288
|
|
289
|
+
struct ZSTD_CCtx_params_s {
|
290
|
+
ZSTD_format_e format;
|
291
|
+
ZSTD_compressionParameters cParams;
|
292
|
+
ZSTD_frameParameters fParams;
|
293
|
+
|
294
|
+
int compressionLevel;
|
295
|
+
U32 forceWindow; /* force back-references to respect limit of
|
296
|
+
* 1<<wLog, even for dictionary */
|
297
|
+
|
298
|
+
/* Multithreading: used to pass parameters to mtctx */
|
299
|
+
U32 nbThreads;
|
300
|
+
unsigned jobSize;
|
301
|
+
unsigned overlapSizeLog;
|
302
|
+
|
303
|
+
/* Long distance matching parameters */
|
304
|
+
ldmParams_t ldmParams;
|
305
|
+
|
306
|
+
/* For use with createCCtxParams() and freeCCtxParams() only */
|
307
|
+
ZSTD_customMem customMem;
|
308
|
+
|
309
|
+
}; /* typedef'd to ZSTD_CCtx_params within "zstd.h" */
|
310
|
+
|
258
311
|
const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx);
|
259
312
|
void ZSTD_seqToCodes(const seqStore_t* seqStorePtr);
|
260
313
|
|
@@ -268,24 +321,27 @@ void ZSTD_free(void* ptr, ZSTD_customMem customMem);
|
|
268
321
|
|
269
322
|
MEM_STATIC U32 ZSTD_highbit32(U32 val)
|
270
323
|
{
|
324
|
+
assert(val != 0);
|
325
|
+
{
|
271
326
|
# if defined(_MSC_VER) /* Visual */
|
272
|
-
|
273
|
-
|
274
|
-
|
327
|
+
unsigned long r=0;
|
328
|
+
_BitScanReverse(&r, val);
|
329
|
+
return (unsigned)r;
|
275
330
|
# elif defined(__GNUC__) && (__GNUC__ >= 3) /* GCC Intrinsic */
|
276
|
-
|
331
|
+
return 31 - __builtin_clz(val);
|
277
332
|
# else /* Software version */
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
333
|
+
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 };
|
334
|
+
U32 v = val;
|
335
|
+
int r;
|
336
|
+
v |= v >> 1;
|
337
|
+
v |= v >> 2;
|
338
|
+
v |= v >> 4;
|
339
|
+
v |= v >> 8;
|
340
|
+
v |= v >> 16;
|
341
|
+
r = DeBruijnClz[(U32)(v * 0x07C4ACDDU) >> 27];
|
342
|
+
return r;
|
288
343
|
# endif
|
344
|
+
}
|
289
345
|
}
|
290
346
|
|
291
347
|
|
@@ -306,7 +362,7 @@ void ZSTD_invalidateRepCodes(ZSTD_CCtx* cctx);
|
|
306
362
|
size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
|
307
363
|
const void* dict, size_t dictSize,
|
308
364
|
const ZSTD_CDict* cdict,
|
309
|
-
|
365
|
+
ZSTD_CCtx_params params, unsigned long long pledgedSrcSize);
|
310
366
|
|
311
367
|
/*! ZSTD_compressStream_generic() :
|
312
368
|
* Private use only. To be called from zstdmt_compress.c in single-thread mode. */
|
@@ -315,10 +371,25 @@ size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
|
|
315
371
|
ZSTD_inBuffer* input,
|
316
372
|
ZSTD_EndDirective const flushMode);
|
317
373
|
|
318
|
-
/*!
|
374
|
+
/*! ZSTD_getCParamsFromCDict() :
|
319
375
|
* as the name implies */
|
320
|
-
|
321
|
-
|
376
|
+
ZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict);
|
377
|
+
|
378
|
+
/* ZSTD_compressBegin_advanced_internal() :
|
379
|
+
* Private use only. To be called from zstdmt_compress.c. */
|
380
|
+
size_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx,
|
381
|
+
const void* dict, size_t dictSize,
|
382
|
+
ZSTD_dictMode_e dictMode,
|
383
|
+
ZSTD_CCtx_params params,
|
384
|
+
unsigned long long pledgedSrcSize);
|
385
|
+
|
386
|
+
/* ZSTD_compress_advanced_internal() :
|
387
|
+
* Private use only. To be called from zstdmt_compress.c. */
|
388
|
+
size_t ZSTD_compress_advanced_internal(ZSTD_CCtx* cctx,
|
389
|
+
void* dst, size_t dstCapacity,
|
390
|
+
const void* src, size_t srcSize,
|
391
|
+
const void* dict,size_t dictSize,
|
392
|
+
ZSTD_CCtx_params params);
|
322
393
|
|
323
394
|
typedef struct {
|
324
395
|
blockType_e blockType;
|
@@ -331,5 +402,8 @@ typedef struct {
|
|
331
402
|
size_t ZSTD_getcBlockSize(const void* src, size_t srcSize,
|
332
403
|
blockProperties_t* bpPtr);
|
333
404
|
|
405
|
+
#if defined (__cplusplus)
|
406
|
+
}
|
407
|
+
#endif
|
334
408
|
|
335
409
|
#endif /* ZSTD_CCOMMON_H_MODULE */
|
@@ -461,6 +461,7 @@ static unsigned FSE_minTableLog(size_t srcSize, unsigned maxSymbolValue)
|
|
461
461
|
U32 minBitsSrc = BIT_highbit32((U32)(srcSize - 1)) + 1;
|
462
462
|
U32 minBitsSymbols = BIT_highbit32(maxSymbolValue) + 2;
|
463
463
|
U32 minBits = minBitsSrc < minBitsSymbols ? minBitsSrc : minBitsSymbols;
|
464
|
+
assert(srcSize > 1); /* Not supported, RLE should be used instead */
|
464
465
|
return minBits;
|
465
466
|
}
|
466
467
|
|
@@ -469,6 +470,7 @@ unsigned FSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsi
|
|
469
470
|
U32 maxBitsSrc = BIT_highbit32((U32)(srcSize - 1)) - minus;
|
470
471
|
U32 tableLog = maxTableLog;
|
471
472
|
U32 minBits = FSE_minTableLog(srcSize, maxSymbolValue);
|
473
|
+
assert(srcSize > 1); /* Not supported, RLE should be used instead */
|
472
474
|
if (tableLog==0) tableLog = FSE_DEFAULT_TABLELOG;
|
473
475
|
if (maxBitsSrc < tableLog) tableLog = maxBitsSrc; /* Accuracy can be reduced */
|
474
476
|
if (minBits > tableLog) tableLog = minBits; /* Need a minimum to safely represent all symbol values */
|
@@ -580,7 +582,7 @@ size_t FSE_normalizeCount (short* normalizedCounter, unsigned tableLog,
|
|
580
582
|
if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge); /* Unsupported size */
|
581
583
|
if (tableLog < FSE_minTableLog(total, maxSymbolValue)) return ERROR(GENERIC); /* Too small tableLog, compression potentially impossible */
|
582
584
|
|
583
|
-
{ U32 const rtbTable[] = { 0, 473195, 504333, 520860, 550000, 700000, 750000, 830000 };
|
585
|
+
{ static U32 const rtbTable[] = { 0, 473195, 504333, 520860, 550000, 700000, 750000, 830000 };
|
584
586
|
U64 const scale = 62 - tableLog;
|
585
587
|
U64 const step = ((U64)1<<62) / total; /* <== here, one division ! */
|
586
588
|
U64 const vStep = 1ULL<<(scale-20);
|
@@ -167,7 +167,7 @@ size_t HUF_writeCTable (void* dst, size_t maxDstSize,
|
|
167
167
|
}
|
168
168
|
|
169
169
|
|
170
|
-
size_t HUF_readCTable (HUF_CElt* CTable, U32
|
170
|
+
size_t HUF_readCTable (HUF_CElt* CTable, U32* maxSymbolValuePtr, const void* src, size_t srcSize)
|
171
171
|
{
|
172
172
|
BYTE huffWeight[HUF_SYMBOLVALUE_MAX + 1]; /* init not required, even though some static analyzer may complain */
|
173
173
|
U32 rankVal[HUF_TABLELOG_ABSOLUTEMAX + 1]; /* large enough for values from 0 to 16 */
|
@@ -179,7 +179,7 @@ size_t HUF_readCTable (HUF_CElt* CTable, U32 maxSymbolValue, const void* src, si
|
|
179
179
|
|
180
180
|
/* check result */
|
181
181
|
if (tableLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge);
|
182
|
-
if (nbSymbols >
|
182
|
+
if (nbSymbols > *maxSymbolValuePtr+1) return ERROR(maxSymbolValue_tooSmall);
|
183
183
|
|
184
184
|
/* Prepare base value per rank */
|
185
185
|
{ U32 n, nextRankStart = 0;
|
@@ -208,9 +208,10 @@ size_t HUF_readCTable (HUF_CElt* CTable, U32 maxSymbolValue, const void* src, si
|
|
208
208
|
min >>= 1;
|
209
209
|
} }
|
210
210
|
/* assign value within rank, symbol order */
|
211
|
-
{ U32 n; for (n=0; n
|
211
|
+
{ U32 n; for (n=0; n<nbSymbols; n++) CTable[n].val = valPerRank[CTable[n].nbBits]++; }
|
212
212
|
}
|
213
213
|
|
214
|
+
*maxSymbolValuePtr = nbSymbols - 1;
|
214
215
|
return readSize;
|
215
216
|
}
|
216
217
|
|
@@ -5,6 +5,7 @@
|
|
5
5
|
* This source code is licensed under both the BSD-style license (found in the
|
6
6
|
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
7
7
|
* in the COPYING file in the root directory of this source tree).
|
8
|
+
* You may select, at your option, one of the above-listed licenses.
|
8
9
|
*/
|
9
10
|
|
10
11
|
|
@@ -25,25 +26,19 @@
|
|
25
26
|
#include "fse.h"
|
26
27
|
#define HUF_STATIC_LINKING_ONLY
|
27
28
|
#include "huf.h"
|
28
|
-
#include "
|
29
|
-
#include "
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
***************************************/
|
35
|
-
static const U32 g_searchStrength = 8; /* control skip over incompressible data */
|
36
|
-
#define HASH_READ_SIZE 8
|
37
|
-
typedef enum { ZSTDcs_created=0, ZSTDcs_init, ZSTDcs_ongoing, ZSTDcs_ending } ZSTD_compressionStage_e;
|
29
|
+
#include "zstd_compress.h"
|
30
|
+
#include "zstd_fast.h"
|
31
|
+
#include "zstd_double_fast.h"
|
32
|
+
#include "zstd_lazy.h"
|
33
|
+
#include "zstd_opt.h"
|
34
|
+
#include "zstd_ldm.h"
|
38
35
|
|
39
36
|
|
40
37
|
/*-*************************************
|
41
38
|
* Helper functions
|
42
39
|
***************************************/
|
43
40
|
size_t ZSTD_compressBound(size_t srcSize) {
|
44
|
-
|
45
|
-
size_t const margin = (srcSize < lowLimit) ? (lowLimit-srcSize) >> 12 : 0; /* from 64 to 0 */
|
46
|
-
return srcSize + (srcSize >> 8) + margin;
|
41
|
+
return ZSTD_COMPRESSBOUND(srcSize);
|
47
42
|
}
|
48
43
|
|
49
44
|
|
@@ -61,8 +56,6 @@ static void ZSTD_resetSeqStore(seqStore_t* ssPtr)
|
|
61
56
|
/*-*************************************
|
62
57
|
* Context memory management
|
63
58
|
***************************************/
|
64
|
-
typedef enum { zcss_init=0, zcss_load, zcss_flush } ZSTD_cStreamStage;
|
65
|
-
|
66
59
|
struct ZSTD_CDict_s {
|
67
60
|
void* dictBuffer;
|
68
61
|
const void* dictContent;
|
@@ -70,65 +63,6 @@ struct ZSTD_CDict_s {
|
|
70
63
|
ZSTD_CCtx* refContext;
|
71
64
|
}; /* typedef'd to ZSTD_CDict within "zstd.h" */
|
72
65
|
|
73
|
-
struct ZSTD_CCtx_s {
|
74
|
-
const BYTE* nextSrc; /* next block here to continue on current prefix */
|
75
|
-
const BYTE* base; /* All regular indexes relative to this position */
|
76
|
-
const BYTE* dictBase; /* extDict indexes relative to this position */
|
77
|
-
U32 dictLimit; /* below that point, need extDict */
|
78
|
-
U32 lowLimit; /* below that point, no more data */
|
79
|
-
U32 nextToUpdate; /* index from which to continue dictionary update */
|
80
|
-
U32 nextToUpdate3; /* index from which to continue dictionary update */
|
81
|
-
U32 hashLog3; /* dispatch table : larger == faster, more memory */
|
82
|
-
U32 loadedDictEnd; /* index of end of dictionary */
|
83
|
-
U32 forceWindow; /* force back-references to respect limit of 1<<wLog, even for dictionary */
|
84
|
-
ZSTD_compressionStage_e stage;
|
85
|
-
U32 dictID;
|
86
|
-
int compressionLevel;
|
87
|
-
ZSTD_parameters requestedParams;
|
88
|
-
ZSTD_parameters appliedParams;
|
89
|
-
void* workSpace;
|
90
|
-
size_t workSpaceSize;
|
91
|
-
size_t blockSize;
|
92
|
-
U64 pledgedSrcSizePlusOne; /* this way, 0 (default) == unknown */
|
93
|
-
U64 consumedSrcSize;
|
94
|
-
XXH64_state_t xxhState;
|
95
|
-
ZSTD_customMem customMem;
|
96
|
-
size_t staticSize;
|
97
|
-
|
98
|
-
seqStore_t seqStore; /* sequences storage ptrs */
|
99
|
-
optState_t optState;
|
100
|
-
U32* hashTable;
|
101
|
-
U32* hashTable3;
|
102
|
-
U32* chainTable;
|
103
|
-
ZSTD_entropyCTables_t* entropy;
|
104
|
-
|
105
|
-
/* streaming */
|
106
|
-
char* inBuff;
|
107
|
-
size_t inBuffSize;
|
108
|
-
size_t inToCompress;
|
109
|
-
size_t inBuffPos;
|
110
|
-
size_t inBuffTarget;
|
111
|
-
char* outBuff;
|
112
|
-
size_t outBuffSize;
|
113
|
-
size_t outBuffContentSize;
|
114
|
-
size_t outBuffFlushedSize;
|
115
|
-
ZSTD_cStreamStage streamStage;
|
116
|
-
U32 frameEnded;
|
117
|
-
|
118
|
-
/* Dictionary */
|
119
|
-
ZSTD_dictMode_e dictMode; /* select restricting dictionary to "rawContent" or "fullDict" only */
|
120
|
-
U32 dictContentByRef;
|
121
|
-
ZSTD_CDict* cdictLocal;
|
122
|
-
const ZSTD_CDict* cdict;
|
123
|
-
const void* prefix;
|
124
|
-
size_t prefixSize;
|
125
|
-
|
126
|
-
/* Multi-threading */
|
127
|
-
U32 nbThreads;
|
128
|
-
ZSTDMT_CCtx* mtctx;
|
129
|
-
};
|
130
|
-
|
131
|
-
|
132
66
|
ZSTD_CCtx* ZSTD_createCCtx(void)
|
133
67
|
{
|
134
68
|
return ZSTD_createCCtx_advanced(ZSTD_defaultCMem);
|
@@ -143,7 +77,7 @@ ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem)
|
|
143
77
|
cctx = (ZSTD_CCtx*) ZSTD_calloc(sizeof(ZSTD_CCtx), customMem);
|
144
78
|
if (!cctx) return NULL;
|
145
79
|
cctx->customMem = customMem;
|
146
|
-
cctx->compressionLevel = ZSTD_CLEVEL_DEFAULT;
|
80
|
+
cctx->requestedParams.compressionLevel = ZSTD_CLEVEL_DEFAULT;
|
147
81
|
ZSTD_STATIC_ASSERT(zcss_init==0);
|
148
82
|
ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN==(0ULL - 1));
|
149
83
|
return cctx;
|
@@ -151,7 +85,7 @@ ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem)
|
|
151
85
|
|
152
86
|
ZSTD_CCtx* ZSTD_initStaticCCtx(void *workspace, size_t workspaceSize)
|
153
87
|
{
|
154
|
-
ZSTD_CCtx* cctx = (ZSTD_CCtx*) workspace;
|
88
|
+
ZSTD_CCtx* const cctx = (ZSTD_CCtx*) workspace;
|
155
89
|
if (workspaceSize <= sizeof(ZSTD_CCtx)) return NULL; /* minimum size */
|
156
90
|
if ((size_t)workspace & 7) return NULL; /* must be 8-aligned */
|
157
91
|
memset(workspace, 0, workspaceSize); /* may be a bit generous, could memset be smaller ? */
|
@@ -161,7 +95,7 @@ ZSTD_CCtx* ZSTD_initStaticCCtx(void *workspace, size_t workspaceSize)
|
|
161
95
|
|
162
96
|
/* entropy space (never moves) */
|
163
97
|
if (cctx->workSpaceSize < sizeof(ZSTD_entropyCTables_t)) return NULL;
|
164
|
-
assert(((size_t)cctx->workSpace &
|
98
|
+
assert(((size_t)cctx->workSpace & (sizeof(void*)-1)) == 0); /* ensure correct alignment */
|
165
99
|
cctx->entropy = (ZSTD_entropyCTables_t*)cctx->workSpace;
|
166
100
|
|
167
101
|
return cctx;
|
@@ -175,23 +109,36 @@ size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
|
|
175
109
|
cctx->workSpace = NULL;
|
176
110
|
ZSTD_freeCDict(cctx->cdictLocal);
|
177
111
|
cctx->cdictLocal = NULL;
|
112
|
+
#ifdef ZSTD_MULTITHREAD
|
178
113
|
ZSTDMT_freeCCtx(cctx->mtctx);
|
179
114
|
cctx->mtctx = NULL;
|
115
|
+
#endif
|
180
116
|
ZSTD_free(cctx, cctx->customMem);
|
181
117
|
return 0; /* reserved as a potential error code in the future */
|
182
118
|
}
|
183
119
|
|
120
|
+
|
121
|
+
static size_t ZSTD_sizeof_mtctx(const ZSTD_CCtx* cctx)
|
122
|
+
{
|
123
|
+
#ifdef ZSTD_MULTITHREAD
|
124
|
+
return ZSTDMT_sizeof_CCtx(cctx->mtctx);
|
125
|
+
#else
|
126
|
+
(void) cctx;
|
127
|
+
return 0;
|
128
|
+
#endif
|
129
|
+
}
|
130
|
+
|
131
|
+
|
184
132
|
size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx)
|
185
133
|
{
|
186
134
|
if (cctx==NULL) return 0; /* support sizeof on NULL */
|
187
|
-
DEBUGLOG(
|
188
|
-
DEBUGLOG(
|
189
|
-
DEBUGLOG(
|
190
|
-
DEBUGLOG(
|
135
|
+
DEBUGLOG(3, "sizeof(*cctx) : %u", (U32)sizeof(*cctx));
|
136
|
+
DEBUGLOG(3, "workSpaceSize (including streaming buffers): %u", (U32)cctx->workSpaceSize);
|
137
|
+
DEBUGLOG(3, "inner cdict : %u", (U32)ZSTD_sizeof_CDict(cctx->cdictLocal));
|
138
|
+
DEBUGLOG(3, "inner MTCTX : %u", (U32)ZSTD_sizeof_mtctx(cctx));
|
191
139
|
return sizeof(*cctx) + cctx->workSpaceSize
|
192
140
|
+ ZSTD_sizeof_CDict(cctx->cdictLocal)
|
193
|
-
+ cctx
|
194
|
-
+ ZSTDMT_sizeof_CCtx(cctx->mtctx);
|
141
|
+
+ ZSTD_sizeof_mtctx(cctx);
|
195
142
|
}
|
196
143
|
|
197
144
|
size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs)
|
@@ -202,29 +149,99 @@ size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs)
|
|
202
149
|
/* private API call, for dictBuilder only */
|
203
150
|
const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx) { return &(ctx->seqStore); }
|
204
151
|
|
205
|
-
|
152
|
+
#define ZSTD_CLEVEL_CUSTOM 999
|
206
153
|
|
207
|
-
|
208
|
-
|
154
|
+
static ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
|
155
|
+
ZSTD_CCtx_params params, U64 srcSizeHint, size_t dictSize)
|
209
156
|
{
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
ZSTD_STATIC_ASSERT(ZSTD_dm_auto==0);
|
214
|
-
ZSTD_STATIC_ASSERT(ZSTD_dm_rawContent==1);
|
215
|
-
case ZSTD_p_forceRawDict : cctx->dictMode = (ZSTD_dictMode_e)(value>0); return 0;
|
216
|
-
default: return ERROR(parameter_unsupported);
|
217
|
-
}
|
157
|
+
return (params.compressionLevel == ZSTD_CLEVEL_CUSTOM ?
|
158
|
+
params.cParams :
|
159
|
+
ZSTD_getCParams(params.compressionLevel, srcSizeHint, dictSize));
|
218
160
|
}
|
219
161
|
|
162
|
+
static void ZSTD_cLevelToCCtxParams_srcSize(ZSTD_CCtx_params* params, U64 srcSize)
|
163
|
+
{
|
164
|
+
params->cParams = ZSTD_getCParamsFromCCtxParams(*params, srcSize, 0);
|
165
|
+
params->compressionLevel = ZSTD_CLEVEL_CUSTOM;
|
166
|
+
}
|
220
167
|
|
221
|
-
#define ZSTD_CLEVEL_CUSTOM 999
|
222
168
|
static void ZSTD_cLevelToCParams(ZSTD_CCtx* cctx)
|
223
169
|
{
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
170
|
+
ZSTD_cLevelToCCtxParams_srcSize(
|
171
|
+
&cctx->requestedParams, cctx->pledgedSrcSizePlusOne-1);
|
172
|
+
}
|
173
|
+
|
174
|
+
static void ZSTD_cLevelToCCtxParams(ZSTD_CCtx_params* params)
|
175
|
+
{
|
176
|
+
ZSTD_cLevelToCCtxParams_srcSize(params, 0);
|
177
|
+
}
|
178
|
+
|
179
|
+
static ZSTD_CCtx_params ZSTD_makeCCtxParamsFromCParams(
|
180
|
+
ZSTD_compressionParameters cParams)
|
181
|
+
{
|
182
|
+
ZSTD_CCtx_params cctxParams;
|
183
|
+
memset(&cctxParams, 0, sizeof(cctxParams));
|
184
|
+
cctxParams.cParams = cParams;
|
185
|
+
cctxParams.compressionLevel = ZSTD_CLEVEL_CUSTOM;
|
186
|
+
return cctxParams;
|
187
|
+
}
|
188
|
+
|
189
|
+
static ZSTD_CCtx_params* ZSTD_createCCtxParams_advanced(
|
190
|
+
ZSTD_customMem customMem)
|
191
|
+
{
|
192
|
+
ZSTD_CCtx_params* params;
|
193
|
+
if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
|
194
|
+
params = (ZSTD_CCtx_params*)ZSTD_calloc(
|
195
|
+
sizeof(ZSTD_CCtx_params), customMem);
|
196
|
+
if (!params) { return NULL; }
|
197
|
+
params->customMem = customMem;
|
198
|
+
params->compressionLevel = ZSTD_CLEVEL_DEFAULT;
|
199
|
+
return params;
|
200
|
+
}
|
201
|
+
|
202
|
+
ZSTD_CCtx_params* ZSTD_createCCtxParams(void)
|
203
|
+
{
|
204
|
+
return ZSTD_createCCtxParams_advanced(ZSTD_defaultCMem);
|
205
|
+
}
|
206
|
+
|
207
|
+
size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params)
|
208
|
+
{
|
209
|
+
if (params == NULL) { return 0; }
|
210
|
+
ZSTD_free(params, params->customMem);
|
211
|
+
return 0;
|
212
|
+
}
|
213
|
+
|
214
|
+
size_t ZSTD_resetCCtxParams(ZSTD_CCtx_params* params)
|
215
|
+
{
|
216
|
+
return ZSTD_initCCtxParams(params, ZSTD_CLEVEL_DEFAULT);
|
217
|
+
}
|
218
|
+
|
219
|
+
size_t ZSTD_initCCtxParams(ZSTD_CCtx_params* cctxParams, int compressionLevel) {
|
220
|
+
if (!cctxParams) { return ERROR(GENERIC); }
|
221
|
+
memset(cctxParams, 0, sizeof(*cctxParams));
|
222
|
+
cctxParams->compressionLevel = compressionLevel;
|
223
|
+
return 0;
|
224
|
+
}
|
225
|
+
|
226
|
+
size_t ZSTD_initCCtxParams_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params)
|
227
|
+
{
|
228
|
+
if (!cctxParams) { return ERROR(GENERIC); }
|
229
|
+
CHECK_F( ZSTD_checkCParams(params.cParams) );
|
230
|
+
memset(cctxParams, 0, sizeof(*cctxParams));
|
231
|
+
cctxParams->cParams = params.cParams;
|
232
|
+
cctxParams->fParams = params.fParams;
|
233
|
+
cctxParams->compressionLevel = ZSTD_CLEVEL_CUSTOM;
|
234
|
+
return 0;
|
235
|
+
}
|
236
|
+
|
237
|
+
static ZSTD_CCtx_params ZSTD_assignParamsToCCtxParams(
|
238
|
+
ZSTD_CCtx_params cctxParams, ZSTD_parameters params)
|
239
|
+
{
|
240
|
+
ZSTD_CCtx_params ret = cctxParams;
|
241
|
+
ret.cParams = params.cParams;
|
242
|
+
ret.fParams = params.fParams;
|
243
|
+
ret.compressionLevel = ZSTD_CLEVEL_CUSTOM;
|
244
|
+
return ret;
|
228
245
|
}
|
229
246
|
|
230
247
|
#define CLAMPCHECK(val,min,max) { \
|
@@ -238,167 +255,285 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, unsigned v
|
|
238
255
|
|
239
256
|
switch(param)
|
240
257
|
{
|
241
|
-
case
|
242
|
-
|
258
|
+
case ZSTD_p_format :
|
259
|
+
return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
|
260
|
+
|
261
|
+
case ZSTD_p_compressionLevel:
|
243
262
|
if (value == 0) return 0; /* special value : 0 means "don't change anything" */
|
244
263
|
if (cctx->cdict) return ERROR(stage_wrong);
|
245
|
-
cctx->
|
246
|
-
|
264
|
+
return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
|
265
|
+
|
266
|
+
case ZSTD_p_windowLog:
|
267
|
+
case ZSTD_p_hashLog:
|
268
|
+
case ZSTD_p_chainLog:
|
269
|
+
case ZSTD_p_searchLog:
|
270
|
+
case ZSTD_p_minMatch:
|
271
|
+
case ZSTD_p_targetLength:
|
272
|
+
case ZSTD_p_compressionStrategy:
|
273
|
+
if (value == 0) return 0; /* special value : 0 means "don't change anything" */
|
274
|
+
if (cctx->cdict) return ERROR(stage_wrong);
|
275
|
+
ZSTD_cLevelToCParams(cctx); /* Can optimize if srcSize is known */
|
276
|
+
return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
|
247
277
|
|
248
|
-
case
|
249
|
-
|
250
|
-
|
278
|
+
case ZSTD_p_contentSizeFlag:
|
279
|
+
case ZSTD_p_checksumFlag:
|
280
|
+
case ZSTD_p_dictIDFlag:
|
281
|
+
return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
|
282
|
+
|
283
|
+
case ZSTD_p_forceMaxWindow : /* Force back-references to remain < windowSize,
|
284
|
+
* even when referencing into Dictionary content
|
285
|
+
* default : 0 when using a CDict, 1 when using a Prefix */
|
286
|
+
cctx->loadedDictEnd = 0;
|
287
|
+
return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
|
288
|
+
|
289
|
+
case ZSTD_p_nbThreads:
|
290
|
+
if (value==0) return 0;
|
291
|
+
DEBUGLOG(5, " setting nbThreads : %u", value);
|
292
|
+
if (value > 1 && cctx->staticSize) {
|
293
|
+
return ERROR(parameter_unsupported); /* MT not compatible with static alloc */
|
294
|
+
}
|
295
|
+
return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
|
296
|
+
|
297
|
+
case ZSTD_p_jobSize:
|
298
|
+
return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
|
299
|
+
|
300
|
+
case ZSTD_p_overlapSizeLog:
|
301
|
+
DEBUGLOG(5, " setting overlap with nbThreads == %u", cctx->requestedParams.nbThreads);
|
302
|
+
return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
|
303
|
+
|
304
|
+
case ZSTD_p_enableLongDistanceMatching:
|
305
|
+
if (cctx->cdict) return ERROR(stage_wrong);
|
306
|
+
if (value != 0) {
|
307
|
+
ZSTD_cLevelToCParams(cctx);
|
308
|
+
}
|
309
|
+
return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
|
310
|
+
|
311
|
+
case ZSTD_p_ldmHashLog:
|
312
|
+
case ZSTD_p_ldmMinMatch:
|
251
313
|
if (value == 0) return 0; /* special value : 0 means "don't change anything" */
|
252
314
|
if (cctx->cdict) return ERROR(stage_wrong);
|
315
|
+
return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
|
316
|
+
|
317
|
+
case ZSTD_p_ldmBucketSizeLog:
|
318
|
+
case ZSTD_p_ldmHashEveryLog:
|
319
|
+
if (cctx->cdict) return ERROR(stage_wrong);
|
320
|
+
return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
|
321
|
+
|
322
|
+
default: return ERROR(parameter_unsupported);
|
323
|
+
}
|
324
|
+
}
|
325
|
+
|
326
|
+
size_t ZSTD_CCtxParam_setParameter(
|
327
|
+
ZSTD_CCtx_params* params, ZSTD_cParameter param, unsigned value)
|
328
|
+
{
|
329
|
+
switch(param)
|
330
|
+
{
|
331
|
+
case ZSTD_p_format :
|
332
|
+
if (value > (unsigned)ZSTD_f_zstd1_magicless)
|
333
|
+
return ERROR(parameter_unsupported);
|
334
|
+
params->format = (ZSTD_format_e)value;
|
335
|
+
return 0;
|
336
|
+
|
337
|
+
case ZSTD_p_compressionLevel :
|
338
|
+
if ((int)value > ZSTD_maxCLevel()) value = ZSTD_maxCLevel();
|
339
|
+
if (value == 0) return 0;
|
340
|
+
params->compressionLevel = value;
|
341
|
+
return 0;
|
342
|
+
|
343
|
+
case ZSTD_p_windowLog :
|
344
|
+
if (value == 0) return 0;
|
253
345
|
CLAMPCHECK(value, ZSTD_WINDOWLOG_MIN, ZSTD_WINDOWLOG_MAX);
|
254
|
-
|
255
|
-
|
346
|
+
ZSTD_cLevelToCCtxParams(params);
|
347
|
+
params->cParams.windowLog = value;
|
256
348
|
return 0;
|
257
349
|
|
258
350
|
case ZSTD_p_hashLog :
|
259
|
-
if (value == 0) return 0;
|
260
|
-
if (cctx->cdict) return ERROR(stage_wrong);
|
351
|
+
if (value == 0) return 0;
|
261
352
|
CLAMPCHECK(value, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
|
262
|
-
|
263
|
-
|
353
|
+
ZSTD_cLevelToCCtxParams(params);
|
354
|
+
params->cParams.hashLog = value;
|
264
355
|
return 0;
|
265
356
|
|
266
357
|
case ZSTD_p_chainLog :
|
267
|
-
if (value == 0) return 0;
|
268
|
-
if (cctx->cdict) return ERROR(stage_wrong);
|
358
|
+
if (value == 0) return 0;
|
269
359
|
CLAMPCHECK(value, ZSTD_CHAINLOG_MIN, ZSTD_CHAINLOG_MAX);
|
270
|
-
|
271
|
-
|
360
|
+
ZSTD_cLevelToCCtxParams(params);
|
361
|
+
params->cParams.chainLog = value;
|
272
362
|
return 0;
|
273
363
|
|
274
364
|
case ZSTD_p_searchLog :
|
275
|
-
if (value == 0) return 0;
|
276
|
-
if (cctx->cdict) return ERROR(stage_wrong);
|
365
|
+
if (value == 0) return 0;
|
277
366
|
CLAMPCHECK(value, ZSTD_SEARCHLOG_MIN, ZSTD_SEARCHLOG_MAX);
|
278
|
-
|
279
|
-
|
367
|
+
ZSTD_cLevelToCCtxParams(params);
|
368
|
+
params->cParams.searchLog = value;
|
280
369
|
return 0;
|
281
370
|
|
282
371
|
case ZSTD_p_minMatch :
|
283
|
-
if (value == 0) return 0;
|
284
|
-
if (cctx->cdict) return ERROR(stage_wrong);
|
372
|
+
if (value == 0) return 0;
|
285
373
|
CLAMPCHECK(value, ZSTD_SEARCHLENGTH_MIN, ZSTD_SEARCHLENGTH_MAX);
|
286
|
-
|
287
|
-
|
374
|
+
ZSTD_cLevelToCCtxParams(params);
|
375
|
+
params->cParams.searchLength = value;
|
288
376
|
return 0;
|
289
377
|
|
290
378
|
case ZSTD_p_targetLength :
|
291
|
-
if (value == 0) return 0;
|
292
|
-
if (cctx->cdict) return ERROR(stage_wrong);
|
379
|
+
if (value == 0) return 0;
|
293
380
|
CLAMPCHECK(value, ZSTD_TARGETLENGTH_MIN, ZSTD_TARGETLENGTH_MAX);
|
294
|
-
|
295
|
-
|
381
|
+
ZSTD_cLevelToCCtxParams(params);
|
382
|
+
params->cParams.targetLength = value;
|
296
383
|
return 0;
|
297
384
|
|
298
385
|
case ZSTD_p_compressionStrategy :
|
299
|
-
if (value == 0) return 0;
|
300
|
-
if (cctx->cdict) return ERROR(stage_wrong);
|
386
|
+
if (value == 0) return 0;
|
301
387
|
CLAMPCHECK(value, (unsigned)ZSTD_fast, (unsigned)ZSTD_btultra);
|
302
|
-
|
303
|
-
|
388
|
+
ZSTD_cLevelToCCtxParams(params);
|
389
|
+
params->cParams.strategy = (ZSTD_strategy)value;
|
304
390
|
return 0;
|
305
391
|
|
306
392
|
case ZSTD_p_contentSizeFlag :
|
307
|
-
DEBUGLOG(5, "set content size flag = %u", (value>0));
|
308
393
|
/* Content size written in frame header _when known_ (default:1) */
|
309
|
-
|
394
|
+
DEBUGLOG(5, "set content size flag = %u", (value>0));
|
395
|
+
params->fParams.contentSizeFlag = value > 0;
|
310
396
|
return 0;
|
311
397
|
|
312
398
|
case ZSTD_p_checksumFlag :
|
313
399
|
/* A 32-bits content checksum will be calculated and written at end of frame (default:0) */
|
314
|
-
|
400
|
+
params->fParams.checksumFlag = value > 0;
|
315
401
|
return 0;
|
316
402
|
|
317
403
|
case ZSTD_p_dictIDFlag : /* When applicable, dictionary's dictID is provided in frame header (default:1) */
|
318
404
|
DEBUGLOG(5, "set dictIDFlag = %u", (value>0));
|
319
|
-
|
405
|
+
params->fParams.noDictIDFlag = (value == 0);
|
320
406
|
return 0;
|
321
407
|
|
322
|
-
|
323
|
-
|
324
|
-
if (cctx->cdict) return ERROR(stage_wrong); /* must be set before loading */
|
325
|
-
/* restrict dictionary mode, to "rawContent" or "fullDict" only */
|
326
|
-
ZSTD_STATIC_ASSERT((U32)ZSTD_dm_fullDict > (U32)ZSTD_dm_rawContent);
|
327
|
-
if (value > (unsigned)ZSTD_dm_fullDict)
|
328
|
-
return ERROR(parameter_outOfBound);
|
329
|
-
cctx->dictMode = (ZSTD_dictMode_e)value;
|
408
|
+
case ZSTD_p_forceMaxWindow :
|
409
|
+
params->forceWindow = value > 0;
|
330
410
|
return 0;
|
331
411
|
|
332
|
-
case
|
333
|
-
if (
|
334
|
-
|
335
|
-
|
412
|
+
case ZSTD_p_nbThreads :
|
413
|
+
if (value == 0) return 0;
|
414
|
+
#ifndef ZSTD_MULTITHREAD
|
415
|
+
if (value > 1) return ERROR(parameter_unsupported);
|
336
416
|
return 0;
|
417
|
+
#else
|
418
|
+
return ZSTDMT_initializeCCtxParameters(params, value);
|
419
|
+
#endif
|
337
420
|
|
338
|
-
case
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
return
|
421
|
+
case ZSTD_p_jobSize :
|
422
|
+
#ifndef ZSTD_MULTITHREAD
|
423
|
+
return ERROR(parameter_unsupported);
|
424
|
+
#else
|
425
|
+
if (params->nbThreads <= 1) return ERROR(parameter_unsupported);
|
426
|
+
return ZSTDMT_CCtxParam_setMTCtxParameter(params, ZSTDMT_p_sectionSize, value);
|
427
|
+
#endif
|
344
428
|
|
345
|
-
case
|
346
|
-
if (value==0) return 0;
|
347
|
-
DEBUGLOG(5, " setting nbThreads : %u", value);
|
429
|
+
case ZSTD_p_overlapSizeLog :
|
348
430
|
#ifndef ZSTD_MULTITHREAD
|
349
|
-
|
431
|
+
return ERROR(parameter_unsupported);
|
432
|
+
#else
|
433
|
+
if (params->nbThreads <= 1) return ERROR(parameter_unsupported);
|
434
|
+
return ZSTDMT_CCtxParam_setMTCtxParameter(params, ZSTDMT_p_overlapSectionLog, value);
|
350
435
|
#endif
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
cctx->mtctx = ZSTDMT_createCCtx_advanced(value, cctx->customMem);
|
357
|
-
if (cctx->mtctx == NULL) return ERROR(memory_allocation);
|
436
|
+
|
437
|
+
case ZSTD_p_enableLongDistanceMatching :
|
438
|
+
if (value != 0) {
|
439
|
+
ZSTD_cLevelToCCtxParams(params);
|
440
|
+
params->cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG;
|
358
441
|
}
|
359
|
-
|
442
|
+
return ZSTD_ldm_initializeParameters(¶ms->ldmParams, value);
|
443
|
+
|
444
|
+
case ZSTD_p_ldmHashLog :
|
445
|
+
if (value == 0) return 0;
|
446
|
+
CLAMPCHECK(value, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
|
447
|
+
params->ldmParams.hashLog = value;
|
360
448
|
return 0;
|
361
449
|
|
362
|
-
case
|
363
|
-
if (
|
364
|
-
|
365
|
-
|
450
|
+
case ZSTD_p_ldmMinMatch :
|
451
|
+
if (value == 0) return 0;
|
452
|
+
CLAMPCHECK(value, ZSTD_LDM_MINMATCH_MIN, ZSTD_LDM_MINMATCH_MAX);
|
453
|
+
params->ldmParams.minMatchLength = value;
|
454
|
+
return 0;
|
366
455
|
|
367
|
-
case
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
456
|
+
case ZSTD_p_ldmBucketSizeLog :
|
457
|
+
if (value > ZSTD_LDM_BUCKETSIZELOG_MAX) {
|
458
|
+
return ERROR(parameter_outOfBound);
|
459
|
+
}
|
460
|
+
params->ldmParams.bucketSizeLog = value;
|
461
|
+
return 0;
|
462
|
+
|
463
|
+
case ZSTD_p_ldmHashEveryLog :
|
464
|
+
if (value > ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN) {
|
465
|
+
return ERROR(parameter_outOfBound);
|
466
|
+
}
|
467
|
+
params->ldmParams.hashEveryLog = value;
|
468
|
+
return 0;
|
372
469
|
|
373
470
|
default: return ERROR(parameter_unsupported);
|
374
471
|
}
|
375
472
|
}
|
376
473
|
|
474
|
+
/**
|
475
|
+
* This function should be updated whenever ZSTD_CCtx_params is updated.
|
476
|
+
* Parameters are copied manually before the dictionary is loaded.
|
477
|
+
* The multithreading parameters jobSize and overlapSizeLog are set only if
|
478
|
+
* nbThreads > 1.
|
479
|
+
*
|
480
|
+
* Pledged srcSize is treated as unknown.
|
481
|
+
*/
|
482
|
+
size_t ZSTD_CCtx_setParametersUsingCCtxParams(
|
483
|
+
ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params)
|
484
|
+
{
|
485
|
+
if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
|
486
|
+
if (cctx->cdict) return ERROR(stage_wrong);
|
487
|
+
|
488
|
+
/* Assume the compression and frame parameters are validated */
|
489
|
+
cctx->requestedParams.cParams = params->cParams;
|
490
|
+
cctx->requestedParams.fParams = params->fParams;
|
491
|
+
cctx->requestedParams.compressionLevel = params->compressionLevel;
|
492
|
+
|
493
|
+
/* Set force window explicitly since it sets cctx->loadedDictEnd */
|
494
|
+
CHECK_F( ZSTD_CCtx_setParameter(
|
495
|
+
cctx, ZSTD_p_forceMaxWindow, params->forceWindow) );
|
496
|
+
|
497
|
+
/* Set multithreading parameters explicitly */
|
498
|
+
CHECK_F( ZSTD_CCtx_setParameter(cctx, ZSTD_p_nbThreads, params->nbThreads) );
|
499
|
+
if (params->nbThreads > 1) {
|
500
|
+
CHECK_F( ZSTD_CCtx_setParameter(cctx, ZSTD_p_jobSize, params->jobSize) );
|
501
|
+
CHECK_F( ZSTD_CCtx_setParameter(
|
502
|
+
cctx, ZSTD_p_overlapSizeLog, params->overlapSizeLog) );
|
503
|
+
}
|
504
|
+
|
505
|
+
/* Copy long distance matching parameters */
|
506
|
+
cctx->requestedParams.ldmParams = params->ldmParams;
|
507
|
+
|
508
|
+
/* customMem is used only for create/free params and can be ignored */
|
509
|
+
return 0;
|
510
|
+
}
|
511
|
+
|
377
512
|
ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize)
|
378
513
|
{
|
379
|
-
DEBUGLOG(
|
514
|
+
DEBUGLOG(4, " setting pledgedSrcSize to %u", (U32)pledgedSrcSize);
|
380
515
|
if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
|
381
516
|
cctx->pledgedSrcSizePlusOne = pledgedSrcSize+1;
|
382
517
|
return 0;
|
383
518
|
}
|
384
519
|
|
385
|
-
|
520
|
+
size_t ZSTD_CCtx_loadDictionary_advanced(
|
521
|
+
ZSTD_CCtx* cctx, const void* dict, size_t dictSize,
|
522
|
+
ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictMode_e dictMode)
|
386
523
|
{
|
387
524
|
if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
|
388
525
|
if (cctx->staticSize) return ERROR(memory_allocation); /* no malloc for static CCtx */
|
389
|
-
DEBUGLOG(
|
526
|
+
DEBUGLOG(4, "load dictionary of size %u", (U32)dictSize);
|
390
527
|
ZSTD_freeCDict(cctx->cdictLocal); /* in case one already exists */
|
391
528
|
if (dict==NULL || dictSize==0) { /* no dictionary mode */
|
392
529
|
cctx->cdictLocal = NULL;
|
393
530
|
cctx->cdict = NULL;
|
394
531
|
} else {
|
395
532
|
ZSTD_compressionParameters const cParams =
|
396
|
-
cctx->
|
397
|
-
cctx->requestedParams.cParams :
|
398
|
-
ZSTD_getCParams(cctx->compressionLevel, 0, dictSize);
|
533
|
+
ZSTD_getCParamsFromCCtxParams(cctx->requestedParams, 0, dictSize);
|
399
534
|
cctx->cdictLocal = ZSTD_createCDict_advanced(
|
400
535
|
dict, dictSize,
|
401
|
-
|
536
|
+
dictLoadMethod, dictMode,
|
402
537
|
cParams, cctx->customMem);
|
403
538
|
cctx->cdict = cctx->cdictLocal;
|
404
539
|
if (cctx->cdictLocal == NULL)
|
@@ -407,21 +542,41 @@ ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, s
|
|
407
542
|
return 0;
|
408
543
|
}
|
409
544
|
|
545
|
+
ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary_byReference(
|
546
|
+
ZSTD_CCtx* cctx, const void* dict, size_t dictSize)
|
547
|
+
{
|
548
|
+
return ZSTD_CCtx_loadDictionary_advanced(
|
549
|
+
cctx, dict, dictSize, ZSTD_dlm_byRef, ZSTD_dm_auto);
|
550
|
+
}
|
551
|
+
|
552
|
+
ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize)
|
553
|
+
{
|
554
|
+
return ZSTD_CCtx_loadDictionary_advanced(
|
555
|
+
cctx, dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dm_auto);
|
556
|
+
}
|
557
|
+
|
558
|
+
|
410
559
|
size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict)
|
411
560
|
{
|
412
561
|
if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
|
413
562
|
cctx->cdict = cdict;
|
414
|
-
cctx->
|
415
|
-
cctx->prefixSize = 0;
|
563
|
+
memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); /* exclusive */
|
416
564
|
return 0;
|
417
565
|
}
|
418
566
|
|
419
567
|
size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize)
|
568
|
+
{
|
569
|
+
return ZSTD_CCtx_refPrefix_advanced(cctx, prefix, prefixSize, ZSTD_dm_rawContent);
|
570
|
+
}
|
571
|
+
|
572
|
+
size_t ZSTD_CCtx_refPrefix_advanced(
|
573
|
+
ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictMode_e dictMode)
|
420
574
|
{
|
421
575
|
if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
|
422
576
|
cctx->cdict = NULL; /* prefix discards any prior cdict */
|
423
|
-
cctx->
|
424
|
-
cctx->
|
577
|
+
cctx->prefixDict.dict = prefix;
|
578
|
+
cctx->prefixDict.dictSize = prefixSize;
|
579
|
+
cctx->prefixDict.dictMode = dictMode;
|
425
580
|
return 0;
|
426
581
|
}
|
427
582
|
|
@@ -484,28 +639,37 @@ static U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat)
|
|
484
639
|
|
485
640
|
/** ZSTD_adjustCParams_internal() :
|
486
641
|
optimize `cPar` for a given input (`srcSize` and `dictSize`).
|
487
|
-
mostly downsizing to reduce memory consumption and initialization.
|
488
|
-
Both `srcSize` and `dictSize` are optional (use 0 if unknown)
|
489
|
-
|
490
|
-
Note : cPar is considered validated at this stage. Use ZSTD_checkParams() to ensure that. */
|
642
|
+
mostly downsizing to reduce memory consumption and initialization latency.
|
643
|
+
Both `srcSize` and `dictSize` are optional (use 0 if unknown).
|
644
|
+
Note : cPar is considered validated at this stage. Use ZSTD_checkCParams() to ensure that condition. */
|
491
645
|
ZSTD_compressionParameters ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize)
|
492
646
|
{
|
647
|
+
static const U64 minSrcSize = 513; /* (1<<9) + 1 */
|
648
|
+
static const U64 maxWindowResize = 1ULL << (ZSTD_WINDOWLOG_MAX-1);
|
493
649
|
assert(ZSTD_checkCParams(cPar)==0);
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
650
|
+
|
651
|
+
if (dictSize && (srcSize+1<2) /* srcSize unknown */ )
|
652
|
+
srcSize = minSrcSize; /* presumed small when there is a dictionary */
|
653
|
+
else if (srcSize == 0)
|
654
|
+
srcSize = ZSTD_CONTENTSIZE_UNKNOWN; /* 0 == unknown : presumed large */
|
655
|
+
|
656
|
+
/* resize windowLog if input is small enough, to use less memory */
|
657
|
+
if ( (srcSize < maxWindowResize)
|
658
|
+
&& (dictSize < maxWindowResize) ) {
|
659
|
+
U32 const tSize = (U32)(srcSize + dictSize);
|
660
|
+
static U32 const hashSizeMin = 1 << ZSTD_HASHLOG_MIN;
|
661
|
+
U32 const srcLog = (tSize < hashSizeMin) ? ZSTD_HASHLOG_MIN :
|
662
|
+
ZSTD_highbit32(tSize-1) + 1;
|
663
|
+
if (cPar.windowLog > srcLog) cPar.windowLog = srcLog;
|
664
|
+
}
|
503
665
|
if (cPar.hashLog > cPar.windowLog) cPar.hashLog = cPar.windowLog;
|
504
666
|
{ U32 const cycleLog = ZSTD_cycleLog(cPar.chainLog, cPar.strategy);
|
505
|
-
if (cycleLog > cPar.windowLog)
|
667
|
+
if (cycleLog > cPar.windowLog)
|
668
|
+
cPar.chainLog -= (cycleLog - cPar.windowLog);
|
506
669
|
}
|
507
670
|
|
508
|
-
if (cPar.windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN)
|
671
|
+
if (cPar.windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN)
|
672
|
+
cPar.windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN; /* required for frame header */
|
509
673
|
|
510
674
|
return cPar;
|
511
675
|
}
|
@@ -516,56 +680,81 @@ ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, u
|
|
516
680
|
return ZSTD_adjustCParams_internal(cPar, srcSize, dictSize);
|
517
681
|
}
|
518
682
|
|
519
|
-
|
520
|
-
size_t ZSTD_estimateCCtxSize_advanced(ZSTD_compressionParameters cParams)
|
683
|
+
size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params)
|
521
684
|
{
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
685
|
+
/* Estimate CCtx size is supported for single-threaded compression only. */
|
686
|
+
if (params->nbThreads > 1) { return ERROR(GENERIC); }
|
687
|
+
{ ZSTD_compressionParameters const cParams =
|
688
|
+
ZSTD_getCParamsFromCCtxParams(*params, 0, 0);
|
689
|
+
size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog);
|
690
|
+
U32 const divider = (cParams.searchLength==3) ? 3 : 4;
|
691
|
+
size_t const maxNbSeq = blockSize / divider;
|
692
|
+
size_t const tokenSpace = blockSize + 11*maxNbSeq;
|
693
|
+
size_t const chainSize =
|
694
|
+
(cParams.strategy == ZSTD_fast) ? 0 : ((size_t)1 << cParams.chainLog);
|
695
|
+
size_t const hSize = ((size_t)1) << cParams.hashLog;
|
696
|
+
U32 const hashLog3 = (cParams.searchLength>3) ?
|
697
|
+
0 : MIN(ZSTD_HASHLOG3_MAX, cParams.windowLog);
|
698
|
+
size_t const h3Size = ((size_t)1) << hashLog3;
|
699
|
+
size_t const entropySpace = sizeof(ZSTD_entropyCTables_t);
|
700
|
+
size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
|
701
|
+
|
702
|
+
size_t const optBudget =
|
703
|
+
((MaxML+1) + (MaxLL+1) + (MaxOff+1) + (1<<Litbits))*sizeof(U32)
|
704
|
+
+ (ZSTD_OPT_NUM+1)*(sizeof(ZSTD_match_t) + sizeof(ZSTD_optimal_t));
|
705
|
+
size_t const optSpace = ((cParams.strategy == ZSTD_btopt) || (cParams.strategy == ZSTD_btultra)) ? optBudget : 0;
|
526
706
|
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
size_t const h3Size = ((size_t)1) << hashLog3;
|
531
|
-
size_t const entropySpace = sizeof(ZSTD_entropyCTables_t);
|
532
|
-
size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
|
707
|
+
size_t const ldmSpace = params->ldmParams.enableLdm ?
|
708
|
+
ZSTD_ldm_getTableSize(params->ldmParams.hashLog,
|
709
|
+
params->ldmParams.bucketSizeLog) : 0;
|
533
710
|
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
711
|
+
size_t const neededSpace = entropySpace + tableSpace + tokenSpace +
|
712
|
+
optSpace + ldmSpace;
|
713
|
+
|
714
|
+
DEBUGLOG(5, "sizeof(ZSTD_CCtx) : %u", (U32)sizeof(ZSTD_CCtx));
|
715
|
+
DEBUGLOG(5, "estimate workSpace : %u", (U32)neededSpace);
|
716
|
+
return sizeof(ZSTD_CCtx) + neededSpace;
|
717
|
+
}
|
718
|
+
}
|
538
719
|
|
539
|
-
|
540
|
-
|
541
|
-
|
720
|
+
size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams)
|
721
|
+
{
|
722
|
+
ZSTD_CCtx_params const params = ZSTD_makeCCtxParamsFromCParams(cParams);
|
723
|
+
return ZSTD_estimateCCtxSize_usingCCtxParams(¶ms);
|
542
724
|
}
|
543
725
|
|
544
726
|
size_t ZSTD_estimateCCtxSize(int compressionLevel)
|
545
727
|
{
|
546
728
|
ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, 0, 0);
|
547
|
-
return
|
729
|
+
return ZSTD_estimateCCtxSize_usingCParams(cParams);
|
548
730
|
}
|
549
731
|
|
550
|
-
size_t
|
732
|
+
size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params)
|
551
733
|
{
|
552
|
-
|
553
|
-
size_t const
|
554
|
-
|
555
|
-
|
556
|
-
|
734
|
+
if (params->nbThreads > 1) { return ERROR(GENERIC); }
|
735
|
+
{ size_t const CCtxSize = ZSTD_estimateCCtxSize_usingCCtxParams(params);
|
736
|
+
size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << params->cParams.windowLog);
|
737
|
+
size_t const inBuffSize = ((size_t)1 << params->cParams.windowLog) + blockSize;
|
738
|
+
size_t const outBuffSize = ZSTD_compressBound(blockSize) + 1;
|
739
|
+
size_t const streamingSize = inBuffSize + outBuffSize;
|
740
|
+
|
741
|
+
return CCtxSize + streamingSize;
|
742
|
+
}
|
743
|
+
}
|
557
744
|
|
558
|
-
|
745
|
+
size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams)
|
746
|
+
{
|
747
|
+
ZSTD_CCtx_params const params = ZSTD_makeCCtxParamsFromCParams(cParams);
|
748
|
+
return ZSTD_estimateCStreamSize_usingCCtxParams(¶ms);
|
559
749
|
}
|
560
750
|
|
561
751
|
size_t ZSTD_estimateCStreamSize(int compressionLevel) {
|
562
752
|
ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, 0, 0);
|
563
|
-
return
|
753
|
+
return ZSTD_estimateCStreamSize_usingCParams(cParams);
|
564
754
|
}
|
565
755
|
|
566
|
-
|
567
|
-
|
568
|
-
ZSTD_compressionParameters cParams2)
|
756
|
+
static U32 ZSTD_equivalentCParams(ZSTD_compressionParameters cParams1,
|
757
|
+
ZSTD_compressionParameters cParams2)
|
569
758
|
{
|
570
759
|
U32 bslog1 = MIN(cParams1.windowLog, ZSTD_BLOCKSIZELOG_MAX);
|
571
760
|
U32 bslog2 = MIN(cParams2.windowLog, ZSTD_BLOCKSIZELOG_MAX);
|
@@ -576,18 +765,39 @@ static U32 ZSTD_equivalentParams(ZSTD_compressionParameters cParams1,
|
|
576
765
|
& ((cParams1.searchLength==3) == (cParams2.searchLength==3)); /* hashlog3 space */
|
577
766
|
}
|
578
767
|
|
768
|
+
/** The parameters are equivalent if ldm is not enabled in both sets or
|
769
|
+
* all the parameters are equivalent. */
|
770
|
+
static U32 ZSTD_equivalentLdmParams(ldmParams_t ldmParams1,
|
771
|
+
ldmParams_t ldmParams2)
|
772
|
+
{
|
773
|
+
return (!ldmParams1.enableLdm && !ldmParams2.enableLdm) ||
|
774
|
+
(ldmParams1.enableLdm == ldmParams2.enableLdm &&
|
775
|
+
ldmParams1.hashLog == ldmParams2.hashLog &&
|
776
|
+
ldmParams1.bucketSizeLog == ldmParams2.bucketSizeLog &&
|
777
|
+
ldmParams1.minMatchLength == ldmParams2.minMatchLength &&
|
778
|
+
ldmParams1.hashEveryLog == ldmParams2.hashEveryLog);
|
779
|
+
}
|
780
|
+
|
781
|
+
/** Equivalence for resetCCtx purposes */
|
782
|
+
static U32 ZSTD_equivalentParams(ZSTD_CCtx_params params1,
|
783
|
+
ZSTD_CCtx_params params2)
|
784
|
+
{
|
785
|
+
return ZSTD_equivalentCParams(params1.cParams, params2.cParams) &&
|
786
|
+
ZSTD_equivalentLdmParams(params1.ldmParams, params2.ldmParams);
|
787
|
+
}
|
788
|
+
|
579
789
|
/*! ZSTD_continueCCtx() :
|
580
790
|
* reuse CCtx without reset (note : requires no dictionary) */
|
581
|
-
static size_t ZSTD_continueCCtx(ZSTD_CCtx* cctx,
|
791
|
+
static size_t ZSTD_continueCCtx(ZSTD_CCtx* cctx, ZSTD_CCtx_params params, U64 pledgedSrcSize)
|
582
792
|
{
|
583
793
|
U32 const end = (U32)(cctx->nextSrc - cctx->base);
|
584
|
-
DEBUGLOG(
|
794
|
+
DEBUGLOG(4, "continue mode");
|
585
795
|
cctx->appliedParams = params;
|
586
796
|
cctx->pledgedSrcSizePlusOne = pledgedSrcSize+1;
|
587
797
|
cctx->consumedSrcSize = 0;
|
588
798
|
if (pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN)
|
589
799
|
cctx->appliedParams.fParams.contentSizeFlag = 0;
|
590
|
-
DEBUGLOG(
|
800
|
+
DEBUGLOG(4, "pledged content size : %u ; flag : %u",
|
591
801
|
(U32)pledgedSrcSize, cctx->appliedParams.fParams.contentSizeFlag);
|
592
802
|
cctx->lowLimit = end;
|
593
803
|
cctx->dictLimit = end;
|
@@ -607,15 +817,19 @@ typedef enum { ZSTDb_not_buffered, ZSTDb_buffered } ZSTD_buffered_policy_e;
|
|
607
817
|
/*! ZSTD_resetCCtx_internal() :
|
608
818
|
note : `params` are assumed fully validated at this stage */
|
609
819
|
static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
|
610
|
-
|
820
|
+
ZSTD_CCtx_params params, U64 pledgedSrcSize,
|
611
821
|
ZSTD_compResetPolicy_e const crp,
|
612
822
|
ZSTD_buffered_policy_e const zbuff)
|
613
823
|
{
|
824
|
+
DEBUGLOG(4, "ZSTD_resetCCtx_internal");
|
614
825
|
assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
|
826
|
+
DEBUGLOG(4, "pledgedSrcSize: %u", (U32)pledgedSrcSize);
|
615
827
|
|
616
828
|
if (crp == ZSTDcrp_continue) {
|
617
|
-
if (ZSTD_equivalentParams(params
|
618
|
-
DEBUGLOG(
|
829
|
+
if (ZSTD_equivalentParams(params, zc->appliedParams)) {
|
830
|
+
DEBUGLOG(4, "ZSTD_equivalentParams()==1");
|
831
|
+
assert(!(params.ldmParams.enableLdm &&
|
832
|
+
params.ldmParams.hashEveryLog == ZSTD_LDM_HASHEVERYLOG_NOTSET));
|
619
833
|
zc->entropy->hufCTable_repeatMode = HUF_repeat_none;
|
620
834
|
zc->entropy->offcode_repeatMode = FSE_repeat_none;
|
621
835
|
zc->entropy->matchlength_repeatMode = FSE_repeat_none;
|
@@ -623,12 +837,21 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
|
|
623
837
|
return ZSTD_continueCCtx(zc, params, pledgedSrcSize);
|
624
838
|
} }
|
625
839
|
|
840
|
+
if (params.ldmParams.enableLdm) {
|
841
|
+
/* Adjust long distance matching parameters */
|
842
|
+
ZSTD_ldm_adjustParameters(¶ms.ldmParams, params.cParams.windowLog);
|
843
|
+
assert(params.ldmParams.hashLog >= params.ldmParams.bucketSizeLog);
|
844
|
+
assert(params.ldmParams.hashEveryLog < 32);
|
845
|
+
zc->ldmState.hashPower =
|
846
|
+
ZSTD_ldm_getHashPower(params.ldmParams.minMatchLength);
|
847
|
+
}
|
848
|
+
|
626
849
|
{ size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << params.cParams.windowLog);
|
627
850
|
U32 const divider = (params.cParams.searchLength==3) ? 3 : 4;
|
628
851
|
size_t const maxNbSeq = blockSize / divider;
|
629
852
|
size_t const tokenSpace = blockSize + 11*maxNbSeq;
|
630
853
|
size_t const chainSize = (params.cParams.strategy == ZSTD_fast) ?
|
631
|
-
0 : (1 << params.cParams.chainLog);
|
854
|
+
0 : ((size_t)1 << params.cParams.chainLog);
|
632
855
|
size_t const hSize = ((size_t)1) << params.cParams.hashLog;
|
633
856
|
U32 const hashLog3 = (params.cParams.searchLength>3) ?
|
634
857
|
0 : MIN(ZSTD_HASHLOG3_MAX, params.cParams.windowLog);
|
@@ -646,10 +869,13 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
|
|
646
869
|
|| (params.cParams.strategy == ZSTD_btultra)) ?
|
647
870
|
optPotentialSpace : 0;
|
648
871
|
size_t const bufferSpace = buffInSize + buffOutSize;
|
649
|
-
size_t const
|
650
|
-
|
872
|
+
size_t const ldmSpace = params.ldmParams.enableLdm
|
873
|
+
? ZSTD_ldm_getTableSize(params.ldmParams.hashLog, params.ldmParams.bucketSizeLog)
|
874
|
+
: 0;
|
875
|
+
size_t const neededSpace = entropySpace + optSpace + ldmSpace +
|
876
|
+
tableSpace + tokenSpace + bufferSpace;
|
651
877
|
|
652
|
-
if (zc->workSpaceSize < neededSpace) { /* too small : resize
|
878
|
+
if (zc->workSpaceSize < neededSpace) { /* too small : resize */
|
653
879
|
DEBUGLOG(5, "Need to update workSpaceSize from %uK to %uK \n",
|
654
880
|
(unsigned)zc->workSpaceSize>>10,
|
655
881
|
(unsigned)neededSpace>>10);
|
@@ -714,6 +940,16 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
|
|
714
940
|
ptr = zc->optState.priceTable + ZSTD_OPT_NUM+1;
|
715
941
|
}
|
716
942
|
|
943
|
+
/* ldm hash table */
|
944
|
+
/* initialize bucketOffsets table later for pointer alignment */
|
945
|
+
if (params.ldmParams.enableLdm) {
|
946
|
+
size_t const ldmHSize = ((size_t)1) << params.ldmParams.hashLog;
|
947
|
+
memset(ptr, 0, ldmHSize * sizeof(ldmEntry_t));
|
948
|
+
assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */
|
949
|
+
zc->ldmState.hashTable = (ldmEntry_t*)ptr;
|
950
|
+
ptr = zc->ldmState.hashTable + ldmHSize;
|
951
|
+
}
|
952
|
+
|
717
953
|
/* table Space */
|
718
954
|
if (crp!=ZSTDcrp_noMemset) memset(ptr, 0, tableSpace); /* reset tables only */
|
719
955
|
assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */
|
@@ -731,6 +967,16 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
|
|
731
967
|
zc->seqStore.litStart = zc->seqStore.ofCode + maxNbSeq;
|
732
968
|
ptr = zc->seqStore.litStart + blockSize;
|
733
969
|
|
970
|
+
/* ldm bucketOffsets table */
|
971
|
+
if (params.ldmParams.enableLdm) {
|
972
|
+
size_t const ldmBucketSize =
|
973
|
+
((size_t)1) << (params.ldmParams.hashLog -
|
974
|
+
params.ldmParams.bucketSizeLog);
|
975
|
+
memset(ptr, 0, ldmBucketSize);
|
976
|
+
zc->ldmState.bucketOffsets = (BYTE*)ptr;
|
977
|
+
ptr = zc->ldmState.bucketOffsets + ldmBucketSize;
|
978
|
+
}
|
979
|
+
|
734
980
|
/* buffers */
|
735
981
|
zc->inBuffSize = buffInSize;
|
736
982
|
zc->inBuff = (char*)ptr;
|
@@ -753,6 +999,8 @@ void ZSTD_invalidateRepCodes(ZSTD_CCtx* cctx) {
|
|
753
999
|
|
754
1000
|
/*! ZSTD_copyCCtx_internal() :
|
755
1001
|
* Duplicate an existing context `srcCCtx` into another one `dstCCtx`.
|
1002
|
+
* The "context", in this case, refers to the hash and chain tables, entropy
|
1003
|
+
* tables, and dictionary offsets.
|
756
1004
|
* Only works during stage ZSTDcs_init (i.e. after creation, but before first call to ZSTD_compressContinue()).
|
757
1005
|
* pledgedSrcSize=0 means "empty" if fParams.contentSizeFlag=1
|
758
1006
|
* @return : 0, or an error code */
|
@@ -766,14 +1014,16 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
|
|
766
1014
|
if (srcCCtx->stage!=ZSTDcs_init) return ERROR(stage_wrong);
|
767
1015
|
|
768
1016
|
memcpy(&dstCCtx->customMem, &srcCCtx->customMem, sizeof(ZSTD_customMem));
|
769
|
-
{
|
1017
|
+
{ ZSTD_CCtx_params params = dstCCtx->requestedParams;
|
1018
|
+
/* Copy only compression parameters related to tables. */
|
1019
|
+
params.cParams = srcCCtx->appliedParams.cParams;
|
770
1020
|
params.fParams = fParams;
|
771
1021
|
ZSTD_resetCCtx_internal(dstCCtx, params, pledgedSrcSize,
|
772
1022
|
ZSTDcrp_noMemset, zbuff);
|
773
1023
|
}
|
774
1024
|
|
775
1025
|
/* copy tables */
|
776
|
-
{ size_t const chainSize = (srcCCtx->appliedParams.cParams.strategy == ZSTD_fast) ? 0 : (1 << srcCCtx->appliedParams.cParams.chainLog);
|
1026
|
+
{ size_t const chainSize = (srcCCtx->appliedParams.cParams.strategy == ZSTD_fast) ? 0 : ((size_t)1 << srcCCtx->appliedParams.cParams.chainLog);
|
777
1027
|
size_t const hSize = (size_t)1 << srcCCtx->appliedParams.cParams.hashLog;
|
778
1028
|
size_t const h3Size = (size_t)1 << srcCCtx->hashLog3;
|
779
1029
|
size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
|
@@ -826,18 +1076,36 @@ static void ZSTD_reduceTable (U32* const table, U32 const size, U32 const reduce
|
|
826
1076
|
}
|
827
1077
|
}
|
828
1078
|
|
1079
|
+
/*! ZSTD_ldm_reduceTable() :
|
1080
|
+
* reduce table indexes by `reducerValue` */
|
1081
|
+
static void ZSTD_ldm_reduceTable(ldmEntry_t* const table, U32 const size,
|
1082
|
+
U32 const reducerValue)
|
1083
|
+
{
|
1084
|
+
U32 u;
|
1085
|
+
for (u = 0; u < size; u++) {
|
1086
|
+
if (table[u].offset < reducerValue) table[u].offset = 0;
|
1087
|
+
else table[u].offset -= reducerValue;
|
1088
|
+
}
|
1089
|
+
}
|
1090
|
+
|
829
1091
|
/*! ZSTD_reduceIndex() :
|
830
1092
|
* rescale all indexes to avoid future overflow (indexes are U32) */
|
831
1093
|
static void ZSTD_reduceIndex (ZSTD_CCtx* zc, const U32 reducerValue)
|
832
1094
|
{
|
833
|
-
{ U32 const hSize = 1 << zc->appliedParams.cParams.hashLog;
|
1095
|
+
{ U32 const hSize = (U32)1 << zc->appliedParams.cParams.hashLog;
|
834
1096
|
ZSTD_reduceTable(zc->hashTable, hSize, reducerValue); }
|
835
1097
|
|
836
|
-
{ U32 const chainSize = (zc->appliedParams.cParams.strategy == ZSTD_fast) ? 0 : (1 << zc->appliedParams.cParams.chainLog);
|
1098
|
+
{ U32 const chainSize = (zc->appliedParams.cParams.strategy == ZSTD_fast) ? 0 : ((U32)1 << zc->appliedParams.cParams.chainLog);
|
837
1099
|
ZSTD_reduceTable(zc->chainTable, chainSize, reducerValue); }
|
838
1100
|
|
839
|
-
{ U32 const h3Size = (zc->hashLog3) ? 1 << zc->hashLog3 : 0;
|
1101
|
+
{ U32 const h3Size = (zc->hashLog3) ? (U32)1 << zc->hashLog3 : 0;
|
840
1102
|
ZSTD_reduceTable(zc->hashTable3, h3Size, reducerValue); }
|
1103
|
+
|
1104
|
+
{ if (zc->appliedParams.ldmParams.enableLdm) {
|
1105
|
+
U32 const ldmHSize = (U32)1 << zc->appliedParams.ldmParams.hashLog;
|
1106
|
+
ZSTD_ldm_reduceTable(zc->ldmState.hashTable, ldmHSize, reducerValue);
|
1107
|
+
}
|
1108
|
+
}
|
841
1109
|
}
|
842
1110
|
|
843
1111
|
|
@@ -976,24 +1244,6 @@ static size_t ZSTD_compressLiterals (ZSTD_entropyCTables_t * entropy,
|
|
976
1244
|
return lhSize+cLitSize;
|
977
1245
|
}
|
978
1246
|
|
979
|
-
static const BYTE LL_Code[64] = { 0, 1, 2, 3, 4, 5, 6, 7,
|
980
|
-
8, 9, 10, 11, 12, 13, 14, 15,
|
981
|
-
16, 16, 17, 17, 18, 18, 19, 19,
|
982
|
-
20, 20, 20, 20, 21, 21, 21, 21,
|
983
|
-
22, 22, 22, 22, 22, 22, 22, 22,
|
984
|
-
23, 23, 23, 23, 23, 23, 23, 23,
|
985
|
-
24, 24, 24, 24, 24, 24, 24, 24,
|
986
|
-
24, 24, 24, 24, 24, 24, 24, 24 };
|
987
|
-
|
988
|
-
static const BYTE ML_Code[128] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
989
|
-
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
990
|
-
32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 36, 36, 37, 37, 37, 37,
|
991
|
-
38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39,
|
992
|
-
40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
|
993
|
-
41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
|
994
|
-
42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
|
995
|
-
42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42 };
|
996
|
-
|
997
1247
|
|
998
1248
|
void ZSTD_seqToCodes(const seqStore_t* seqStorePtr)
|
999
1249
|
{
|
@@ -1018,20 +1268,30 @@ void ZSTD_seqToCodes(const seqStore_t* seqStorePtr)
|
|
1018
1268
|
mlCodeTable[seqStorePtr->longLengthPos] = MaxML;
|
1019
1269
|
}
|
1020
1270
|
|
1021
|
-
|
1022
|
-
|
1271
|
+
typedef enum {
|
1272
|
+
ZSTD_defaultDisallowed = 0,
|
1273
|
+
ZSTD_defaultAllowed = 1
|
1274
|
+
} ZSTD_defaultPolicy_e;
|
1275
|
+
|
1276
|
+
MEM_STATIC symbolEncodingType_e ZSTD_selectEncodingType(
|
1277
|
+
FSE_repeat* repeatMode, size_t const mostFrequent, size_t nbSeq,
|
1278
|
+
U32 defaultNormLog, ZSTD_defaultPolicy_e const isDefaultAllowed)
|
1023
1279
|
{
|
1024
1280
|
#define MIN_SEQ_FOR_DYNAMIC_FSE 64
|
1025
1281
|
#define MAX_SEQ_FOR_STATIC_FSE 1000
|
1026
|
-
|
1027
|
-
if ((mostFrequent == nbSeq) && (nbSeq > 2)) {
|
1282
|
+
ZSTD_STATIC_ASSERT(ZSTD_defaultDisallowed == 0 && ZSTD_defaultAllowed != 0);
|
1283
|
+
if ((mostFrequent == nbSeq) && (!isDefaultAllowed || nbSeq > 2)) {
|
1284
|
+
/* Prefer set_basic over set_rle when there are 2 or less symbols,
|
1285
|
+
* since RLE uses 1 byte, but set_basic uses 5-6 bits per symbol.
|
1286
|
+
* If basic encoding isn't possible, always choose RLE.
|
1287
|
+
*/
|
1028
1288
|
*repeatMode = FSE_repeat_check;
|
1029
1289
|
return set_rle;
|
1030
1290
|
}
|
1031
|
-
if ((*repeatMode == FSE_repeat_valid) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
|
1291
|
+
if (isDefaultAllowed && (*repeatMode == FSE_repeat_valid) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
|
1032
1292
|
return set_repeat;
|
1033
1293
|
}
|
1034
|
-
if ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (defaultNormLog-1)))) {
|
1294
|
+
if (isDefaultAllowed && ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (defaultNormLog-1))))) {
|
1035
1295
|
*repeatMode = FSE_repeat_valid;
|
1036
1296
|
return set_basic;
|
1037
1297
|
}
|
@@ -1059,1748 +1319,234 @@ MEM_STATIC size_t ZSTD_buildCTable(void* dst, size_t dstCapacity,
|
|
1059
1319
|
case set_basic:
|
1060
1320
|
CHECK_F(FSE_buildCTable_wksp(CTable, defaultNorm, defaultMax, defaultNormLog, workspace, workspaceSize));
|
1061
1321
|
return 0;
|
1062
|
-
case set_compressed: {
|
1063
|
-
S16 norm[MaxSeq + 1];
|
1064
|
-
size_t nbSeq_1 = nbSeq;
|
1065
|
-
const U32 tableLog = FSE_optimalTableLog(FSELog, nbSeq, max);
|
1066
|
-
if (count[codeTable[nbSeq-1]] > 1) {
|
1067
|
-
count[codeTable[nbSeq-1]]--;
|
1068
|
-
nbSeq_1--;
|
1069
|
-
}
|
1070
|
-
CHECK_F(FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max));
|
1071
|
-
{ size_t const NCountSize = FSE_writeNCount(op, oend - op, norm, max, tableLog); /* overflow protected */
|
1072
|
-
if (FSE_isError(NCountSize)) return NCountSize;
|
1073
|
-
CHECK_F(FSE_buildCTable_wksp(CTable, norm, max, tableLog, workspace, workspaceSize));
|
1074
|
-
return NCountSize;
|
1075
|
-
}
|
1076
|
-
}
|
1077
|
-
default: return assert(0), ERROR(GENERIC);
|
1078
|
-
}
|
1079
|
-
}
|
1080
|
-
|
1081
|
-
MEM_STATIC size_t ZSTD_encodeSequences(void* dst, size_t dstCapacity,
|
1082
|
-
FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,
|
1083
|
-
FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,
|
1084
|
-
FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,
|
1085
|
-
seqDef const* sequences, size_t nbSeq, int longOffsets)
|
1086
|
-
{
|
1087
|
-
BIT_CStream_t blockStream;
|
1088
|
-
FSE_CState_t stateMatchLength;
|
1089
|
-
FSE_CState_t stateOffsetBits;
|
1090
|
-
FSE_CState_t stateLitLength;
|
1091
|
-
|
1092
|
-
CHECK_E(BIT_initCStream(&blockStream, dst, dstCapacity), dstSize_tooSmall); /* not enough space remaining */
|
1093
|
-
|
1094
|
-
/* first symbols */
|
1095
|
-
FSE_initCState2(&stateMatchLength, CTable_MatchLength, mlCodeTable[nbSeq-1]);
|
1096
|
-
FSE_initCState2(&stateOffsetBits, CTable_OffsetBits, ofCodeTable[nbSeq-1]);
|
1097
|
-
FSE_initCState2(&stateLitLength, CTable_LitLength, llCodeTable[nbSeq-1]);
|
1098
|
-
BIT_addBits(&blockStream, sequences[nbSeq-1].litLength, LL_bits[llCodeTable[nbSeq-1]]);
|
1099
|
-
if (MEM_32bits()) BIT_flushBits(&blockStream);
|
1100
|
-
BIT_addBits(&blockStream, sequences[nbSeq-1].matchLength, ML_bits[mlCodeTable[nbSeq-1]]);
|
1101
|
-
if (MEM_32bits()) BIT_flushBits(&blockStream);
|
1102
|
-
if (longOffsets) {
|
1103
|
-
U32 const ofBits = ofCodeTable[nbSeq-1];
|
1104
|
-
int const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN-1);
|
1105
|
-
if (extraBits) {
|
1106
|
-
BIT_addBits(&blockStream, sequences[nbSeq-1].offset, extraBits);
|
1107
|
-
BIT_flushBits(&blockStream);
|
1108
|
-
}
|
1109
|
-
BIT_addBits(&blockStream, sequences[nbSeq-1].offset >> extraBits,
|
1110
|
-
ofBits - extraBits);
|
1111
|
-
} else {
|
1112
|
-
BIT_addBits(&blockStream, sequences[nbSeq-1].offset, ofCodeTable[nbSeq-1]);
|
1113
|
-
}
|
1114
|
-
BIT_flushBits(&blockStream);
|
1115
|
-
|
1116
|
-
{ size_t n;
|
1117
|
-
for (n=nbSeq-2 ; n<nbSeq ; n--) { /* intentional underflow */
|
1118
|
-
BYTE const llCode = llCodeTable[n];
|
1119
|
-
BYTE const ofCode = ofCodeTable[n];
|
1120
|
-
BYTE const mlCode = mlCodeTable[n];
|
1121
|
-
U32 const llBits = LL_bits[llCode];
|
1122
|
-
U32 const ofBits = ofCode; /* 32b*/ /* 64b*/
|
1123
|
-
U32 const mlBits = ML_bits[mlCode];
|
1124
|
-
/* (7)*/ /* (7)*/
|
1125
|
-
FSE_encodeSymbol(&blockStream, &stateOffsetBits, ofCode); /* 15 */ /* 15 */
|
1126
|
-
FSE_encodeSymbol(&blockStream, &stateMatchLength, mlCode); /* 24 */ /* 24 */
|
1127
|
-
if (MEM_32bits()) BIT_flushBits(&blockStream); /* (7)*/
|
1128
|
-
FSE_encodeSymbol(&blockStream, &stateLitLength, llCode); /* 16 */ /* 33 */
|
1129
|
-
if (MEM_32bits() || (ofBits+mlBits+llBits >= 64-7-(LLFSELog+MLFSELog+OffFSELog)))
|
1130
|
-
BIT_flushBits(&blockStream); /* (7)*/
|
1131
|
-
BIT_addBits(&blockStream, sequences[n].litLength, llBits);
|
1132
|
-
if (MEM_32bits() && ((llBits+mlBits)>24)) BIT_flushBits(&blockStream);
|
1133
|
-
BIT_addBits(&blockStream, sequences[n].matchLength, mlBits);
|
1134
|
-
if (MEM_32bits()) BIT_flushBits(&blockStream); /* (7)*/
|
1135
|
-
if (longOffsets) {
|
1136
|
-
int const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN-1);
|
1137
|
-
if (extraBits) {
|
1138
|
-
BIT_addBits(&blockStream, sequences[n].offset, extraBits);
|
1139
|
-
BIT_flushBits(&blockStream); /* (7)*/
|
1140
|
-
}
|
1141
|
-
BIT_addBits(&blockStream, sequences[n].offset >> extraBits,
|
1142
|
-
ofBits - extraBits); /* 31 */
|
1143
|
-
} else {
|
1144
|
-
BIT_addBits(&blockStream, sequences[n].offset, ofBits); /* 31 */
|
1145
|
-
}
|
1146
|
-
BIT_flushBits(&blockStream); /* (7)*/
|
1147
|
-
} }
|
1148
|
-
|
1149
|
-
FSE_flushCState(&blockStream, &stateMatchLength);
|
1150
|
-
FSE_flushCState(&blockStream, &stateOffsetBits);
|
1151
|
-
FSE_flushCState(&blockStream, &stateLitLength);
|
1152
|
-
|
1153
|
-
{ size_t const streamSize = BIT_closeCStream(&blockStream);
|
1154
|
-
if (streamSize==0) return ERROR(dstSize_tooSmall); /* not enough space */
|
1155
|
-
return streamSize;
|
1156
|
-
}
|
1157
|
-
}
|
1158
|
-
|
1159
|
-
MEM_STATIC size_t ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
|
1160
|
-
ZSTD_entropyCTables_t* entropy,
|
1161
|
-
ZSTD_compressionParameters const* cParams,
|
1162
|
-
void* dst, size_t dstCapacity)
|
1163
|
-
{
|
1164
|
-
const int longOffsets = cParams->windowLog > STREAM_ACCUMULATOR_MIN;
|
1165
|
-
U32 count[MaxSeq+1];
|
1166
|
-
FSE_CTable* CTable_LitLength = entropy->litlengthCTable;
|
1167
|
-
FSE_CTable* CTable_OffsetBits = entropy->offcodeCTable;
|
1168
|
-
FSE_CTable* CTable_MatchLength = entropy->matchlengthCTable;
|
1169
|
-
U32 LLtype, Offtype, MLtype; /* compressed, raw or rle */
|
1170
|
-
const seqDef* const sequences = seqStorePtr->sequencesStart;
|
1171
|
-
const BYTE* const ofCodeTable = seqStorePtr->ofCode;
|
1172
|
-
const BYTE* const llCodeTable = seqStorePtr->llCode;
|
1173
|
-
const BYTE* const mlCodeTable = seqStorePtr->mlCode;
|
1174
|
-
BYTE* const ostart = (BYTE*)dst;
|
1175
|
-
BYTE* const oend = ostart + dstCapacity;
|
1176
|
-
BYTE* op = ostart;
|
1177
|
-
size_t const nbSeq = seqStorePtr->sequences - seqStorePtr->sequencesStart;
|
1178
|
-
BYTE* seqHead;
|
1179
|
-
|
1180
|
-
ZSTD_STATIC_ASSERT(sizeof(entropy->workspace) >= (1<<MAX(MLFSELog,LLFSELog)));
|
1181
|
-
|
1182
|
-
/* Compress literals */
|
1183
|
-
{ const BYTE* const literals = seqStorePtr->litStart;
|
1184
|
-
size_t const litSize = seqStorePtr->lit - literals;
|
1185
|
-
size_t const cSize = ZSTD_compressLiterals(
|
1186
|
-
entropy, cParams->strategy, op, dstCapacity, literals, litSize);
|
1187
|
-
if (ZSTD_isError(cSize))
|
1188
|
-
return cSize;
|
1189
|
-
op += cSize;
|
1190
|
-
}
|
1191
|
-
|
1192
|
-
/* Sequences Header */
|
1193
|
-
if ((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead */) return ERROR(dstSize_tooSmall);
|
1194
|
-
if (nbSeq < 0x7F) *op++ = (BYTE)nbSeq;
|
1195
|
-
else if (nbSeq < LONGNBSEQ) op[0] = (BYTE)((nbSeq>>8) + 0x80), op[1] = (BYTE)nbSeq, op+=2;
|
1196
|
-
else op[0]=0xFF, MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ)), op+=3;
|
1197
|
-
if (nbSeq==0) return op - ostart;
|
1198
|
-
|
1199
|
-
/* seqHead : flags for FSE encoding type */
|
1200
|
-
seqHead = op++;
|
1201
|
-
|
1202
|
-
/* convert length/distances into codes */
|
1203
|
-
ZSTD_seqToCodes(seqStorePtr);
|
1204
|
-
/* CTable for Literal Lengths */
|
1205
|
-
{ U32 max = MaxLL;
|
1206
|
-
size_t const mostFrequent = FSE_countFast_wksp(count, &max, llCodeTable, nbSeq, entropy->workspace);
|
1207
|
-
LLtype = ZSTD_selectEncodingType(&entropy->litlength_repeatMode, mostFrequent, nbSeq, LL_defaultNormLog);
|
1208
|
-
{ size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_LitLength, LLFSELog, (symbolEncodingType_e)LLtype,
|
1209
|
-
count, max, llCodeTable, nbSeq, LL_defaultNorm, LL_defaultNormLog, MaxLL,
|
1210
|
-
entropy->workspace, sizeof(entropy->workspace));
|
1211
|
-
if (ZSTD_isError(countSize)) return countSize;
|
1212
|
-
op += countSize;
|
1213
|
-
} }
|
1214
|
-
/* CTable for Offsets */
|
1215
|
-
{ U32 max = MaxOff;
|
1216
|
-
size_t const mostFrequent = FSE_countFast_wksp(count, &max, ofCodeTable, nbSeq, entropy->workspace);
|
1217
|
-
Offtype = ZSTD_selectEncodingType(&entropy->offcode_repeatMode, mostFrequent, nbSeq, OF_defaultNormLog);
|
1218
|
-
{ size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_OffsetBits, OffFSELog, (symbolEncodingType_e)Offtype,
|
1219
|
-
count, max, ofCodeTable, nbSeq, OF_defaultNorm, OF_defaultNormLog, MaxOff,
|
1220
|
-
entropy->workspace, sizeof(entropy->workspace));
|
1221
|
-
if (ZSTD_isError(countSize)) return countSize;
|
1222
|
-
op += countSize;
|
1223
|
-
} }
|
1224
|
-
/* CTable for MatchLengths */
|
1225
|
-
{ U32 max = MaxML;
|
1226
|
-
size_t const mostFrequent = FSE_countFast_wksp(count, &max, mlCodeTable, nbSeq, entropy->workspace);
|
1227
|
-
MLtype = ZSTD_selectEncodingType(&entropy->matchlength_repeatMode, mostFrequent, nbSeq, ML_defaultNormLog);
|
1228
|
-
{ size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_MatchLength, MLFSELog, (symbolEncodingType_e)MLtype,
|
1229
|
-
count, max, mlCodeTable, nbSeq, ML_defaultNorm, ML_defaultNormLog, MaxML,
|
1230
|
-
entropy->workspace, sizeof(entropy->workspace));
|
1231
|
-
if (ZSTD_isError(countSize)) return countSize;
|
1232
|
-
op += countSize;
|
1233
|
-
} }
|
1234
|
-
|
1235
|
-
*seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2));
|
1236
|
-
|
1237
|
-
{ size_t const streamSize = ZSTD_encodeSequences(op, oend - op,
|
1238
|
-
CTable_MatchLength, mlCodeTable,
|
1239
|
-
CTable_OffsetBits, ofCodeTable,
|
1240
|
-
CTable_LitLength, llCodeTable,
|
1241
|
-
sequences, nbSeq, longOffsets);
|
1242
|
-
if (ZSTD_isError(streamSize)) return streamSize;
|
1243
|
-
op += streamSize;
|
1244
|
-
}
|
1245
|
-
|
1246
|
-
return op - ostart;
|
1247
|
-
}
|
1248
|
-
|
1249
|
-
MEM_STATIC size_t ZSTD_compressSequences(seqStore_t* seqStorePtr,
|
1250
|
-
ZSTD_entropyCTables_t* entropy,
|
1251
|
-
ZSTD_compressionParameters const* cParams,
|
1252
|
-
void* dst, size_t dstCapacity,
|
1253
|
-
size_t srcSize)
|
1254
|
-
{
|
1255
|
-
size_t const cSize = ZSTD_compressSequences_internal(seqStorePtr, entropy, cParams,
|
1256
|
-
dst, dstCapacity);
|
1257
|
-
size_t const minGain = ZSTD_minGain(srcSize);
|
1258
|
-
size_t const maxCSize = srcSize - minGain;
|
1259
|
-
/* If the srcSize <= dstCapacity, then there is enough space to write a
|
1260
|
-
* raw uncompressed block. Since we ran out of space, the block must not
|
1261
|
-
* be compressible, so fall back to a raw uncompressed block.
|
1262
|
-
*/
|
1263
|
-
int const uncompressibleError = cSize == ERROR(dstSize_tooSmall) && srcSize <= dstCapacity;
|
1264
|
-
|
1265
|
-
if (ZSTD_isError(cSize) && !uncompressibleError)
|
1266
|
-
return cSize;
|
1267
|
-
/* Check compressibility */
|
1268
|
-
if (cSize >= maxCSize || uncompressibleError) {
|
1269
|
-
entropy->hufCTable_repeatMode = HUF_repeat_none;
|
1270
|
-
entropy->offcode_repeatMode = FSE_repeat_none;
|
1271
|
-
entropy->matchlength_repeatMode = FSE_repeat_none;
|
1272
|
-
entropy->litlength_repeatMode = FSE_repeat_none;
|
1273
|
-
return 0;
|
1274
|
-
}
|
1275
|
-
assert(!ZSTD_isError(cSize));
|
1276
|
-
|
1277
|
-
/* confirm repcodes */
|
1278
|
-
{ int i; for (i=0; i<ZSTD_REP_NUM; i++) seqStorePtr->rep[i] = seqStorePtr->repToConfirm[i]; }
|
1279
|
-
return cSize;
|
1280
|
-
}
|
1281
|
-
|
1282
|
-
|
1283
|
-
/*! ZSTD_storeSeq() :
|
1284
|
-
Store a sequence (literal length, literals, offset code and match length code) into seqStore_t.
|
1285
|
-
`offsetCode` : distance to match, or 0 == repCode.
|
1286
|
-
`matchCode` : matchLength - MINMATCH
|
1287
|
-
*/
|
1288
|
-
MEM_STATIC void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const void* literals, U32 offsetCode, size_t matchCode)
|
1289
|
-
{
|
1290
|
-
#if defined(ZSTD_DEBUG) && (ZSTD_DEBUG >= 6)
|
1291
|
-
static const BYTE* g_start = NULL;
|
1292
|
-
U32 const pos = (U32)((const BYTE*)literals - g_start);
|
1293
|
-
if (g_start==NULL) g_start = (const BYTE*)literals;
|
1294
|
-
if ((pos > 0) && (pos < 1000000000))
|
1295
|
-
DEBUGLOG(6, "Cpos %6u :%5u literals & match %3u bytes at distance %6u",
|
1296
|
-
pos, (U32)litLength, (U32)matchCode+MINMATCH, (U32)offsetCode);
|
1297
|
-
#endif
|
1298
|
-
/* copy Literals */
|
1299
|
-
assert(seqStorePtr->lit + litLength <= seqStorePtr->litStart + 128 KB);
|
1300
|
-
ZSTD_wildcopy(seqStorePtr->lit, literals, litLength);
|
1301
|
-
seqStorePtr->lit += litLength;
|
1302
|
-
|
1303
|
-
/* literal Length */
|
1304
|
-
if (litLength>0xFFFF) {
|
1305
|
-
seqStorePtr->longLengthID = 1;
|
1306
|
-
seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
|
1307
|
-
}
|
1308
|
-
seqStorePtr->sequences[0].litLength = (U16)litLength;
|
1309
|
-
|
1310
|
-
/* match offset */
|
1311
|
-
seqStorePtr->sequences[0].offset = offsetCode + 1;
|
1312
|
-
|
1313
|
-
/* match Length */
|
1314
|
-
if (matchCode>0xFFFF) {
|
1315
|
-
seqStorePtr->longLengthID = 2;
|
1316
|
-
seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
|
1317
|
-
}
|
1318
|
-
seqStorePtr->sequences[0].matchLength = (U16)matchCode;
|
1319
|
-
|
1320
|
-
seqStorePtr->sequences++;
|
1321
|
-
}
|
1322
|
-
|
1323
|
-
|
1324
|
-
/*-*************************************
|
1325
|
-
* Match length counter
|
1326
|
-
***************************************/
|
1327
|
-
static unsigned ZSTD_NbCommonBytes (register size_t val)
|
1328
|
-
{
|
1329
|
-
if (MEM_isLittleEndian()) {
|
1330
|
-
if (MEM_64bits()) {
|
1331
|
-
# if defined(_MSC_VER) && defined(_WIN64)
|
1332
|
-
unsigned long r = 0;
|
1333
|
-
_BitScanForward64( &r, (U64)val );
|
1334
|
-
return (unsigned)(r>>3);
|
1335
|
-
# elif defined(__GNUC__) && (__GNUC__ >= 3)
|
1336
|
-
return (__builtin_ctzll((U64)val) >> 3);
|
1337
|
-
# else
|
1338
|
-
static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2,
|
1339
|
-
0, 3, 1, 3, 1, 4, 2, 7,
|
1340
|
-
0, 2, 3, 6, 1, 5, 3, 5,
|
1341
|
-
1, 3, 4, 4, 2, 5, 6, 7,
|
1342
|
-
7, 0, 1, 2, 3, 3, 4, 6,
|
1343
|
-
2, 6, 5, 5, 3, 4, 5, 6,
|
1344
|
-
7, 1, 2, 4, 6, 4, 4, 5,
|
1345
|
-
7, 2, 6, 5, 7, 6, 7, 7 };
|
1346
|
-
return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58];
|
1347
|
-
# endif
|
1348
|
-
} else { /* 32 bits */
|
1349
|
-
# if defined(_MSC_VER)
|
1350
|
-
unsigned long r=0;
|
1351
|
-
_BitScanForward( &r, (U32)val );
|
1352
|
-
return (unsigned)(r>>3);
|
1353
|
-
# elif defined(__GNUC__) && (__GNUC__ >= 3)
|
1354
|
-
return (__builtin_ctz((U32)val) >> 3);
|
1355
|
-
# else
|
1356
|
-
static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0,
|
1357
|
-
3, 2, 2, 1, 3, 2, 0, 1,
|
1358
|
-
3, 3, 1, 2, 2, 2, 2, 0,
|
1359
|
-
3, 1, 2, 0, 1, 0, 1, 1 };
|
1360
|
-
return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27];
|
1361
|
-
# endif
|
1362
|
-
}
|
1363
|
-
} else { /* Big Endian CPU */
|
1364
|
-
if (MEM_64bits()) {
|
1365
|
-
# if defined(_MSC_VER) && defined(_WIN64)
|
1366
|
-
unsigned long r = 0;
|
1367
|
-
_BitScanReverse64( &r, val );
|
1368
|
-
return (unsigned)(r>>3);
|
1369
|
-
# elif defined(__GNUC__) && (__GNUC__ >= 3)
|
1370
|
-
return (__builtin_clzll(val) >> 3);
|
1371
|
-
# else
|
1372
|
-
unsigned r;
|
1373
|
-
const unsigned n32 = sizeof(size_t)*4; /* calculate this way due to compiler complaining in 32-bits mode */
|
1374
|
-
if (!(val>>n32)) { r=4; } else { r=0; val>>=n32; }
|
1375
|
-
if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; }
|
1376
|
-
r += (!val);
|
1377
|
-
return r;
|
1378
|
-
# endif
|
1379
|
-
} else { /* 32 bits */
|
1380
|
-
# if defined(_MSC_VER)
|
1381
|
-
unsigned long r = 0;
|
1382
|
-
_BitScanReverse( &r, (unsigned long)val );
|
1383
|
-
return (unsigned)(r>>3);
|
1384
|
-
# elif defined(__GNUC__) && (__GNUC__ >= 3)
|
1385
|
-
return (__builtin_clz((U32)val) >> 3);
|
1386
|
-
# else
|
1387
|
-
unsigned r;
|
1388
|
-
if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; }
|
1389
|
-
r += (!val);
|
1390
|
-
return r;
|
1391
|
-
# endif
|
1392
|
-
} }
|
1393
|
-
}
|
1394
|
-
|
1395
|
-
|
1396
|
-
static size_t ZSTD_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* const pInLimit)
|
1397
|
-
{
|
1398
|
-
const BYTE* const pStart = pIn;
|
1399
|
-
const BYTE* const pInLoopLimit = pInLimit - (sizeof(size_t)-1);
|
1400
|
-
|
1401
|
-
while (pIn < pInLoopLimit) {
|
1402
|
-
size_t const diff = MEM_readST(pMatch) ^ MEM_readST(pIn);
|
1403
|
-
if (!diff) { pIn+=sizeof(size_t); pMatch+=sizeof(size_t); continue; }
|
1404
|
-
pIn += ZSTD_NbCommonBytes(diff);
|
1405
|
-
return (size_t)(pIn - pStart);
|
1406
|
-
}
|
1407
|
-
if (MEM_64bits()) if ((pIn<(pInLimit-3)) && (MEM_read32(pMatch) == MEM_read32(pIn))) { pIn+=4; pMatch+=4; }
|
1408
|
-
if ((pIn<(pInLimit-1)) && (MEM_read16(pMatch) == MEM_read16(pIn))) { pIn+=2; pMatch+=2; }
|
1409
|
-
if ((pIn<pInLimit) && (*pMatch == *pIn)) pIn++;
|
1410
|
-
return (size_t)(pIn - pStart);
|
1411
|
-
}
|
1412
|
-
|
1413
|
-
/** ZSTD_count_2segments() :
|
1414
|
-
* can count match length with `ip` & `match` in 2 different segments.
|
1415
|
-
* convention : on reaching mEnd, match count continue starting from iStart
|
1416
|
-
*/
|
1417
|
-
static size_t ZSTD_count_2segments(const BYTE* ip, const BYTE* match, const BYTE* iEnd, const BYTE* mEnd, const BYTE* iStart)
|
1418
|
-
{
|
1419
|
-
const BYTE* const vEnd = MIN( ip + (mEnd - match), iEnd);
|
1420
|
-
size_t const matchLength = ZSTD_count(ip, match, vEnd);
|
1421
|
-
if (match + matchLength != mEnd) return matchLength;
|
1422
|
-
return matchLength + ZSTD_count(ip+matchLength, iStart, iEnd);
|
1423
|
-
}
|
1424
|
-
|
1425
|
-
|
1426
|
-
/*-*************************************
|
1427
|
-
* Hashes
|
1428
|
-
***************************************/
|
1429
|
-
static const U32 prime3bytes = 506832829U;
|
1430
|
-
static U32 ZSTD_hash3(U32 u, U32 h) { return ((u << (32-24)) * prime3bytes) >> (32-h) ; }
|
1431
|
-
MEM_STATIC size_t ZSTD_hash3Ptr(const void* ptr, U32 h) { return ZSTD_hash3(MEM_readLE32(ptr), h); } /* only in zstd_opt.h */
|
1432
|
-
|
1433
|
-
static const U32 prime4bytes = 2654435761U;
|
1434
|
-
static U32 ZSTD_hash4(U32 u, U32 h) { return (u * prime4bytes) >> (32-h) ; }
|
1435
|
-
static size_t ZSTD_hash4Ptr(const void* ptr, U32 h) { return ZSTD_hash4(MEM_read32(ptr), h); }
|
1436
|
-
|
1437
|
-
static const U64 prime5bytes = 889523592379ULL;
|
1438
|
-
static size_t ZSTD_hash5(U64 u, U32 h) { return (size_t)(((u << (64-40)) * prime5bytes) >> (64-h)) ; }
|
1439
|
-
static size_t ZSTD_hash5Ptr(const void* p, U32 h) { return ZSTD_hash5(MEM_readLE64(p), h); }
|
1440
|
-
|
1441
|
-
static const U64 prime6bytes = 227718039650203ULL;
|
1442
|
-
static size_t ZSTD_hash6(U64 u, U32 h) { return (size_t)(((u << (64-48)) * prime6bytes) >> (64-h)) ; }
|
1443
|
-
static size_t ZSTD_hash6Ptr(const void* p, U32 h) { return ZSTD_hash6(MEM_readLE64(p), h); }
|
1444
|
-
|
1445
|
-
static const U64 prime7bytes = 58295818150454627ULL;
|
1446
|
-
static size_t ZSTD_hash7(U64 u, U32 h) { return (size_t)(((u << (64-56)) * prime7bytes) >> (64-h)) ; }
|
1447
|
-
static size_t ZSTD_hash7Ptr(const void* p, U32 h) { return ZSTD_hash7(MEM_readLE64(p), h); }
|
1448
|
-
|
1449
|
-
static const U64 prime8bytes = 0xCF1BBCDCB7A56463ULL;
|
1450
|
-
static size_t ZSTD_hash8(U64 u, U32 h) { return (size_t)(((u) * prime8bytes) >> (64-h)) ; }
|
1451
|
-
static size_t ZSTD_hash8Ptr(const void* p, U32 h) { return ZSTD_hash8(MEM_readLE64(p), h); }
|
1452
|
-
|
1453
|
-
static size_t ZSTD_hashPtr(const void* p, U32 hBits, U32 mls)
|
1454
|
-
{
|
1455
|
-
switch(mls)
|
1456
|
-
{
|
1457
|
-
default:
|
1458
|
-
case 4: return ZSTD_hash4Ptr(p, hBits);
|
1459
|
-
case 5: return ZSTD_hash5Ptr(p, hBits);
|
1460
|
-
case 6: return ZSTD_hash6Ptr(p, hBits);
|
1461
|
-
case 7: return ZSTD_hash7Ptr(p, hBits);
|
1462
|
-
case 8: return ZSTD_hash8Ptr(p, hBits);
|
1463
|
-
}
|
1464
|
-
}
|
1465
|
-
|
1466
|
-
|
1467
|
-
/*-*************************************
|
1468
|
-
* Fast Scan
|
1469
|
-
***************************************/
|
1470
|
-
static void ZSTD_fillHashTable (ZSTD_CCtx* zc, const void* end, const U32 mls)
|
1471
|
-
{
|
1472
|
-
U32* const hashTable = zc->hashTable;
|
1473
|
-
U32 const hBits = zc->appliedParams.cParams.hashLog;
|
1474
|
-
const BYTE* const base = zc->base;
|
1475
|
-
const BYTE* ip = base + zc->nextToUpdate;
|
1476
|
-
const BYTE* const iend = ((const BYTE*)end) - HASH_READ_SIZE;
|
1477
|
-
const size_t fastHashFillStep = 3;
|
1478
|
-
|
1479
|
-
while(ip <= iend) {
|
1480
|
-
hashTable[ZSTD_hashPtr(ip, hBits, mls)] = (U32)(ip - base);
|
1481
|
-
ip += fastHashFillStep;
|
1482
|
-
}
|
1483
|
-
}
|
1484
|
-
|
1485
|
-
|
1486
|
-
FORCE_INLINE_TEMPLATE
|
1487
|
-
void ZSTD_compressBlock_fast_generic(ZSTD_CCtx* cctx,
|
1488
|
-
const void* src, size_t srcSize,
|
1489
|
-
const U32 mls)
|
1490
|
-
{
|
1491
|
-
U32* const hashTable = cctx->hashTable;
|
1492
|
-
U32 const hBits = cctx->appliedParams.cParams.hashLog;
|
1493
|
-
seqStore_t* seqStorePtr = &(cctx->seqStore);
|
1494
|
-
const BYTE* const base = cctx->base;
|
1495
|
-
const BYTE* const istart = (const BYTE*)src;
|
1496
|
-
const BYTE* ip = istart;
|
1497
|
-
const BYTE* anchor = istart;
|
1498
|
-
const U32 lowestIndex = cctx->dictLimit;
|
1499
|
-
const BYTE* const lowest = base + lowestIndex;
|
1500
|
-
const BYTE* const iend = istart + srcSize;
|
1501
|
-
const BYTE* const ilimit = iend - HASH_READ_SIZE;
|
1502
|
-
U32 offset_1=seqStorePtr->rep[0], offset_2=seqStorePtr->rep[1];
|
1503
|
-
U32 offsetSaved = 0;
|
1504
|
-
|
1505
|
-
/* init */
|
1506
|
-
ip += (ip==lowest);
|
1507
|
-
{ U32 const maxRep = (U32)(ip-lowest);
|
1508
|
-
if (offset_2 > maxRep) offsetSaved = offset_2, offset_2 = 0;
|
1509
|
-
if (offset_1 > maxRep) offsetSaved = offset_1, offset_1 = 0;
|
1510
|
-
}
|
1511
|
-
|
1512
|
-
/* Main Search Loop */
|
1513
|
-
while (ip < ilimit) { /* < instead of <=, because repcode check at (ip+1) */
|
1514
|
-
size_t mLength;
|
1515
|
-
size_t const h = ZSTD_hashPtr(ip, hBits, mls);
|
1516
|
-
U32 const current = (U32)(ip-base);
|
1517
|
-
U32 const matchIndex = hashTable[h];
|
1518
|
-
const BYTE* match = base + matchIndex;
|
1519
|
-
hashTable[h] = current; /* update hash table */
|
1520
|
-
|
1521
|
-
if ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1))) {
|
1522
|
-
mLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;
|
1523
|
-
ip++;
|
1524
|
-
ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, 0, mLength-MINMATCH);
|
1525
|
-
} else {
|
1526
|
-
U32 offset;
|
1527
|
-
if ( (matchIndex <= lowestIndex) || (MEM_read32(match) != MEM_read32(ip)) ) {
|
1528
|
-
ip += ((ip-anchor) >> g_searchStrength) + 1;
|
1529
|
-
continue;
|
1530
|
-
}
|
1531
|
-
mLength = ZSTD_count(ip+4, match+4, iend) + 4;
|
1532
|
-
offset = (U32)(ip-match);
|
1533
|
-
while (((ip>anchor) & (match>lowest)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
|
1534
|
-
offset_2 = offset_1;
|
1535
|
-
offset_1 = offset;
|
1536
|
-
|
1537
|
-
ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
1538
|
-
}
|
1539
|
-
|
1540
|
-
/* match found */
|
1541
|
-
ip += mLength;
|
1542
|
-
anchor = ip;
|
1543
|
-
|
1544
|
-
if (ip <= ilimit) {
|
1545
|
-
/* Fill Table */
|
1546
|
-
hashTable[ZSTD_hashPtr(base+current+2, hBits, mls)] = current+2; /* here because current+2 could be > iend-8 */
|
1547
|
-
hashTable[ZSTD_hashPtr(ip-2, hBits, mls)] = (U32)(ip-2-base);
|
1548
|
-
/* check immediate repcode */
|
1549
|
-
while ( (ip <= ilimit)
|
1550
|
-
&& ( (offset_2>0)
|
1551
|
-
& (MEM_read32(ip) == MEM_read32(ip - offset_2)) )) {
|
1552
|
-
/* store sequence */
|
1553
|
-
size_t const rLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;
|
1554
|
-
{ U32 const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; } /* swap offset_2 <=> offset_1 */
|
1555
|
-
hashTable[ZSTD_hashPtr(ip, hBits, mls)] = (U32)(ip-base);
|
1556
|
-
ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, rLength-MINMATCH);
|
1557
|
-
ip += rLength;
|
1558
|
-
anchor = ip;
|
1559
|
-
continue; /* faster when present ... (?) */
|
1560
|
-
} } }
|
1561
|
-
|
1562
|
-
/* save reps for next block */
|
1563
|
-
seqStorePtr->repToConfirm[0] = offset_1 ? offset_1 : offsetSaved;
|
1564
|
-
seqStorePtr->repToConfirm[1] = offset_2 ? offset_2 : offsetSaved;
|
1565
|
-
|
1566
|
-
/* Last Literals */
|
1567
|
-
{ size_t const lastLLSize = iend - anchor;
|
1568
|
-
memcpy(seqStorePtr->lit, anchor, lastLLSize);
|
1569
|
-
seqStorePtr->lit += lastLLSize;
|
1570
|
-
}
|
1571
|
-
}
|
1572
|
-
|
1573
|
-
|
1574
|
-
static void ZSTD_compressBlock_fast(ZSTD_CCtx* ctx,
|
1575
|
-
const void* src, size_t srcSize)
|
1576
|
-
{
|
1577
|
-
const U32 mls = ctx->appliedParams.cParams.searchLength;
|
1578
|
-
switch(mls)
|
1579
|
-
{
|
1580
|
-
default: /* includes case 3 */
|
1581
|
-
case 4 :
|
1582
|
-
ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 4); return;
|
1583
|
-
case 5 :
|
1584
|
-
ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 5); return;
|
1585
|
-
case 6 :
|
1586
|
-
ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 6); return;
|
1587
|
-
case 7 :
|
1588
|
-
ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 7); return;
|
1589
|
-
}
|
1590
|
-
}
|
1591
|
-
|
1592
|
-
|
1593
|
-
static void ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
|
1594
|
-
const void* src, size_t srcSize,
|
1595
|
-
const U32 mls)
|
1596
|
-
{
|
1597
|
-
U32* hashTable = ctx->hashTable;
|
1598
|
-
const U32 hBits = ctx->appliedParams.cParams.hashLog;
|
1599
|
-
seqStore_t* seqStorePtr = &(ctx->seqStore);
|
1600
|
-
const BYTE* const base = ctx->base;
|
1601
|
-
const BYTE* const dictBase = ctx->dictBase;
|
1602
|
-
const BYTE* const istart = (const BYTE*)src;
|
1603
|
-
const BYTE* ip = istart;
|
1604
|
-
const BYTE* anchor = istart;
|
1605
|
-
const U32 lowestIndex = ctx->lowLimit;
|
1606
|
-
const BYTE* const dictStart = dictBase + lowestIndex;
|
1607
|
-
const U32 dictLimit = ctx->dictLimit;
|
1608
|
-
const BYTE* const lowPrefixPtr = base + dictLimit;
|
1609
|
-
const BYTE* const dictEnd = dictBase + dictLimit;
|
1610
|
-
const BYTE* const iend = istart + srcSize;
|
1611
|
-
const BYTE* const ilimit = iend - 8;
|
1612
|
-
U32 offset_1=seqStorePtr->rep[0], offset_2=seqStorePtr->rep[1];
|
1613
|
-
|
1614
|
-
/* Search Loop */
|
1615
|
-
while (ip < ilimit) { /* < instead of <=, because (ip+1) */
|
1616
|
-
const size_t h = ZSTD_hashPtr(ip, hBits, mls);
|
1617
|
-
const U32 matchIndex = hashTable[h];
|
1618
|
-
const BYTE* matchBase = matchIndex < dictLimit ? dictBase : base;
|
1619
|
-
const BYTE* match = matchBase + matchIndex;
|
1620
|
-
const U32 current = (U32)(ip-base);
|
1621
|
-
const U32 repIndex = current + 1 - offset_1; /* offset_1 expected <= current +1 */
|
1622
|
-
const BYTE* repBase = repIndex < dictLimit ? dictBase : base;
|
1623
|
-
const BYTE* repMatch = repBase + repIndex;
|
1624
|
-
size_t mLength;
|
1625
|
-
hashTable[h] = current; /* update hash table */
|
1626
|
-
|
1627
|
-
if ( (((U32)((dictLimit-1) - repIndex) >= 3) /* intentional underflow */ & (repIndex > lowestIndex))
|
1628
|
-
&& (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
|
1629
|
-
const BYTE* repMatchEnd = repIndex < dictLimit ? dictEnd : iend;
|
1630
|
-
mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, lowPrefixPtr) + 4;
|
1631
|
-
ip++;
|
1632
|
-
ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, 0, mLength-MINMATCH);
|
1633
|
-
} else {
|
1634
|
-
if ( (matchIndex < lowestIndex) ||
|
1635
|
-
(MEM_read32(match) != MEM_read32(ip)) ) {
|
1636
|
-
ip += ((ip-anchor) >> g_searchStrength) + 1;
|
1637
|
-
continue;
|
1638
|
-
}
|
1639
|
-
{ const BYTE* matchEnd = matchIndex < dictLimit ? dictEnd : iend;
|
1640
|
-
const BYTE* lowMatchPtr = matchIndex < dictLimit ? dictStart : lowPrefixPtr;
|
1641
|
-
U32 offset;
|
1642
|
-
mLength = ZSTD_count_2segments(ip+4, match+4, iend, matchEnd, lowPrefixPtr) + 4;
|
1643
|
-
while (((ip>anchor) & (match>lowMatchPtr)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
|
1644
|
-
offset = current - matchIndex;
|
1645
|
-
offset_2 = offset_1;
|
1646
|
-
offset_1 = offset;
|
1647
|
-
ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
1648
|
-
} }
|
1649
|
-
|
1650
|
-
/* found a match : store it */
|
1651
|
-
ip += mLength;
|
1652
|
-
anchor = ip;
|
1653
|
-
|
1654
|
-
if (ip <= ilimit) {
|
1655
|
-
/* Fill Table */
|
1656
|
-
hashTable[ZSTD_hashPtr(base+current+2, hBits, mls)] = current+2;
|
1657
|
-
hashTable[ZSTD_hashPtr(ip-2, hBits, mls)] = (U32)(ip-2-base);
|
1658
|
-
/* check immediate repcode */
|
1659
|
-
while (ip <= ilimit) {
|
1660
|
-
U32 const current2 = (U32)(ip-base);
|
1661
|
-
U32 const repIndex2 = current2 - offset_2;
|
1662
|
-
const BYTE* repMatch2 = repIndex2 < dictLimit ? dictBase + repIndex2 : base + repIndex2;
|
1663
|
-
if ( (((U32)((dictLimit-1) - repIndex2) >= 3) & (repIndex2 > lowestIndex)) /* intentional overflow */
|
1664
|
-
&& (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
|
1665
|
-
const BYTE* const repEnd2 = repIndex2 < dictLimit ? dictEnd : iend;
|
1666
|
-
size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, lowPrefixPtr) + 4;
|
1667
|
-
U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
|
1668
|
-
ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, repLength2-MINMATCH);
|
1669
|
-
hashTable[ZSTD_hashPtr(ip, hBits, mls)] = current2;
|
1670
|
-
ip += repLength2;
|
1671
|
-
anchor = ip;
|
1672
|
-
continue;
|
1673
|
-
}
|
1674
|
-
break;
|
1675
|
-
} } }
|
1676
|
-
|
1677
|
-
/* save reps for next block */
|
1678
|
-
seqStorePtr->repToConfirm[0] = offset_1; seqStorePtr->repToConfirm[1] = offset_2;
|
1679
|
-
|
1680
|
-
/* Last Literals */
|
1681
|
-
{ size_t const lastLLSize = iend - anchor;
|
1682
|
-
memcpy(seqStorePtr->lit, anchor, lastLLSize);
|
1683
|
-
seqStorePtr->lit += lastLLSize;
|
1684
|
-
}
|
1685
|
-
}
|
1686
|
-
|
1687
|
-
|
1688
|
-
static void ZSTD_compressBlock_fast_extDict(ZSTD_CCtx* ctx,
|
1689
|
-
const void* src, size_t srcSize)
|
1690
|
-
{
|
1691
|
-
U32 const mls = ctx->appliedParams.cParams.searchLength;
|
1692
|
-
switch(mls)
|
1693
|
-
{
|
1694
|
-
default: /* includes case 3 */
|
1695
|
-
case 4 :
|
1696
|
-
ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 4); return;
|
1697
|
-
case 5 :
|
1698
|
-
ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 5); return;
|
1699
|
-
case 6 :
|
1700
|
-
ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 6); return;
|
1701
|
-
case 7 :
|
1702
|
-
ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 7); return;
|
1703
|
-
}
|
1704
|
-
}
|
1705
|
-
|
1706
|
-
|
1707
|
-
/*-*************************************
|
1708
|
-
* Double Fast
|
1709
|
-
***************************************/
|
1710
|
-
static void ZSTD_fillDoubleHashTable (ZSTD_CCtx* cctx, const void* end, const U32 mls)
|
1711
|
-
{
|
1712
|
-
U32* const hashLarge = cctx->hashTable;
|
1713
|
-
U32 const hBitsL = cctx->appliedParams.cParams.hashLog;
|
1714
|
-
U32* const hashSmall = cctx->chainTable;
|
1715
|
-
U32 const hBitsS = cctx->appliedParams.cParams.chainLog;
|
1716
|
-
const BYTE* const base = cctx->base;
|
1717
|
-
const BYTE* ip = base + cctx->nextToUpdate;
|
1718
|
-
const BYTE* const iend = ((const BYTE*)end) - HASH_READ_SIZE;
|
1719
|
-
const size_t fastHashFillStep = 3;
|
1720
|
-
|
1721
|
-
while(ip <= iend) {
|
1722
|
-
hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = (U32)(ip - base);
|
1723
|
-
hashLarge[ZSTD_hashPtr(ip, hBitsL, 8)] = (U32)(ip - base);
|
1724
|
-
ip += fastHashFillStep;
|
1725
|
-
}
|
1726
|
-
}
|
1727
|
-
|
1728
|
-
|
1729
|
-
FORCE_INLINE_TEMPLATE
|
1730
|
-
void ZSTD_compressBlock_doubleFast_generic(ZSTD_CCtx* cctx,
|
1731
|
-
const void* src, size_t srcSize,
|
1732
|
-
const U32 mls)
|
1733
|
-
{
|
1734
|
-
U32* const hashLong = cctx->hashTable;
|
1735
|
-
const U32 hBitsL = cctx->appliedParams.cParams.hashLog;
|
1736
|
-
U32* const hashSmall = cctx->chainTable;
|
1737
|
-
const U32 hBitsS = cctx->appliedParams.cParams.chainLog;
|
1738
|
-
seqStore_t* seqStorePtr = &(cctx->seqStore);
|
1739
|
-
const BYTE* const base = cctx->base;
|
1740
|
-
const BYTE* const istart = (const BYTE*)src;
|
1741
|
-
const BYTE* ip = istart;
|
1742
|
-
const BYTE* anchor = istart;
|
1743
|
-
const U32 lowestIndex = cctx->dictLimit;
|
1744
|
-
const BYTE* const lowest = base + lowestIndex;
|
1745
|
-
const BYTE* const iend = istart + srcSize;
|
1746
|
-
const BYTE* const ilimit = iend - HASH_READ_SIZE;
|
1747
|
-
U32 offset_1=seqStorePtr->rep[0], offset_2=seqStorePtr->rep[1];
|
1748
|
-
U32 offsetSaved = 0;
|
1749
|
-
|
1750
|
-
/* init */
|
1751
|
-
ip += (ip==lowest);
|
1752
|
-
{ U32 const maxRep = (U32)(ip-lowest);
|
1753
|
-
if (offset_2 > maxRep) offsetSaved = offset_2, offset_2 = 0;
|
1754
|
-
if (offset_1 > maxRep) offsetSaved = offset_1, offset_1 = 0;
|
1755
|
-
}
|
1756
|
-
|
1757
|
-
/* Main Search Loop */
|
1758
|
-
while (ip < ilimit) { /* < instead of <=, because repcode check at (ip+1) */
|
1759
|
-
size_t mLength;
|
1760
|
-
size_t const h2 = ZSTD_hashPtr(ip, hBitsL, 8);
|
1761
|
-
size_t const h = ZSTD_hashPtr(ip, hBitsS, mls);
|
1762
|
-
U32 const current = (U32)(ip-base);
|
1763
|
-
U32 const matchIndexL = hashLong[h2];
|
1764
|
-
U32 const matchIndexS = hashSmall[h];
|
1765
|
-
const BYTE* matchLong = base + matchIndexL;
|
1766
|
-
const BYTE* match = base + matchIndexS;
|
1767
|
-
hashLong[h2] = hashSmall[h] = current; /* update hash tables */
|
1768
|
-
|
1769
|
-
assert(offset_1 <= current); /* supposed guaranteed by construction */
|
1770
|
-
if ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1))) {
|
1771
|
-
/* favor repcode */
|
1772
|
-
mLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;
|
1773
|
-
ip++;
|
1774
|
-
ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, 0, mLength-MINMATCH);
|
1775
|
-
} else {
|
1776
|
-
U32 offset;
|
1777
|
-
if ( (matchIndexL > lowestIndex) && (MEM_read64(matchLong) == MEM_read64(ip)) ) {
|
1778
|
-
mLength = ZSTD_count(ip+8, matchLong+8, iend) + 8;
|
1779
|
-
offset = (U32)(ip-matchLong);
|
1780
|
-
while (((ip>anchor) & (matchLong>lowest)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } /* catch up */
|
1781
|
-
} else if ( (matchIndexS > lowestIndex) && (MEM_read32(match) == MEM_read32(ip)) ) {
|
1782
|
-
size_t const hl3 = ZSTD_hashPtr(ip+1, hBitsL, 8);
|
1783
|
-
U32 const matchIndexL3 = hashLong[hl3];
|
1784
|
-
const BYTE* matchL3 = base + matchIndexL3;
|
1785
|
-
hashLong[hl3] = current + 1;
|
1786
|
-
if ( (matchIndexL3 > lowestIndex) && (MEM_read64(matchL3) == MEM_read64(ip+1)) ) {
|
1787
|
-
mLength = ZSTD_count(ip+9, matchL3+8, iend) + 8;
|
1788
|
-
ip++;
|
1789
|
-
offset = (U32)(ip-matchL3);
|
1790
|
-
while (((ip>anchor) & (matchL3>lowest)) && (ip[-1] == matchL3[-1])) { ip--; matchL3--; mLength++; } /* catch up */
|
1791
|
-
} else {
|
1792
|
-
mLength = ZSTD_count(ip+4, match+4, iend) + 4;
|
1793
|
-
offset = (U32)(ip-match);
|
1794
|
-
while (((ip>anchor) & (match>lowest)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
|
1795
|
-
}
|
1796
|
-
} else {
|
1797
|
-
ip += ((ip-anchor) >> g_searchStrength) + 1;
|
1798
|
-
continue;
|
1799
|
-
}
|
1800
|
-
|
1801
|
-
offset_2 = offset_1;
|
1802
|
-
offset_1 = offset;
|
1803
|
-
|
1804
|
-
ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
1805
|
-
}
|
1806
|
-
|
1807
|
-
/* match found */
|
1808
|
-
ip += mLength;
|
1809
|
-
anchor = ip;
|
1810
|
-
|
1811
|
-
if (ip <= ilimit) {
|
1812
|
-
/* Fill Table */
|
1813
|
-
hashLong[ZSTD_hashPtr(base+current+2, hBitsL, 8)] =
|
1814
|
-
hashSmall[ZSTD_hashPtr(base+current+2, hBitsS, mls)] = current+2; /* here because current+2 could be > iend-8 */
|
1815
|
-
hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] =
|
1816
|
-
hashSmall[ZSTD_hashPtr(ip-2, hBitsS, mls)] = (U32)(ip-2-base);
|
1817
|
-
|
1818
|
-
/* check immediate repcode */
|
1819
|
-
while ( (ip <= ilimit)
|
1820
|
-
&& ( (offset_2>0)
|
1821
|
-
& (MEM_read32(ip) == MEM_read32(ip - offset_2)) )) {
|
1822
|
-
/* store sequence */
|
1823
|
-
size_t const rLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;
|
1824
|
-
{ U32 const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; } /* swap offset_2 <=> offset_1 */
|
1825
|
-
hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = (U32)(ip-base);
|
1826
|
-
hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = (U32)(ip-base);
|
1827
|
-
ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, rLength-MINMATCH);
|
1828
|
-
ip += rLength;
|
1829
|
-
anchor = ip;
|
1830
|
-
continue; /* faster when present ... (?) */
|
1831
|
-
} } }
|
1832
|
-
|
1833
|
-
/* save reps for next block */
|
1834
|
-
seqStorePtr->repToConfirm[0] = offset_1 ? offset_1 : offsetSaved;
|
1835
|
-
seqStorePtr->repToConfirm[1] = offset_2 ? offset_2 : offsetSaved;
|
1836
|
-
|
1837
|
-
/* Last Literals */
|
1838
|
-
{ size_t const lastLLSize = iend - anchor;
|
1839
|
-
memcpy(seqStorePtr->lit, anchor, lastLLSize);
|
1840
|
-
seqStorePtr->lit += lastLLSize;
|
1841
|
-
}
|
1842
|
-
}
|
1843
|
-
|
1844
|
-
|
1845
|
-
static void ZSTD_compressBlock_doubleFast(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
|
1846
|
-
{
|
1847
|
-
const U32 mls = ctx->appliedParams.cParams.searchLength;
|
1848
|
-
switch(mls)
|
1849
|
-
{
|
1850
|
-
default: /* includes case 3 */
|
1851
|
-
case 4 :
|
1852
|
-
ZSTD_compressBlock_doubleFast_generic(ctx, src, srcSize, 4); return;
|
1853
|
-
case 5 :
|
1854
|
-
ZSTD_compressBlock_doubleFast_generic(ctx, src, srcSize, 5); return;
|
1855
|
-
case 6 :
|
1856
|
-
ZSTD_compressBlock_doubleFast_generic(ctx, src, srcSize, 6); return;
|
1857
|
-
case 7 :
|
1858
|
-
ZSTD_compressBlock_doubleFast_generic(ctx, src, srcSize, 7); return;
|
1859
|
-
}
|
1860
|
-
}
|
1861
|
-
|
1862
|
-
|
1863
|
-
static void ZSTD_compressBlock_doubleFast_extDict_generic(ZSTD_CCtx* ctx,
|
1864
|
-
const void* src, size_t srcSize,
|
1865
|
-
const U32 mls)
|
1866
|
-
{
|
1867
|
-
U32* const hashLong = ctx->hashTable;
|
1868
|
-
U32 const hBitsL = ctx->appliedParams.cParams.hashLog;
|
1869
|
-
U32* const hashSmall = ctx->chainTable;
|
1870
|
-
U32 const hBitsS = ctx->appliedParams.cParams.chainLog;
|
1871
|
-
seqStore_t* seqStorePtr = &(ctx->seqStore);
|
1872
|
-
const BYTE* const base = ctx->base;
|
1873
|
-
const BYTE* const dictBase = ctx->dictBase;
|
1874
|
-
const BYTE* const istart = (const BYTE*)src;
|
1875
|
-
const BYTE* ip = istart;
|
1876
|
-
const BYTE* anchor = istart;
|
1877
|
-
const U32 lowestIndex = ctx->lowLimit;
|
1878
|
-
const BYTE* const dictStart = dictBase + lowestIndex;
|
1879
|
-
const U32 dictLimit = ctx->dictLimit;
|
1880
|
-
const BYTE* const lowPrefixPtr = base + dictLimit;
|
1881
|
-
const BYTE* const dictEnd = dictBase + dictLimit;
|
1882
|
-
const BYTE* const iend = istart + srcSize;
|
1883
|
-
const BYTE* const ilimit = iend - 8;
|
1884
|
-
U32 offset_1=seqStorePtr->rep[0], offset_2=seqStorePtr->rep[1];
|
1885
|
-
|
1886
|
-
/* Search Loop */
|
1887
|
-
while (ip < ilimit) { /* < instead of <=, because (ip+1) */
|
1888
|
-
const size_t hSmall = ZSTD_hashPtr(ip, hBitsS, mls);
|
1889
|
-
const U32 matchIndex = hashSmall[hSmall];
|
1890
|
-
const BYTE* matchBase = matchIndex < dictLimit ? dictBase : base;
|
1891
|
-
const BYTE* match = matchBase + matchIndex;
|
1892
|
-
|
1893
|
-
const size_t hLong = ZSTD_hashPtr(ip, hBitsL, 8);
|
1894
|
-
const U32 matchLongIndex = hashLong[hLong];
|
1895
|
-
const BYTE* matchLongBase = matchLongIndex < dictLimit ? dictBase : base;
|
1896
|
-
const BYTE* matchLong = matchLongBase + matchLongIndex;
|
1897
|
-
|
1898
|
-
const U32 current = (U32)(ip-base);
|
1899
|
-
const U32 repIndex = current + 1 - offset_1; /* offset_1 expected <= current +1 */
|
1900
|
-
const BYTE* repBase = repIndex < dictLimit ? dictBase : base;
|
1901
|
-
const BYTE* repMatch = repBase + repIndex;
|
1902
|
-
size_t mLength;
|
1903
|
-
hashSmall[hSmall] = hashLong[hLong] = current; /* update hash table */
|
1904
|
-
|
1905
|
-
if ( (((U32)((dictLimit-1) - repIndex) >= 3) /* intentional underflow */ & (repIndex > lowestIndex))
|
1906
|
-
&& (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
|
1907
|
-
const BYTE* repMatchEnd = repIndex < dictLimit ? dictEnd : iend;
|
1908
|
-
mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, lowPrefixPtr) + 4;
|
1909
|
-
ip++;
|
1910
|
-
ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, 0, mLength-MINMATCH);
|
1911
|
-
} else {
|
1912
|
-
if ((matchLongIndex > lowestIndex) && (MEM_read64(matchLong) == MEM_read64(ip))) {
|
1913
|
-
const BYTE* matchEnd = matchLongIndex < dictLimit ? dictEnd : iend;
|
1914
|
-
const BYTE* lowMatchPtr = matchLongIndex < dictLimit ? dictStart : lowPrefixPtr;
|
1915
|
-
U32 offset;
|
1916
|
-
mLength = ZSTD_count_2segments(ip+8, matchLong+8, iend, matchEnd, lowPrefixPtr) + 8;
|
1917
|
-
offset = current - matchLongIndex;
|
1918
|
-
while (((ip>anchor) & (matchLong>lowMatchPtr)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } /* catch up */
|
1919
|
-
offset_2 = offset_1;
|
1920
|
-
offset_1 = offset;
|
1921
|
-
ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
1922
|
-
|
1923
|
-
} else if ((matchIndex > lowestIndex) && (MEM_read32(match) == MEM_read32(ip))) {
|
1924
|
-
size_t const h3 = ZSTD_hashPtr(ip+1, hBitsL, 8);
|
1925
|
-
U32 const matchIndex3 = hashLong[h3];
|
1926
|
-
const BYTE* const match3Base = matchIndex3 < dictLimit ? dictBase : base;
|
1927
|
-
const BYTE* match3 = match3Base + matchIndex3;
|
1928
|
-
U32 offset;
|
1929
|
-
hashLong[h3] = current + 1;
|
1930
|
-
if ( (matchIndex3 > lowestIndex) && (MEM_read64(match3) == MEM_read64(ip+1)) ) {
|
1931
|
-
const BYTE* matchEnd = matchIndex3 < dictLimit ? dictEnd : iend;
|
1932
|
-
const BYTE* lowMatchPtr = matchIndex3 < dictLimit ? dictStart : lowPrefixPtr;
|
1933
|
-
mLength = ZSTD_count_2segments(ip+9, match3+8, iend, matchEnd, lowPrefixPtr) + 8;
|
1934
|
-
ip++;
|
1935
|
-
offset = current+1 - matchIndex3;
|
1936
|
-
while (((ip>anchor) & (match3>lowMatchPtr)) && (ip[-1] == match3[-1])) { ip--; match3--; mLength++; } /* catch up */
|
1937
|
-
} else {
|
1938
|
-
const BYTE* matchEnd = matchIndex < dictLimit ? dictEnd : iend;
|
1939
|
-
const BYTE* lowMatchPtr = matchIndex < dictLimit ? dictStart : lowPrefixPtr;
|
1940
|
-
mLength = ZSTD_count_2segments(ip+4, match+4, iend, matchEnd, lowPrefixPtr) + 4;
|
1941
|
-
offset = current - matchIndex;
|
1942
|
-
while (((ip>anchor) & (match>lowMatchPtr)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
|
1943
|
-
}
|
1944
|
-
offset_2 = offset_1;
|
1945
|
-
offset_1 = offset;
|
1946
|
-
ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
1947
|
-
|
1948
|
-
} else {
|
1949
|
-
ip += ((ip-anchor) >> g_searchStrength) + 1;
|
1950
|
-
continue;
|
1951
|
-
} }
|
1952
|
-
|
1953
|
-
/* found a match : store it */
|
1954
|
-
ip += mLength;
|
1955
|
-
anchor = ip;
|
1956
|
-
|
1957
|
-
if (ip <= ilimit) {
|
1958
|
-
/* Fill Table */
|
1959
|
-
hashSmall[ZSTD_hashPtr(base+current+2, hBitsS, mls)] = current+2;
|
1960
|
-
hashLong[ZSTD_hashPtr(base+current+2, hBitsL, 8)] = current+2;
|
1961
|
-
hashSmall[ZSTD_hashPtr(ip-2, hBitsS, mls)] = (U32)(ip-2-base);
|
1962
|
-
hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] = (U32)(ip-2-base);
|
1963
|
-
/* check immediate repcode */
|
1964
|
-
while (ip <= ilimit) {
|
1965
|
-
U32 const current2 = (U32)(ip-base);
|
1966
|
-
U32 const repIndex2 = current2 - offset_2;
|
1967
|
-
const BYTE* repMatch2 = repIndex2 < dictLimit ? dictBase + repIndex2 : base + repIndex2;
|
1968
|
-
if ( (((U32)((dictLimit-1) - repIndex2) >= 3) & (repIndex2 > lowestIndex)) /* intentional overflow */
|
1969
|
-
&& (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
|
1970
|
-
const BYTE* const repEnd2 = repIndex2 < dictLimit ? dictEnd : iend;
|
1971
|
-
size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, lowPrefixPtr) + 4;
|
1972
|
-
U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
|
1973
|
-
ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, repLength2-MINMATCH);
|
1974
|
-
hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = current2;
|
1975
|
-
hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = current2;
|
1976
|
-
ip += repLength2;
|
1977
|
-
anchor = ip;
|
1978
|
-
continue;
|
1979
|
-
}
|
1980
|
-
break;
|
1981
|
-
} } }
|
1982
|
-
|
1983
|
-
/* save reps for next block */
|
1984
|
-
seqStorePtr->repToConfirm[0] = offset_1; seqStorePtr->repToConfirm[1] = offset_2;
|
1985
|
-
|
1986
|
-
/* Last Literals */
|
1987
|
-
{ size_t const lastLLSize = iend - anchor;
|
1988
|
-
memcpy(seqStorePtr->lit, anchor, lastLLSize);
|
1989
|
-
seqStorePtr->lit += lastLLSize;
|
1990
|
-
}
|
1991
|
-
}
|
1992
|
-
|
1993
|
-
|
1994
|
-
static void ZSTD_compressBlock_doubleFast_extDict(ZSTD_CCtx* ctx,
|
1995
|
-
const void* src, size_t srcSize)
|
1996
|
-
{
|
1997
|
-
U32 const mls = ctx->appliedParams.cParams.searchLength;
|
1998
|
-
switch(mls)
|
1999
|
-
{
|
2000
|
-
default: /* includes case 3 */
|
2001
|
-
case 4 :
|
2002
|
-
ZSTD_compressBlock_doubleFast_extDict_generic(ctx, src, srcSize, 4); return;
|
2003
|
-
case 5 :
|
2004
|
-
ZSTD_compressBlock_doubleFast_extDict_generic(ctx, src, srcSize, 5); return;
|
2005
|
-
case 6 :
|
2006
|
-
ZSTD_compressBlock_doubleFast_extDict_generic(ctx, src, srcSize, 6); return;
|
2007
|
-
case 7 :
|
2008
|
-
ZSTD_compressBlock_doubleFast_extDict_generic(ctx, src, srcSize, 7); return;
|
2009
|
-
}
|
2010
|
-
}
|
2011
|
-
|
2012
|
-
|
2013
|
-
/*-*************************************
|
2014
|
-
* Binary Tree search
|
2015
|
-
***************************************/
|
2016
|
-
/** ZSTD_insertBt1() : add one or multiple positions to tree.
|
2017
|
-
* ip : assumed <= iend-8 .
|
2018
|
-
* @return : nb of positions added */
|
2019
|
-
static U32 ZSTD_insertBt1(ZSTD_CCtx* zc, const BYTE* const ip, const U32 mls, const BYTE* const iend, U32 nbCompares,
|
2020
|
-
U32 extDict)
|
2021
|
-
{
|
2022
|
-
U32* const hashTable = zc->hashTable;
|
2023
|
-
U32 const hashLog = zc->appliedParams.cParams.hashLog;
|
2024
|
-
size_t const h = ZSTD_hashPtr(ip, hashLog, mls);
|
2025
|
-
U32* const bt = zc->chainTable;
|
2026
|
-
U32 const btLog = zc->appliedParams.cParams.chainLog - 1;
|
2027
|
-
U32 const btMask = (1 << btLog) - 1;
|
2028
|
-
U32 matchIndex = hashTable[h];
|
2029
|
-
size_t commonLengthSmaller=0, commonLengthLarger=0;
|
2030
|
-
const BYTE* const base = zc->base;
|
2031
|
-
const BYTE* const dictBase = zc->dictBase;
|
2032
|
-
const U32 dictLimit = zc->dictLimit;
|
2033
|
-
const BYTE* const dictEnd = dictBase + dictLimit;
|
2034
|
-
const BYTE* const prefixStart = base + dictLimit;
|
2035
|
-
const BYTE* match;
|
2036
|
-
const U32 current = (U32)(ip-base);
|
2037
|
-
const U32 btLow = btMask >= current ? 0 : current - btMask;
|
2038
|
-
U32* smallerPtr = bt + 2*(current&btMask);
|
2039
|
-
U32* largerPtr = smallerPtr + 1;
|
2040
|
-
U32 dummy32; /* to be nullified at the end */
|
2041
|
-
U32 const windowLow = zc->lowLimit;
|
2042
|
-
U32 matchEndIdx = current+8;
|
2043
|
-
size_t bestLength = 8;
|
2044
|
-
#ifdef ZSTD_C_PREDICT
|
2045
|
-
U32 predictedSmall = *(bt + 2*((current-1)&btMask) + 0);
|
2046
|
-
U32 predictedLarge = *(bt + 2*((current-1)&btMask) + 1);
|
2047
|
-
predictedSmall += (predictedSmall>0);
|
2048
|
-
predictedLarge += (predictedLarge>0);
|
2049
|
-
#endif /* ZSTD_C_PREDICT */
|
2050
|
-
|
2051
|
-
hashTable[h] = current; /* Update Hash Table */
|
2052
|
-
|
2053
|
-
while (nbCompares-- && (matchIndex > windowLow)) {
|
2054
|
-
U32* const nextPtr = bt + 2*(matchIndex & btMask);
|
2055
|
-
size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
|
2056
|
-
|
2057
|
-
#ifdef ZSTD_C_PREDICT /* note : can create issues when hlog small <= 11 */
|
2058
|
-
const U32* predictPtr = bt + 2*((matchIndex-1) & btMask); /* written this way, as bt is a roll buffer */
|
2059
|
-
if (matchIndex == predictedSmall) {
|
2060
|
-
/* no need to check length, result known */
|
2061
|
-
*smallerPtr = matchIndex;
|
2062
|
-
if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */
|
2063
|
-
smallerPtr = nextPtr+1; /* new "smaller" => larger of match */
|
2064
|
-
matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
|
2065
|
-
predictedSmall = predictPtr[1] + (predictPtr[1]>0);
|
2066
|
-
continue;
|
2067
|
-
}
|
2068
|
-
if (matchIndex == predictedLarge) {
|
2069
|
-
*largerPtr = matchIndex;
|
2070
|
-
if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */
|
2071
|
-
largerPtr = nextPtr;
|
2072
|
-
matchIndex = nextPtr[0];
|
2073
|
-
predictedLarge = predictPtr[0] + (predictPtr[0]>0);
|
2074
|
-
continue;
|
2075
|
-
}
|
2076
|
-
#endif
|
2077
|
-
if ((!extDict) || (matchIndex+matchLength >= dictLimit)) {
|
2078
|
-
match = base + matchIndex;
|
2079
|
-
if (match[matchLength] == ip[matchLength])
|
2080
|
-
matchLength += ZSTD_count(ip+matchLength+1, match+matchLength+1, iend) +1;
|
2081
|
-
} else {
|
2082
|
-
match = dictBase + matchIndex;
|
2083
|
-
matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart);
|
2084
|
-
if (matchIndex+matchLength >= dictLimit)
|
2085
|
-
match = base + matchIndex; /* to prepare for next usage of match[matchLength] */
|
2086
|
-
}
|
2087
|
-
|
2088
|
-
if (matchLength > bestLength) {
|
2089
|
-
bestLength = matchLength;
|
2090
|
-
if (matchLength > matchEndIdx - matchIndex)
|
2091
|
-
matchEndIdx = matchIndex + (U32)matchLength;
|
2092
|
-
}
|
2093
|
-
|
2094
|
-
if (ip+matchLength == iend) /* equal : no way to know if inf or sup */
|
2095
|
-
break; /* drop , to guarantee consistency ; miss a bit of compression, but other solutions can corrupt the tree */
|
2096
|
-
|
2097
|
-
if (match[matchLength] < ip[matchLength]) { /* necessarily within correct buffer */
|
2098
|
-
/* match is smaller than current */
|
2099
|
-
*smallerPtr = matchIndex; /* update smaller idx */
|
2100
|
-
commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */
|
2101
|
-
if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */
|
2102
|
-
smallerPtr = nextPtr+1; /* new "smaller" => larger of match */
|
2103
|
-
matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
|
2104
|
-
} else {
|
2105
|
-
/* match is larger than current */
|
2106
|
-
*largerPtr = matchIndex;
|
2107
|
-
commonLengthLarger = matchLength;
|
2108
|
-
if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */
|
2109
|
-
largerPtr = nextPtr;
|
2110
|
-
matchIndex = nextPtr[0];
|
2111
|
-
} }
|
2112
|
-
|
2113
|
-
*smallerPtr = *largerPtr = 0;
|
2114
|
-
if (bestLength > 384) return MIN(192, (U32)(bestLength - 384)); /* speed optimization */
|
2115
|
-
if (matchEndIdx > current + 8) return matchEndIdx - current - 8;
|
2116
|
-
return 1;
|
2117
|
-
}
|
2118
|
-
|
2119
|
-
|
2120
|
-
static size_t ZSTD_insertBtAndFindBestMatch (
|
2121
|
-
ZSTD_CCtx* zc,
|
2122
|
-
const BYTE* const ip, const BYTE* const iend,
|
2123
|
-
size_t* offsetPtr,
|
2124
|
-
U32 nbCompares, const U32 mls,
|
2125
|
-
U32 extDict)
|
2126
|
-
{
|
2127
|
-
U32* const hashTable = zc->hashTable;
|
2128
|
-
U32 const hashLog = zc->appliedParams.cParams.hashLog;
|
2129
|
-
size_t const h = ZSTD_hashPtr(ip, hashLog, mls);
|
2130
|
-
U32* const bt = zc->chainTable;
|
2131
|
-
U32 const btLog = zc->appliedParams.cParams.chainLog - 1;
|
2132
|
-
U32 const btMask = (1 << btLog) - 1;
|
2133
|
-
U32 matchIndex = hashTable[h];
|
2134
|
-
size_t commonLengthSmaller=0, commonLengthLarger=0;
|
2135
|
-
const BYTE* const base = zc->base;
|
2136
|
-
const BYTE* const dictBase = zc->dictBase;
|
2137
|
-
const U32 dictLimit = zc->dictLimit;
|
2138
|
-
const BYTE* const dictEnd = dictBase + dictLimit;
|
2139
|
-
const BYTE* const prefixStart = base + dictLimit;
|
2140
|
-
const U32 current = (U32)(ip-base);
|
2141
|
-
const U32 btLow = btMask >= current ? 0 : current - btMask;
|
2142
|
-
const U32 windowLow = zc->lowLimit;
|
2143
|
-
U32* smallerPtr = bt + 2*(current&btMask);
|
2144
|
-
U32* largerPtr = bt + 2*(current&btMask) + 1;
|
2145
|
-
U32 matchEndIdx = current+8;
|
2146
|
-
U32 dummy32; /* to be nullified at the end */
|
2147
|
-
size_t bestLength = 0;
|
2148
|
-
|
2149
|
-
hashTable[h] = current; /* Update Hash Table */
|
2150
|
-
|
2151
|
-
while (nbCompares-- && (matchIndex > windowLow)) {
|
2152
|
-
U32* const nextPtr = bt + 2*(matchIndex & btMask);
|
2153
|
-
size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
|
2154
|
-
const BYTE* match;
|
2155
|
-
|
2156
|
-
if ((!extDict) || (matchIndex+matchLength >= dictLimit)) {
|
2157
|
-
match = base + matchIndex;
|
2158
|
-
if (match[matchLength] == ip[matchLength])
|
2159
|
-
matchLength += ZSTD_count(ip+matchLength+1, match+matchLength+1, iend) +1;
|
2160
|
-
} else {
|
2161
|
-
match = dictBase + matchIndex;
|
2162
|
-
matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart);
|
2163
|
-
if (matchIndex+matchLength >= dictLimit)
|
2164
|
-
match = base + matchIndex; /* to prepare for next usage of match[matchLength] */
|
2165
|
-
}
|
2166
|
-
|
2167
|
-
if (matchLength > bestLength) {
|
2168
|
-
if (matchLength > matchEndIdx - matchIndex)
|
2169
|
-
matchEndIdx = matchIndex + (U32)matchLength;
|
2170
|
-
if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit32(current-matchIndex+1) - ZSTD_highbit32((U32)offsetPtr[0]+1)) )
|
2171
|
-
bestLength = matchLength, *offsetPtr = ZSTD_REP_MOVE + current - matchIndex;
|
2172
|
-
if (ip+matchLength == iend) /* equal : no way to know if inf or sup */
|
2173
|
-
break; /* drop, to guarantee consistency (miss a little bit of compression) */
|
2174
|
-
}
|
2175
|
-
|
2176
|
-
if (match[matchLength] < ip[matchLength]) {
|
2177
|
-
/* match is smaller than current */
|
2178
|
-
*smallerPtr = matchIndex; /* update smaller idx */
|
2179
|
-
commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */
|
2180
|
-
if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */
|
2181
|
-
smallerPtr = nextPtr+1; /* new "smaller" => larger of match */
|
2182
|
-
matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
|
2183
|
-
} else {
|
2184
|
-
/* match is larger than current */
|
2185
|
-
*largerPtr = matchIndex;
|
2186
|
-
commonLengthLarger = matchLength;
|
2187
|
-
if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */
|
2188
|
-
largerPtr = nextPtr;
|
2189
|
-
matchIndex = nextPtr[0];
|
2190
|
-
} }
|
2191
|
-
|
2192
|
-
*smallerPtr = *largerPtr = 0;
|
2193
|
-
|
2194
|
-
zc->nextToUpdate = (matchEndIdx > current + 8) ? matchEndIdx - 8 : current+1;
|
2195
|
-
return bestLength;
|
2196
|
-
}
|
2197
|
-
|
2198
|
-
|
2199
|
-
static void ZSTD_updateTree(ZSTD_CCtx* zc, const BYTE* const ip, const BYTE* const iend, const U32 nbCompares, const U32 mls)
|
2200
|
-
{
|
2201
|
-
const BYTE* const base = zc->base;
|
2202
|
-
const U32 target = (U32)(ip - base);
|
2203
|
-
U32 idx = zc->nextToUpdate;
|
2204
|
-
|
2205
|
-
while(idx < target)
|
2206
|
-
idx += ZSTD_insertBt1(zc, base+idx, mls, iend, nbCompares, 0);
|
2207
|
-
}
|
2208
|
-
|
2209
|
-
/** ZSTD_BtFindBestMatch() : Tree updater, providing best match */
|
2210
|
-
static size_t ZSTD_BtFindBestMatch (
|
2211
|
-
ZSTD_CCtx* zc,
|
2212
|
-
const BYTE* const ip, const BYTE* const iLimit,
|
2213
|
-
size_t* offsetPtr,
|
2214
|
-
const U32 maxNbAttempts, const U32 mls)
|
2215
|
-
{
|
2216
|
-
if (ip < zc->base + zc->nextToUpdate) return 0; /* skipped area */
|
2217
|
-
ZSTD_updateTree(zc, ip, iLimit, maxNbAttempts, mls);
|
2218
|
-
return ZSTD_insertBtAndFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, mls, 0);
|
2219
|
-
}
|
2220
|
-
|
2221
|
-
|
2222
|
-
static size_t ZSTD_BtFindBestMatch_selectMLS (
|
2223
|
-
ZSTD_CCtx* zc, /* Index table will be updated */
|
2224
|
-
const BYTE* ip, const BYTE* const iLimit,
|
2225
|
-
size_t* offsetPtr,
|
2226
|
-
const U32 maxNbAttempts, const U32 matchLengthSearch)
|
2227
|
-
{
|
2228
|
-
switch(matchLengthSearch)
|
2229
|
-
{
|
2230
|
-
default : /* includes case 3 */
|
2231
|
-
case 4 : return ZSTD_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4);
|
2232
|
-
case 5 : return ZSTD_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5);
|
2233
|
-
case 7 :
|
2234
|
-
case 6 : return ZSTD_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6);
|
2235
|
-
}
|
2236
|
-
}
|
2237
|
-
|
2238
|
-
|
2239
|
-
static void ZSTD_updateTree_extDict(ZSTD_CCtx* zc, const BYTE* const ip, const BYTE* const iend, const U32 nbCompares, const U32 mls)
|
2240
|
-
{
|
2241
|
-
const BYTE* const base = zc->base;
|
2242
|
-
const U32 target = (U32)(ip - base);
|
2243
|
-
U32 idx = zc->nextToUpdate;
|
2244
|
-
|
2245
|
-
while (idx < target) idx += ZSTD_insertBt1(zc, base+idx, mls, iend, nbCompares, 1);
|
2246
|
-
}
|
2247
|
-
|
2248
|
-
|
2249
|
-
/** Tree updater, providing best match */
|
2250
|
-
static size_t ZSTD_BtFindBestMatch_extDict (
|
2251
|
-
ZSTD_CCtx* zc,
|
2252
|
-
const BYTE* const ip, const BYTE* const iLimit,
|
2253
|
-
size_t* offsetPtr,
|
2254
|
-
const U32 maxNbAttempts, const U32 mls)
|
2255
|
-
{
|
2256
|
-
if (ip < zc->base + zc->nextToUpdate) return 0; /* skipped area */
|
2257
|
-
ZSTD_updateTree_extDict(zc, ip, iLimit, maxNbAttempts, mls);
|
2258
|
-
return ZSTD_insertBtAndFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, mls, 1);
|
2259
|
-
}
|
2260
|
-
|
2261
|
-
|
2262
|
-
static size_t ZSTD_BtFindBestMatch_selectMLS_extDict (
|
2263
|
-
ZSTD_CCtx* zc, /* Index table will be updated */
|
2264
|
-
const BYTE* ip, const BYTE* const iLimit,
|
2265
|
-
size_t* offsetPtr,
|
2266
|
-
const U32 maxNbAttempts, const U32 matchLengthSearch)
|
2267
|
-
{
|
2268
|
-
switch(matchLengthSearch)
|
2269
|
-
{
|
2270
|
-
default : /* includes case 3 */
|
2271
|
-
case 4 : return ZSTD_BtFindBestMatch_extDict(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4);
|
2272
|
-
case 5 : return ZSTD_BtFindBestMatch_extDict(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5);
|
2273
|
-
case 7 :
|
2274
|
-
case 6 : return ZSTD_BtFindBestMatch_extDict(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6);
|
2275
|
-
}
|
2276
|
-
}
|
2277
|
-
|
2278
|
-
|
2279
|
-
|
2280
|
-
/* *********************************
|
2281
|
-
* Hash Chain
|
2282
|
-
***********************************/
|
2283
|
-
#define NEXT_IN_CHAIN(d, mask) chainTable[(d) & mask]
|
2284
|
-
|
2285
|
-
/* Update chains up to ip (excluded)
|
2286
|
-
Assumption : always within prefix (i.e. not within extDict) */
|
2287
|
-
FORCE_INLINE_TEMPLATE
|
2288
|
-
U32 ZSTD_insertAndFindFirstIndex (ZSTD_CCtx* zc, const BYTE* ip, U32 mls)
|
2289
|
-
{
|
2290
|
-
U32* const hashTable = zc->hashTable;
|
2291
|
-
const U32 hashLog = zc->appliedParams.cParams.hashLog;
|
2292
|
-
U32* const chainTable = zc->chainTable;
|
2293
|
-
const U32 chainMask = (1 << zc->appliedParams.cParams.chainLog) - 1;
|
2294
|
-
const BYTE* const base = zc->base;
|
2295
|
-
const U32 target = (U32)(ip - base);
|
2296
|
-
U32 idx = zc->nextToUpdate;
|
2297
|
-
|
2298
|
-
while(idx < target) { /* catch up */
|
2299
|
-
size_t const h = ZSTD_hashPtr(base+idx, hashLog, mls);
|
2300
|
-
NEXT_IN_CHAIN(idx, chainMask) = hashTable[h];
|
2301
|
-
hashTable[h] = idx;
|
2302
|
-
idx++;
|
2303
|
-
}
|
2304
|
-
|
2305
|
-
zc->nextToUpdate = target;
|
2306
|
-
return hashTable[ZSTD_hashPtr(ip, hashLog, mls)];
|
2307
|
-
}
|
2308
|
-
|
2309
|
-
|
2310
|
-
/* inlining is important to hardwire a hot branch (template emulation) */
|
2311
|
-
FORCE_INLINE_TEMPLATE
|
2312
|
-
size_t ZSTD_HcFindBestMatch_generic (
|
2313
|
-
ZSTD_CCtx* zc, /* Index table will be updated */
|
2314
|
-
const BYTE* const ip, const BYTE* const iLimit,
|
2315
|
-
size_t* offsetPtr,
|
2316
|
-
const U32 maxNbAttempts, const U32 mls, const U32 extDict)
|
2317
|
-
{
|
2318
|
-
U32* const chainTable = zc->chainTable;
|
2319
|
-
const U32 chainSize = (1 << zc->appliedParams.cParams.chainLog);
|
2320
|
-
const U32 chainMask = chainSize-1;
|
2321
|
-
const BYTE* const base = zc->base;
|
2322
|
-
const BYTE* const dictBase = zc->dictBase;
|
2323
|
-
const U32 dictLimit = zc->dictLimit;
|
2324
|
-
const BYTE* const prefixStart = base + dictLimit;
|
2325
|
-
const BYTE* const dictEnd = dictBase + dictLimit;
|
2326
|
-
const U32 lowLimit = zc->lowLimit;
|
2327
|
-
const U32 current = (U32)(ip-base);
|
2328
|
-
const U32 minChain = current > chainSize ? current - chainSize : 0;
|
2329
|
-
int nbAttempts=maxNbAttempts;
|
2330
|
-
size_t ml=4-1;
|
2331
|
-
|
2332
|
-
/* HC4 match finder */
|
2333
|
-
U32 matchIndex = ZSTD_insertAndFindFirstIndex (zc, ip, mls);
|
2334
|
-
|
2335
|
-
for ( ; (matchIndex>lowLimit) & (nbAttempts>0) ; nbAttempts--) {
|
2336
|
-
const BYTE* match;
|
2337
|
-
size_t currentMl=0;
|
2338
|
-
if ((!extDict) || matchIndex >= dictLimit) {
|
2339
|
-
match = base + matchIndex;
|
2340
|
-
if (match[ml] == ip[ml]) /* potentially better */
|
2341
|
-
currentMl = ZSTD_count(ip, match, iLimit);
|
2342
|
-
} else {
|
2343
|
-
match = dictBase + matchIndex;
|
2344
|
-
if (MEM_read32(match) == MEM_read32(ip)) /* assumption : matchIndex <= dictLimit-4 (by table construction) */
|
2345
|
-
currentMl = ZSTD_count_2segments(ip+4, match+4, iLimit, dictEnd, prefixStart) + 4;
|
2346
|
-
}
|
2347
|
-
|
2348
|
-
/* save best solution */
|
2349
|
-
if (currentMl > ml) {
|
2350
|
-
ml = currentMl;
|
2351
|
-
*offsetPtr = current - matchIndex + ZSTD_REP_MOVE;
|
2352
|
-
if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */
|
2353
|
-
}
|
2354
|
-
|
2355
|
-
if (matchIndex <= minChain) break;
|
2356
|
-
matchIndex = NEXT_IN_CHAIN(matchIndex, chainMask);
|
2357
|
-
}
|
2358
|
-
|
2359
|
-
return ml;
|
2360
|
-
}
|
2361
|
-
|
2362
|
-
|
2363
|
-
FORCE_INLINE_TEMPLATE size_t ZSTD_HcFindBestMatch_selectMLS (
|
2364
|
-
ZSTD_CCtx* zc,
|
2365
|
-
const BYTE* ip, const BYTE* const iLimit,
|
2366
|
-
size_t* offsetPtr,
|
2367
|
-
const U32 maxNbAttempts, const U32 matchLengthSearch)
|
2368
|
-
{
|
2369
|
-
switch(matchLengthSearch)
|
2370
|
-
{
|
2371
|
-
default : /* includes case 3 */
|
2372
|
-
case 4 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4, 0);
|
2373
|
-
case 5 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5, 0);
|
2374
|
-
case 7 :
|
2375
|
-
case 6 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6, 0);
|
2376
|
-
}
|
2377
|
-
}
|
2378
|
-
|
2379
|
-
|
2380
|
-
FORCE_INLINE_TEMPLATE size_t ZSTD_HcFindBestMatch_extDict_selectMLS (
|
2381
|
-
ZSTD_CCtx* zc,
|
2382
|
-
const BYTE* ip, const BYTE* const iLimit,
|
2383
|
-
size_t* offsetPtr,
|
2384
|
-
const U32 maxNbAttempts, const U32 matchLengthSearch)
|
2385
|
-
{
|
2386
|
-
switch(matchLengthSearch)
|
2387
|
-
{
|
2388
|
-
default : /* includes case 3 */
|
2389
|
-
case 4 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4, 1);
|
2390
|
-
case 5 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5, 1);
|
2391
|
-
case 7 :
|
2392
|
-
case 6 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6, 1);
|
2393
|
-
}
|
2394
|
-
}
|
2395
|
-
|
2396
|
-
|
2397
|
-
/* *******************************
|
2398
|
-
* Common parser - lazy strategy
|
2399
|
-
*********************************/
|
2400
|
-
FORCE_INLINE_TEMPLATE
|
2401
|
-
void ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
|
2402
|
-
const void* src, size_t srcSize,
|
2403
|
-
const U32 searchMethod, const U32 depth)
|
2404
|
-
{
|
2405
|
-
seqStore_t* seqStorePtr = &(ctx->seqStore);
|
2406
|
-
const BYTE* const istart = (const BYTE*)src;
|
2407
|
-
const BYTE* ip = istart;
|
2408
|
-
const BYTE* anchor = istart;
|
2409
|
-
const BYTE* const iend = istart + srcSize;
|
2410
|
-
const BYTE* const ilimit = iend - 8;
|
2411
|
-
const BYTE* const base = ctx->base + ctx->dictLimit;
|
2412
|
-
|
2413
|
-
U32 const maxSearches = 1 << ctx->appliedParams.cParams.searchLog;
|
2414
|
-
U32 const mls = ctx->appliedParams.cParams.searchLength;
|
2415
|
-
|
2416
|
-
typedef size_t (*searchMax_f)(ZSTD_CCtx* zc, const BYTE* ip, const BYTE* iLimit,
|
2417
|
-
size_t* offsetPtr,
|
2418
|
-
U32 maxNbAttempts, U32 matchLengthSearch);
|
2419
|
-
searchMax_f const searchMax = searchMethod ? ZSTD_BtFindBestMatch_selectMLS : ZSTD_HcFindBestMatch_selectMLS;
|
2420
|
-
U32 offset_1 = seqStorePtr->rep[0], offset_2 = seqStorePtr->rep[1], savedOffset=0;
|
2421
|
-
|
2422
|
-
/* init */
|
2423
|
-
ip += (ip==base);
|
2424
|
-
ctx->nextToUpdate3 = ctx->nextToUpdate;
|
2425
|
-
{ U32 const maxRep = (U32)(ip-base);
|
2426
|
-
if (offset_2 > maxRep) savedOffset = offset_2, offset_2 = 0;
|
2427
|
-
if (offset_1 > maxRep) savedOffset = offset_1, offset_1 = 0;
|
2428
|
-
}
|
2429
|
-
|
2430
|
-
/* Match Loop */
|
2431
|
-
while (ip < ilimit) {
|
2432
|
-
size_t matchLength=0;
|
2433
|
-
size_t offset=0;
|
2434
|
-
const BYTE* start=ip+1;
|
2435
|
-
|
2436
|
-
/* check repCode */
|
2437
|
-
if ((offset_1>0) & (MEM_read32(ip+1) == MEM_read32(ip+1 - offset_1))) {
|
2438
|
-
/* repcode : we take it */
|
2439
|
-
matchLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;
|
2440
|
-
if (depth==0) goto _storeSequence;
|
2441
|
-
}
|
2442
|
-
|
2443
|
-
/* first search (depth 0) */
|
2444
|
-
{ size_t offsetFound = 99999999;
|
2445
|
-
size_t const ml2 = searchMax(ctx, ip, iend, &offsetFound, maxSearches, mls);
|
2446
|
-
if (ml2 > matchLength)
|
2447
|
-
matchLength = ml2, start = ip, offset=offsetFound;
|
2448
|
-
}
|
2449
|
-
|
2450
|
-
if (matchLength < 4) {
|
2451
|
-
ip += ((ip-anchor) >> g_searchStrength) + 1; /* jump faster over incompressible sections */
|
2452
|
-
continue;
|
2453
|
-
}
|
2454
|
-
|
2455
|
-
/* let's try to find a better solution */
|
2456
|
-
if (depth>=1)
|
2457
|
-
while (ip<ilimit) {
|
2458
|
-
ip ++;
|
2459
|
-
if ((offset) && ((offset_1>0) & (MEM_read32(ip) == MEM_read32(ip - offset_1)))) {
|
2460
|
-
size_t const mlRep = ZSTD_count(ip+4, ip+4-offset_1, iend) + 4;
|
2461
|
-
int const gain2 = (int)(mlRep * 3);
|
2462
|
-
int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)offset+1) + 1);
|
2463
|
-
if ((mlRep >= 4) && (gain2 > gain1))
|
2464
|
-
matchLength = mlRep, offset = 0, start = ip;
|
2465
|
-
}
|
2466
|
-
{ size_t offset2=99999999;
|
2467
|
-
size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
|
2468
|
-
int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
|
2469
|
-
int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 4);
|
2470
|
-
if ((ml2 >= 4) && (gain2 > gain1)) {
|
2471
|
-
matchLength = ml2, offset = offset2, start = ip;
|
2472
|
-
continue; /* search a better one */
|
2473
|
-
} }
|
2474
|
-
|
2475
|
-
/* let's find an even better one */
|
2476
|
-
if ((depth==2) && (ip<ilimit)) {
|
2477
|
-
ip ++;
|
2478
|
-
if ((offset) && ((offset_1>0) & (MEM_read32(ip) == MEM_read32(ip - offset_1)))) {
|
2479
|
-
size_t const ml2 = ZSTD_count(ip+4, ip+4-offset_1, iend) + 4;
|
2480
|
-
int const gain2 = (int)(ml2 * 4);
|
2481
|
-
int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 1);
|
2482
|
-
if ((ml2 >= 4) && (gain2 > gain1))
|
2483
|
-
matchLength = ml2, offset = 0, start = ip;
|
2484
|
-
}
|
2485
|
-
{ size_t offset2=99999999;
|
2486
|
-
size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
|
2487
|
-
int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
|
2488
|
-
int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 7);
|
2489
|
-
if ((ml2 >= 4) && (gain2 > gain1)) {
|
2490
|
-
matchLength = ml2, offset = offset2, start = ip;
|
2491
|
-
continue;
|
2492
|
-
} } }
|
2493
|
-
break; /* nothing found : store previous solution */
|
2494
|
-
}
|
2495
|
-
|
2496
|
-
/* NOTE:
|
2497
|
-
* start[-offset+ZSTD_REP_MOVE-1] is undefined behavior.
|
2498
|
-
* (-offset+ZSTD_REP_MOVE-1) is unsigned, and is added to start, which
|
2499
|
-
* overflows the pointer, which is undefined behavior.
|
2500
|
-
*/
|
2501
|
-
/* catch up */
|
2502
|
-
if (offset) {
|
2503
|
-
while ( (start > anchor)
|
2504
|
-
&& (start > base+offset-ZSTD_REP_MOVE)
|
2505
|
-
&& (start[-1] == (start-offset+ZSTD_REP_MOVE)[-1]) ) /* only search for offset within prefix */
|
2506
|
-
{ start--; matchLength++; }
|
2507
|
-
offset_2 = offset_1; offset_1 = (U32)(offset - ZSTD_REP_MOVE);
|
2508
|
-
}
|
2509
|
-
/* store sequence */
|
2510
|
-
_storeSequence:
|
2511
|
-
{ size_t const litLength = start - anchor;
|
2512
|
-
ZSTD_storeSeq(seqStorePtr, litLength, anchor, (U32)offset, matchLength-MINMATCH);
|
2513
|
-
anchor = ip = start + matchLength;
|
2514
|
-
}
|
2515
|
-
|
2516
|
-
/* check immediate repcode */
|
2517
|
-
while ( (ip <= ilimit)
|
2518
|
-
&& ((offset_2>0)
|
2519
|
-
& (MEM_read32(ip) == MEM_read32(ip - offset_2)) )) {
|
2520
|
-
/* store sequence */
|
2521
|
-
matchLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;
|
2522
|
-
offset = offset_2; offset_2 = offset_1; offset_1 = (U32)offset; /* swap repcodes */
|
2523
|
-
ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, matchLength-MINMATCH);
|
2524
|
-
ip += matchLength;
|
2525
|
-
anchor = ip;
|
2526
|
-
continue; /* faster when present ... (?) */
|
2527
|
-
} }
|
2528
|
-
|
2529
|
-
/* Save reps for next block */
|
2530
|
-
seqStorePtr->repToConfirm[0] = offset_1 ? offset_1 : savedOffset;
|
2531
|
-
seqStorePtr->repToConfirm[1] = offset_2 ? offset_2 : savedOffset;
|
2532
|
-
|
2533
|
-
/* Last Literals */
|
2534
|
-
{ size_t const lastLLSize = iend - anchor;
|
2535
|
-
memcpy(seqStorePtr->lit, anchor, lastLLSize);
|
2536
|
-
seqStorePtr->lit += lastLLSize;
|
2537
|
-
}
|
2538
|
-
}
|
2539
|
-
|
2540
|
-
|
2541
|
-
static void ZSTD_compressBlock_btlazy2(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
|
2542
|
-
{
|
2543
|
-
ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 1, 2);
|
2544
|
-
}
|
2545
|
-
|
2546
|
-
static void ZSTD_compressBlock_lazy2(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
|
2547
|
-
{
|
2548
|
-
ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 0, 2);
|
2549
|
-
}
|
2550
|
-
|
2551
|
-
static void ZSTD_compressBlock_lazy(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
|
2552
|
-
{
|
2553
|
-
ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 0, 1);
|
2554
|
-
}
|
2555
|
-
|
2556
|
-
static void ZSTD_compressBlock_greedy(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
|
2557
|
-
{
|
2558
|
-
ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 0, 0);
|
2559
|
-
}
|
2560
|
-
|
2561
|
-
|
2562
|
-
FORCE_INLINE_TEMPLATE
|
2563
|
-
void ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
|
2564
|
-
const void* src, size_t srcSize,
|
2565
|
-
const U32 searchMethod, const U32 depth)
|
2566
|
-
{
|
2567
|
-
seqStore_t* seqStorePtr = &(ctx->seqStore);
|
2568
|
-
const BYTE* const istart = (const BYTE*)src;
|
2569
|
-
const BYTE* ip = istart;
|
2570
|
-
const BYTE* anchor = istart;
|
2571
|
-
const BYTE* const iend = istart + srcSize;
|
2572
|
-
const BYTE* const ilimit = iend - 8;
|
2573
|
-
const BYTE* const base = ctx->base;
|
2574
|
-
const U32 dictLimit = ctx->dictLimit;
|
2575
|
-
const U32 lowestIndex = ctx->lowLimit;
|
2576
|
-
const BYTE* const prefixStart = base + dictLimit;
|
2577
|
-
const BYTE* const dictBase = ctx->dictBase;
|
2578
|
-
const BYTE* const dictEnd = dictBase + dictLimit;
|
2579
|
-
const BYTE* const dictStart = dictBase + ctx->lowLimit;
|
2580
|
-
|
2581
|
-
const U32 maxSearches = 1 << ctx->appliedParams.cParams.searchLog;
|
2582
|
-
const U32 mls = ctx->appliedParams.cParams.searchLength;
|
2583
|
-
|
2584
|
-
typedef size_t (*searchMax_f)(ZSTD_CCtx* zc, const BYTE* ip, const BYTE* iLimit,
|
2585
|
-
size_t* offsetPtr,
|
2586
|
-
U32 maxNbAttempts, U32 matchLengthSearch);
|
2587
|
-
searchMax_f searchMax = searchMethod ? ZSTD_BtFindBestMatch_selectMLS_extDict : ZSTD_HcFindBestMatch_extDict_selectMLS;
|
2588
|
-
|
2589
|
-
U32 offset_1 = seqStorePtr->rep[0], offset_2 = seqStorePtr->rep[1];
|
2590
|
-
|
2591
|
-
/* init */
|
2592
|
-
ctx->nextToUpdate3 = ctx->nextToUpdate;
|
2593
|
-
ip += (ip == prefixStart);
|
2594
|
-
|
2595
|
-
/* Match Loop */
|
2596
|
-
while (ip < ilimit) {
|
2597
|
-
size_t matchLength=0;
|
2598
|
-
size_t offset=0;
|
2599
|
-
const BYTE* start=ip+1;
|
2600
|
-
U32 current = (U32)(ip-base);
|
2601
|
-
|
2602
|
-
/* check repCode */
|
2603
|
-
{ const U32 repIndex = (U32)(current+1 - offset_1);
|
2604
|
-
const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
|
2605
|
-
const BYTE* const repMatch = repBase + repIndex;
|
2606
|
-
if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */
|
2607
|
-
if (MEM_read32(ip+1) == MEM_read32(repMatch)) {
|
2608
|
-
/* repcode detected we should take it */
|
2609
|
-
const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
|
2610
|
-
matchLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repEnd, prefixStart) + 4;
|
2611
|
-
if (depth==0) goto _storeSequence;
|
2612
|
-
} }
|
2613
|
-
|
2614
|
-
/* first search (depth 0) */
|
2615
|
-
{ size_t offsetFound = 99999999;
|
2616
|
-
size_t const ml2 = searchMax(ctx, ip, iend, &offsetFound, maxSearches, mls);
|
2617
|
-
if (ml2 > matchLength)
|
2618
|
-
matchLength = ml2, start = ip, offset=offsetFound;
|
1322
|
+
case set_compressed: {
|
1323
|
+
S16 norm[MaxSeq + 1];
|
1324
|
+
size_t nbSeq_1 = nbSeq;
|
1325
|
+
const U32 tableLog = FSE_optimalTableLog(FSELog, nbSeq, max);
|
1326
|
+
if (count[codeTable[nbSeq-1]] > 1) {
|
1327
|
+
count[codeTable[nbSeq-1]]--;
|
1328
|
+
nbSeq_1--;
|
2619
1329
|
}
|
2620
|
-
|
2621
|
-
|
2622
|
-
|
2623
|
-
|
1330
|
+
assert(nbSeq_1 > 1);
|
1331
|
+
CHECK_F(FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max));
|
1332
|
+
{ size_t const NCountSize = FSE_writeNCount(op, oend - op, norm, max, tableLog); /* overflow protected */
|
1333
|
+
if (FSE_isError(NCountSize)) return NCountSize;
|
1334
|
+
CHECK_F(FSE_buildCTable_wksp(CTable, norm, max, tableLog, workspace, workspaceSize));
|
1335
|
+
return NCountSize;
|
2624
1336
|
}
|
1337
|
+
}
|
1338
|
+
default: return assert(0), ERROR(GENERIC);
|
1339
|
+
}
|
1340
|
+
}
|
2625
1341
|
|
2626
|
-
|
2627
|
-
|
2628
|
-
|
2629
|
-
|
2630
|
-
|
2631
|
-
|
2632
|
-
|
2633
|
-
|
2634
|
-
|
2635
|
-
|
2636
|
-
if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */
|
2637
|
-
if (MEM_read32(ip) == MEM_read32(repMatch)) {
|
2638
|
-
/* repcode detected */
|
2639
|
-
const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
|
2640
|
-
size_t const repLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd, prefixStart) + 4;
|
2641
|
-
int const gain2 = (int)(repLength * 3);
|
2642
|
-
int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)offset+1) + 1);
|
2643
|
-
if ((repLength >= 4) && (gain2 > gain1))
|
2644
|
-
matchLength = repLength, offset = 0, start = ip;
|
2645
|
-
} }
|
2646
|
-
|
2647
|
-
/* search match, depth 1 */
|
2648
|
-
{ size_t offset2=99999999;
|
2649
|
-
size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
|
2650
|
-
int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
|
2651
|
-
int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 4);
|
2652
|
-
if ((ml2 >= 4) && (gain2 > gain1)) {
|
2653
|
-
matchLength = ml2, offset = offset2, start = ip;
|
2654
|
-
continue; /* search a better one */
|
2655
|
-
} }
|
2656
|
-
|
2657
|
-
/* let's find an even better one */
|
2658
|
-
if ((depth==2) && (ip<ilimit)) {
|
2659
|
-
ip ++;
|
2660
|
-
current++;
|
2661
|
-
/* check repCode */
|
2662
|
-
if (offset) {
|
2663
|
-
const U32 repIndex = (U32)(current - offset_1);
|
2664
|
-
const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
|
2665
|
-
const BYTE* const repMatch = repBase + repIndex;
|
2666
|
-
if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */
|
2667
|
-
if (MEM_read32(ip) == MEM_read32(repMatch)) {
|
2668
|
-
/* repcode detected */
|
2669
|
-
const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
|
2670
|
-
size_t const repLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd, prefixStart) + 4;
|
2671
|
-
int const gain2 = (int)(repLength * 4);
|
2672
|
-
int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 1);
|
2673
|
-
if ((repLength >= 4) && (gain2 > gain1))
|
2674
|
-
matchLength = repLength, offset = 0, start = ip;
|
2675
|
-
} }
|
2676
|
-
|
2677
|
-
/* search match, depth 2 */
|
2678
|
-
{ size_t offset2=99999999;
|
2679
|
-
size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
|
2680
|
-
int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
|
2681
|
-
int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 7);
|
2682
|
-
if ((ml2 >= 4) && (gain2 > gain1)) {
|
2683
|
-
matchLength = ml2, offset = offset2, start = ip;
|
2684
|
-
continue;
|
2685
|
-
} } }
|
2686
|
-
break; /* nothing found : store previous solution */
|
2687
|
-
}
|
1342
|
+
MEM_STATIC size_t ZSTD_encodeSequences(void* dst, size_t dstCapacity,
|
1343
|
+
FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,
|
1344
|
+
FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,
|
1345
|
+
FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,
|
1346
|
+
seqDef const* sequences, size_t nbSeq, int longOffsets)
|
1347
|
+
{
|
1348
|
+
BIT_CStream_t blockStream;
|
1349
|
+
FSE_CState_t stateMatchLength;
|
1350
|
+
FSE_CState_t stateOffsetBits;
|
1351
|
+
FSE_CState_t stateLitLength;
|
2688
1352
|
|
2689
|
-
|
2690
|
-
if (offset) {
|
2691
|
-
U32 const matchIndex = (U32)((start-base) - (offset - ZSTD_REP_MOVE));
|
2692
|
-
const BYTE* match = (matchIndex < dictLimit) ? dictBase + matchIndex : base + matchIndex;
|
2693
|
-
const BYTE* const mStart = (matchIndex < dictLimit) ? dictStart : prefixStart;
|
2694
|
-
while ((start>anchor) && (match>mStart) && (start[-1] == match[-1])) { start--; match--; matchLength++; } /* catch up */
|
2695
|
-
offset_2 = offset_1; offset_1 = (U32)(offset - ZSTD_REP_MOVE);
|
2696
|
-
}
|
1353
|
+
CHECK_E(BIT_initCStream(&blockStream, dst, dstCapacity), dstSize_tooSmall); /* not enough space remaining */
|
2697
1354
|
|
2698
|
-
|
2699
|
-
|
2700
|
-
|
2701
|
-
|
2702
|
-
|
1355
|
+
/* first symbols */
|
1356
|
+
FSE_initCState2(&stateMatchLength, CTable_MatchLength, mlCodeTable[nbSeq-1]);
|
1357
|
+
FSE_initCState2(&stateOffsetBits, CTable_OffsetBits, ofCodeTable[nbSeq-1]);
|
1358
|
+
FSE_initCState2(&stateLitLength, CTable_LitLength, llCodeTable[nbSeq-1]);
|
1359
|
+
BIT_addBits(&blockStream, sequences[nbSeq-1].litLength, LL_bits[llCodeTable[nbSeq-1]]);
|
1360
|
+
if (MEM_32bits()) BIT_flushBits(&blockStream);
|
1361
|
+
BIT_addBits(&blockStream, sequences[nbSeq-1].matchLength, ML_bits[mlCodeTable[nbSeq-1]]);
|
1362
|
+
if (MEM_32bits()) BIT_flushBits(&blockStream);
|
1363
|
+
if (longOffsets) {
|
1364
|
+
U32 const ofBits = ofCodeTable[nbSeq-1];
|
1365
|
+
int const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN-1);
|
1366
|
+
if (extraBits) {
|
1367
|
+
BIT_addBits(&blockStream, sequences[nbSeq-1].offset, extraBits);
|
1368
|
+
BIT_flushBits(&blockStream);
|
2703
1369
|
}
|
1370
|
+
BIT_addBits(&blockStream, sequences[nbSeq-1].offset >> extraBits,
|
1371
|
+
ofBits - extraBits);
|
1372
|
+
} else {
|
1373
|
+
BIT_addBits(&blockStream, sequences[nbSeq-1].offset, ofCodeTable[nbSeq-1]);
|
1374
|
+
}
|
1375
|
+
BIT_flushBits(&blockStream);
|
2704
1376
|
|
2705
|
-
|
2706
|
-
|
2707
|
-
const
|
2708
|
-
|
2709
|
-
|
2710
|
-
|
2711
|
-
|
2712
|
-
|
2713
|
-
|
2714
|
-
|
2715
|
-
|
2716
|
-
|
2717
|
-
|
2718
|
-
|
2719
|
-
|
1377
|
+
{ size_t n;
|
1378
|
+
for (n=nbSeq-2 ; n<nbSeq ; n--) { /* intentional underflow */
|
1379
|
+
BYTE const llCode = llCodeTable[n];
|
1380
|
+
BYTE const ofCode = ofCodeTable[n];
|
1381
|
+
BYTE const mlCode = mlCodeTable[n];
|
1382
|
+
U32 const llBits = LL_bits[llCode];
|
1383
|
+
U32 const ofBits = ofCode; /* 32b*/ /* 64b*/
|
1384
|
+
U32 const mlBits = ML_bits[mlCode];
|
1385
|
+
/* (7)*/ /* (7)*/
|
1386
|
+
FSE_encodeSymbol(&blockStream, &stateOffsetBits, ofCode); /* 15 */ /* 15 */
|
1387
|
+
FSE_encodeSymbol(&blockStream, &stateMatchLength, mlCode); /* 24 */ /* 24 */
|
1388
|
+
if (MEM_32bits()) BIT_flushBits(&blockStream); /* (7)*/
|
1389
|
+
FSE_encodeSymbol(&blockStream, &stateLitLength, llCode); /* 16 */ /* 33 */
|
1390
|
+
if (MEM_32bits() || (ofBits+mlBits+llBits >= 64-7-(LLFSELog+MLFSELog+OffFSELog)))
|
1391
|
+
BIT_flushBits(&blockStream); /* (7)*/
|
1392
|
+
BIT_addBits(&blockStream, sequences[n].litLength, llBits);
|
1393
|
+
if (MEM_32bits() && ((llBits+mlBits)>24)) BIT_flushBits(&blockStream);
|
1394
|
+
BIT_addBits(&blockStream, sequences[n].matchLength, mlBits);
|
1395
|
+
if (MEM_32bits() || (ofBits+mlBits+llBits > 56)) BIT_flushBits(&blockStream);
|
1396
|
+
if (longOffsets) {
|
1397
|
+
int const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN-1);
|
1398
|
+
if (extraBits) {
|
1399
|
+
BIT_addBits(&blockStream, sequences[n].offset, extraBits);
|
1400
|
+
BIT_flushBits(&blockStream); /* (7)*/
|
1401
|
+
}
|
1402
|
+
BIT_addBits(&blockStream, sequences[n].offset >> extraBits,
|
1403
|
+
ofBits - extraBits); /* 31 */
|
1404
|
+
} else {
|
1405
|
+
BIT_addBits(&blockStream, sequences[n].offset, ofBits); /* 31 */
|
2720
1406
|
}
|
2721
|
-
|
1407
|
+
BIT_flushBits(&blockStream); /* (7)*/
|
2722
1408
|
} }
|
2723
1409
|
|
2724
|
-
|
2725
|
-
|
1410
|
+
FSE_flushCState(&blockStream, &stateMatchLength);
|
1411
|
+
FSE_flushCState(&blockStream, &stateOffsetBits);
|
1412
|
+
FSE_flushCState(&blockStream, &stateLitLength);
|
2726
1413
|
|
2727
|
-
|
2728
|
-
|
2729
|
-
|
2730
|
-
seqStorePtr->lit += lastLLSize;
|
1414
|
+
{ size_t const streamSize = BIT_closeCStream(&blockStream);
|
1415
|
+
if (streamSize==0) return ERROR(dstSize_tooSmall); /* not enough space */
|
1416
|
+
return streamSize;
|
2731
1417
|
}
|
2732
1418
|
}
|
2733
1419
|
|
2734
|
-
|
2735
|
-
|
1420
|
+
MEM_STATIC size_t ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
|
1421
|
+
ZSTD_entropyCTables_t* entropy,
|
1422
|
+
ZSTD_compressionParameters const* cParams,
|
1423
|
+
void* dst, size_t dstCapacity)
|
2736
1424
|
{
|
2737
|
-
|
2738
|
-
|
1425
|
+
const int longOffsets = cParams->windowLog > STREAM_ACCUMULATOR_MIN;
|
1426
|
+
U32 count[MaxSeq+1];
|
1427
|
+
FSE_CTable* CTable_LitLength = entropy->litlengthCTable;
|
1428
|
+
FSE_CTable* CTable_OffsetBits = entropy->offcodeCTable;
|
1429
|
+
FSE_CTable* CTable_MatchLength = entropy->matchlengthCTable;
|
1430
|
+
U32 LLtype, Offtype, MLtype; /* compressed, raw or rle */
|
1431
|
+
const seqDef* const sequences = seqStorePtr->sequencesStart;
|
1432
|
+
const BYTE* const ofCodeTable = seqStorePtr->ofCode;
|
1433
|
+
const BYTE* const llCodeTable = seqStorePtr->llCode;
|
1434
|
+
const BYTE* const mlCodeTable = seqStorePtr->mlCode;
|
1435
|
+
BYTE* const ostart = (BYTE*)dst;
|
1436
|
+
BYTE* const oend = ostart + dstCapacity;
|
1437
|
+
BYTE* op = ostart;
|
1438
|
+
size_t const nbSeq = seqStorePtr->sequences - seqStorePtr->sequencesStart;
|
1439
|
+
BYTE* seqHead;
|
2739
1440
|
|
2740
|
-
|
2741
|
-
{
|
2742
|
-
ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 0, 1);
|
2743
|
-
}
|
1441
|
+
ZSTD_STATIC_ASSERT(sizeof(entropy->workspace) >= (1<<MAX(MLFSELog,LLFSELog)));
|
2744
1442
|
|
2745
|
-
|
2746
|
-
{
|
2747
|
-
|
2748
|
-
|
1443
|
+
/* Compress literals */
|
1444
|
+
{ const BYTE* const literals = seqStorePtr->litStart;
|
1445
|
+
size_t const litSize = seqStorePtr->lit - literals;
|
1446
|
+
size_t const cSize = ZSTD_compressLiterals(
|
1447
|
+
entropy, cParams->strategy, op, dstCapacity, literals, litSize);
|
1448
|
+
if (ZSTD_isError(cSize))
|
1449
|
+
return cSize;
|
1450
|
+
op += cSize;
|
1451
|
+
}
|
2749
1452
|
|
2750
|
-
|
2751
|
-
|
2752
|
-
|
2753
|
-
|
1453
|
+
/* Sequences Header */
|
1454
|
+
if ((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead */) return ERROR(dstSize_tooSmall);
|
1455
|
+
if (nbSeq < 0x7F) *op++ = (BYTE)nbSeq;
|
1456
|
+
else if (nbSeq < LONGNBSEQ) op[0] = (BYTE)((nbSeq>>8) + 0x80), op[1] = (BYTE)nbSeq, op+=2;
|
1457
|
+
else op[0]=0xFF, MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ)), op+=3;
|
1458
|
+
if (nbSeq==0) return op - ostart;
|
2754
1459
|
|
1460
|
+
/* seqHead : flags for FSE encoding type */
|
1461
|
+
seqHead = op++;
|
2755
1462
|
|
2756
|
-
/*
|
2757
|
-
|
1463
|
+
/* convert length/distances into codes */
|
1464
|
+
ZSTD_seqToCodes(seqStorePtr);
|
1465
|
+
/* CTable for Literal Lengths */
|
1466
|
+
{ U32 max = MaxLL;
|
1467
|
+
size_t const mostFrequent = FSE_countFast_wksp(count, &max, llCodeTable, nbSeq, entropy->workspace);
|
1468
|
+
LLtype = ZSTD_selectEncodingType(&entropy->litlength_repeatMode, mostFrequent, nbSeq, LL_defaultNormLog, ZSTD_defaultAllowed);
|
1469
|
+
{ size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_LitLength, LLFSELog, (symbolEncodingType_e)LLtype,
|
1470
|
+
count, max, llCodeTable, nbSeq, LL_defaultNorm, LL_defaultNormLog, MaxLL,
|
1471
|
+
entropy->workspace, sizeof(entropy->workspace));
|
1472
|
+
if (ZSTD_isError(countSize)) return countSize;
|
1473
|
+
op += countSize;
|
1474
|
+
} }
|
1475
|
+
/* CTable for Offsets */
|
1476
|
+
{ U32 max = MaxOff;
|
1477
|
+
size_t const mostFrequent = FSE_countFast_wksp(count, &max, ofCodeTable, nbSeq, entropy->workspace);
|
1478
|
+
/* We can only use the basic table if max <= DefaultMaxOff, otherwise the offsets are too large */
|
1479
|
+
ZSTD_defaultPolicy_e const defaultPolicy = max <= DefaultMaxOff ? ZSTD_defaultAllowed : ZSTD_defaultDisallowed;
|
1480
|
+
Offtype = ZSTD_selectEncodingType(&entropy->offcode_repeatMode, mostFrequent, nbSeq, OF_defaultNormLog, defaultPolicy);
|
1481
|
+
{ size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_OffsetBits, OffFSELog, (symbolEncodingType_e)Offtype,
|
1482
|
+
count, max, ofCodeTable, nbSeq, OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
|
1483
|
+
entropy->workspace, sizeof(entropy->workspace));
|
1484
|
+
if (ZSTD_isError(countSize)) return countSize;
|
1485
|
+
op += countSize;
|
1486
|
+
} }
|
1487
|
+
/* CTable for MatchLengths */
|
1488
|
+
{ U32 max = MaxML;
|
1489
|
+
size_t const mostFrequent = FSE_countFast_wksp(count, &max, mlCodeTable, nbSeq, entropy->workspace);
|
1490
|
+
MLtype = ZSTD_selectEncodingType(&entropy->matchlength_repeatMode, mostFrequent, nbSeq, ML_defaultNormLog, ZSTD_defaultAllowed);
|
1491
|
+
{ size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_MatchLength, MLFSELog, (symbolEncodingType_e)MLtype,
|
1492
|
+
count, max, mlCodeTable, nbSeq, ML_defaultNorm, ML_defaultNormLog, MaxML,
|
1493
|
+
entropy->workspace, sizeof(entropy->workspace));
|
1494
|
+
if (ZSTD_isError(countSize)) return countSize;
|
1495
|
+
op += countSize;
|
1496
|
+
} }
|
2758
1497
|
|
2759
|
-
|
2760
|
-
{
|
2761
|
-
#ifdef ZSTD_OPT_H_91842398743
|
2762
|
-
ZSTD_compressBlock_opt_generic(ctx, src, srcSize, 0);
|
2763
|
-
#else
|
2764
|
-
(void)ctx; (void)src; (void)srcSize;
|
2765
|
-
return;
|
2766
|
-
#endif
|
2767
|
-
}
|
1498
|
+
*seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2));
|
2768
1499
|
|
2769
|
-
|
2770
|
-
|
2771
|
-
|
2772
|
-
|
2773
|
-
|
2774
|
-
|
2775
|
-
|
2776
|
-
|
2777
|
-
}
|
1500
|
+
{ size_t const streamSize = ZSTD_encodeSequences(op, oend - op,
|
1501
|
+
CTable_MatchLength, mlCodeTable,
|
1502
|
+
CTable_OffsetBits, ofCodeTable,
|
1503
|
+
CTable_LitLength, llCodeTable,
|
1504
|
+
sequences, nbSeq, longOffsets);
|
1505
|
+
if (ZSTD_isError(streamSize)) return streamSize;
|
1506
|
+
op += streamSize;
|
1507
|
+
}
|
2778
1508
|
|
2779
|
-
|
2780
|
-
{
|
2781
|
-
#ifdef ZSTD_OPT_H_91842398743
|
2782
|
-
ZSTD_compressBlock_opt_extDict_generic(ctx, src, srcSize, 0);
|
2783
|
-
#else
|
2784
|
-
(void)ctx; (void)src; (void)srcSize;
|
2785
|
-
return;
|
2786
|
-
#endif
|
1509
|
+
return op - ostart;
|
2787
1510
|
}
|
2788
1511
|
|
2789
|
-
|
1512
|
+
MEM_STATIC size_t ZSTD_compressSequences(seqStore_t* seqStorePtr,
|
1513
|
+
ZSTD_entropyCTables_t* entropy,
|
1514
|
+
ZSTD_compressionParameters const* cParams,
|
1515
|
+
void* dst, size_t dstCapacity,
|
1516
|
+
size_t srcSize)
|
2790
1517
|
{
|
2791
|
-
|
2792
|
-
|
2793
|
-
|
2794
|
-
|
2795
|
-
|
2796
|
-
|
2797
|
-
|
1518
|
+
size_t const cSize = ZSTD_compressSequences_internal(seqStorePtr, entropy, cParams,
|
1519
|
+
dst, dstCapacity);
|
1520
|
+
size_t const minGain = ZSTD_minGain(srcSize);
|
1521
|
+
size_t const maxCSize = srcSize - minGain;
|
1522
|
+
/* If the srcSize <= dstCapacity, then there is enough space to write a
|
1523
|
+
* raw uncompressed block. Since we ran out of space, the block must not
|
1524
|
+
* be compressible, so fall back to a raw uncompressed block.
|
1525
|
+
*/
|
1526
|
+
int const uncompressibleError = cSize == ERROR(dstSize_tooSmall) && srcSize <= dstCapacity;
|
1527
|
+
|
1528
|
+
if (ZSTD_isError(cSize) && !uncompressibleError)
|
1529
|
+
return cSize;
|
1530
|
+
/* Check compressibility */
|
1531
|
+
if (cSize >= maxCSize || uncompressibleError) {
|
1532
|
+
entropy->hufCTable_repeatMode = HUF_repeat_none;
|
1533
|
+
entropy->offcode_repeatMode = FSE_repeat_none;
|
1534
|
+
entropy->matchlength_repeatMode = FSE_repeat_none;
|
1535
|
+
entropy->litlength_repeatMode = FSE_repeat_none;
|
1536
|
+
return 0;
|
1537
|
+
}
|
1538
|
+
assert(!ZSTD_isError(cSize));
|
2798
1539
|
|
1540
|
+
/* confirm repcodes */
|
1541
|
+
{ int i; for (i=0; i<ZSTD_REP_NUM; i++) seqStorePtr->rep[i] = seqStorePtr->repToConfirm[i]; }
|
1542
|
+
return cSize;
|
1543
|
+
}
|
2799
1544
|
|
2800
1545
|
/* ZSTD_selectBlockCompressor() :
|
1546
|
+
* Not static, but internal use only (used by long distance matcher)
|
2801
1547
|
* assumption : strat is a valid strategy */
|
2802
|
-
typedef
|
2803
|
-
|
1548
|
+
typedef size_t (*ZSTD_blockCompressor) (ZSTD_CCtx* ctx, const void* src, size_t srcSize);
|
1549
|
+
ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, int extDict)
|
2804
1550
|
{
|
2805
1551
|
static const ZSTD_blockCompressor blockCompressor[2][(unsigned)ZSTD_btultra+1] = {
|
2806
1552
|
{ ZSTD_compressBlock_fast /* default for 0 */,
|
@@ -2819,18 +1565,37 @@ static ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, int
|
|
2819
1565
|
return blockCompressor[extDict!=0][(U32)strat];
|
2820
1566
|
}
|
2821
1567
|
|
1568
|
+
static void ZSTD_storeLastLiterals(seqStore_t* seqStorePtr,
|
1569
|
+
const BYTE* anchor, size_t lastLLSize)
|
1570
|
+
{
|
1571
|
+
memcpy(seqStorePtr->lit, anchor, lastLLSize);
|
1572
|
+
seqStorePtr->lit += lastLLSize;
|
1573
|
+
}
|
2822
1574
|
|
2823
1575
|
static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
|
2824
1576
|
{
|
2825
|
-
ZSTD_blockCompressor const blockCompressor = ZSTD_selectBlockCompressor(zc->appliedParams.cParams.strategy, zc->lowLimit < zc->dictLimit);
|
2826
1577
|
const BYTE* const base = zc->base;
|
2827
1578
|
const BYTE* const istart = (const BYTE*)src;
|
2828
1579
|
const U32 current = (U32)(istart-base);
|
1580
|
+
size_t lastLLSize;
|
1581
|
+
const BYTE* anchor;
|
1582
|
+
U32 const extDict = zc->lowLimit < zc->dictLimit;
|
1583
|
+
const ZSTD_blockCompressor blockCompressor =
|
1584
|
+
zc->appliedParams.ldmParams.enableLdm
|
1585
|
+
? (extDict ? ZSTD_compressBlock_ldm_extDict : ZSTD_compressBlock_ldm)
|
1586
|
+
: ZSTD_selectBlockCompressor(zc->appliedParams.cParams.strategy, extDict);
|
1587
|
+
|
2829
1588
|
if (srcSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1) return 0; /* don't even attempt compression below a certain srcSize */
|
2830
1589
|
ZSTD_resetSeqStore(&(zc->seqStore));
|
2831
1590
|
if (current > zc->nextToUpdate + 384)
|
2832
1591
|
zc->nextToUpdate = current - MIN(192, (U32)(current - zc->nextToUpdate - 384)); /* limited update after finding a very long match */
|
2833
|
-
|
1592
|
+
|
1593
|
+
lastLLSize = blockCompressor(zc, src, srcSize);
|
1594
|
+
|
1595
|
+
/* Last literals */
|
1596
|
+
anchor = (const BYTE*)src + srcSize - lastLLSize;
|
1597
|
+
ZSTD_storeLastLiterals(&zc->seqStore, anchor, lastLLSize);
|
1598
|
+
|
2834
1599
|
return ZSTD_compressSequences(&zc->seqStore, zc->entropy, &zc->appliedParams.cParams, dst, dstCapacity, srcSize);
|
2835
1600
|
}
|
2836
1601
|
|
@@ -2852,7 +1617,7 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
|
|
2852
1617
|
const BYTE* ip = (const BYTE*)src;
|
2853
1618
|
BYTE* const ostart = (BYTE*)dst;
|
2854
1619
|
BYTE* op = ostart;
|
2855
|
-
U32 const maxDist = 1 << cctx->appliedParams.cParams.windowLog;
|
1620
|
+
U32 const maxDist = (U32)1 << cctx->appliedParams.cParams.windowLog;
|
2856
1621
|
|
2857
1622
|
if (cctx->appliedParams.fParams.checksumFlag && srcSize)
|
2858
1623
|
XXH64_update(&cctx->xxhState, src, srcSize);
|
@@ -2865,13 +1630,33 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
|
|
2865
1630
|
return ERROR(dstSize_tooSmall); /* not enough space to store compressed block */
|
2866
1631
|
if (remaining < blockSize) blockSize = remaining;
|
2867
1632
|
|
2868
|
-
/* preemptive overflow correction
|
1633
|
+
/* preemptive overflow correction:
|
1634
|
+
* 1. correction is large enough:
|
1635
|
+
* lowLimit > (3<<29) ==> current > 3<<29 + 1<<windowLog - blockSize
|
1636
|
+
* 1<<windowLog <= newCurrent < 1<<chainLog + 1<<windowLog
|
1637
|
+
*
|
1638
|
+
* current - newCurrent
|
1639
|
+
* > (3<<29 + 1<<windowLog - blockSize) - (1<<windowLog + 1<<chainLog)
|
1640
|
+
* > (3<<29 - blockSize) - (1<<chainLog)
|
1641
|
+
* > (3<<29 - blockSize) - (1<<30) (NOTE: chainLog <= 30)
|
1642
|
+
* > 1<<29 - 1<<17
|
1643
|
+
*
|
1644
|
+
* 2. (ip+blockSize - cctx->base) doesn't overflow:
|
1645
|
+
* In 32 bit mode we limit windowLog to 30 so we don't get
|
1646
|
+
* differences larger than 1<<31-1.
|
1647
|
+
* 3. cctx->lowLimit < 1<<32:
|
1648
|
+
* windowLog <= 31 ==> 3<<29 + 1<<windowLog < 7<<29 < 1<<32.
|
1649
|
+
*/
|
2869
1650
|
if (cctx->lowLimit > (3U<<29)) {
|
2870
|
-
U32 const cycleMask = (1 << ZSTD_cycleLog(cctx->appliedParams.cParams.
|
1651
|
+
U32 const cycleMask = ((U32)1 << ZSTD_cycleLog(cctx->appliedParams.cParams.chainLog, cctx->appliedParams.cParams.strategy)) - 1;
|
2871
1652
|
U32 const current = (U32)(ip - cctx->base);
|
2872
|
-
U32 const newCurrent = (current & cycleMask) + (1 << cctx->appliedParams.cParams.windowLog);
|
1653
|
+
U32 const newCurrent = (current & cycleMask) + ((U32)1 << cctx->appliedParams.cParams.windowLog);
|
2873
1654
|
U32 const correction = current - newCurrent;
|
2874
|
-
ZSTD_STATIC_ASSERT(
|
1655
|
+
ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30);
|
1656
|
+
ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30);
|
1657
|
+
ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31);
|
1658
|
+
assert(current > newCurrent);
|
1659
|
+
assert(correction > 1<<28); /* Loose bound, should be about 1<<29 */
|
2875
1660
|
ZSTD_reduceIndex(cctx, correction);
|
2876
1661
|
cctx->base += correction;
|
2877
1662
|
cctx->dictBase += correction;
|
@@ -2879,6 +1664,7 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
|
|
2879
1664
|
cctx->dictLimit -= correction;
|
2880
1665
|
if (cctx->nextToUpdate < correction) cctx->nextToUpdate = 0;
|
2881
1666
|
else cctx->nextToUpdate -= correction;
|
1667
|
+
DEBUGLOG(4, "Correction of 0x%x bytes to lowLimit=0x%x\n", correction, cctx->lowLimit);
|
2882
1668
|
}
|
2883
1669
|
|
2884
1670
|
if ((U32)(ip+blockSize - cctx->base) > cctx->loadedDictEnd + maxDist) {
|
@@ -2915,25 +1701,29 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
|
|
2915
1701
|
|
2916
1702
|
|
2917
1703
|
static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
|
2918
|
-
|
1704
|
+
ZSTD_CCtx_params params, U64 pledgedSrcSize, U32 dictID)
|
2919
1705
|
{ BYTE* const op = (BYTE*)dst;
|
2920
1706
|
U32 const dictIDSizeCodeLength = (dictID>0) + (dictID>=256) + (dictID>=65536); /* 0-3 */
|
2921
1707
|
U32 const dictIDSizeCode = params.fParams.noDictIDFlag ? 0 : dictIDSizeCodeLength; /* 0-3 */
|
2922
1708
|
U32 const checksumFlag = params.fParams.checksumFlag>0;
|
2923
|
-
U32 const windowSize =
|
1709
|
+
U32 const windowSize = (U32)1 << params.cParams.windowLog;
|
2924
1710
|
U32 const singleSegment = params.fParams.contentSizeFlag && (windowSize >= pledgedSrcSize);
|
2925
1711
|
BYTE const windowLogByte = (BYTE)((params.cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3);
|
2926
1712
|
U32 const fcsCode = params.fParams.contentSizeFlag ?
|
2927
1713
|
(pledgedSrcSize>=256) + (pledgedSrcSize>=65536+256) + (pledgedSrcSize>=0xFFFFFFFFU) : 0; /* 0-3 */
|
2928
1714
|
BYTE const frameHeaderDecriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag<<2) + (singleSegment<<5) + (fcsCode<<6) );
|
2929
|
-
size_t pos;
|
1715
|
+
size_t pos=0;
|
2930
1716
|
|
2931
1717
|
if (dstCapacity < ZSTD_frameHeaderSize_max) return ERROR(dstSize_tooSmall);
|
2932
|
-
DEBUGLOG(
|
1718
|
+
DEBUGLOG(4, "ZSTD_writeFrameHeader : dictIDFlag : %u ; dictID : %u ; dictIDSizeCode : %u",
|
2933
1719
|
!params.fParams.noDictIDFlag, dictID, dictIDSizeCode);
|
2934
1720
|
|
2935
|
-
|
2936
|
-
|
1721
|
+
if (params.format == ZSTD_f_zstd1) {
|
1722
|
+
DEBUGLOG(4, "writing zstd magic number");
|
1723
|
+
MEM_writeLE32(dst, ZSTD_MAGICNUMBER);
|
1724
|
+
pos = 4;
|
1725
|
+
}
|
1726
|
+
op[pos++] = frameHeaderDecriptionByte;
|
2937
1727
|
if (!singleSegment) op[pos++] = windowLogByte;
|
2938
1728
|
switch(dictIDSizeCode)
|
2939
1729
|
{
|
@@ -2969,7 +1759,7 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
|
|
2969
1759
|
|
2970
1760
|
if (frame && (cctx->stage==ZSTDcs_init)) {
|
2971
1761
|
fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, cctx->appliedParams,
|
2972
|
-
|
1762
|
+
cctx->pledgedSrcSizePlusOne-1, cctx->dictID);
|
2973
1763
|
if (ZSTD_isError(fhSize)) return fhSize;
|
2974
1764
|
dstCapacity -= fhSize;
|
2975
1765
|
dst = (char*)dst + fhSize;
|
@@ -3018,11 +1808,9 @@ size_t ZSTD_compressContinue (ZSTD_CCtx* cctx,
|
|
3018
1808
|
|
3019
1809
|
size_t ZSTD_getBlockSize(const ZSTD_CCtx* cctx)
|
3020
1810
|
{
|
3021
|
-
|
3022
|
-
|
3023
|
-
|
3024
|
-
ZSTD_getCParams(cLevel, 0, 0);
|
3025
|
-
return MIN (ZSTD_BLOCKSIZE_MAX, 1 << cParams.windowLog);
|
1811
|
+
ZSTD_compressionParameters const cParams =
|
1812
|
+
ZSTD_getCParamsFromCCtxParams(cctx->appliedParams, 0, 0);
|
1813
|
+
return MIN (ZSTD_BLOCKSIZE_MAX, (U32)1 << cParams.windowLog);
|
3026
1814
|
}
|
3027
1815
|
|
3028
1816
|
size_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
|
@@ -3046,7 +1834,7 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_CCtx* zc, const void* src, size_t
|
|
3046
1834
|
zc->dictBase = zc->base;
|
3047
1835
|
zc->base += ip - zc->nextSrc;
|
3048
1836
|
zc->nextToUpdate = zc->dictLimit;
|
3049
|
-
zc->loadedDictEnd = zc->forceWindow ? 0 : (U32)(iend - zc->base);
|
1837
|
+
zc->loadedDictEnd = zc->appliedParams.forceWindow ? 0 : (U32)(iend - zc->base);
|
3050
1838
|
|
3051
1839
|
zc->nextSrc = iend;
|
3052
1840
|
if (srcSize <= HASH_READ_SIZE) return 0;
|
@@ -3056,7 +1844,6 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_CCtx* zc, const void* src, size_t
|
|
3056
1844
|
case ZSTD_fast:
|
3057
1845
|
ZSTD_fillHashTable (zc, iend, zc->appliedParams.cParams.searchLength);
|
3058
1846
|
break;
|
3059
|
-
|
3060
1847
|
case ZSTD_dfast:
|
3061
1848
|
ZSTD_fillDoubleHashTable (zc, iend, zc->appliedParams.cParams.searchLength);
|
3062
1849
|
break;
|
@@ -3072,7 +1859,7 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_CCtx* zc, const void* src, size_t
|
|
3072
1859
|
case ZSTD_btopt:
|
3073
1860
|
case ZSTD_btultra:
|
3074
1861
|
if (srcSize >= HASH_READ_SIZE)
|
3075
|
-
ZSTD_updateTree(zc, iend-HASH_READ_SIZE, iend, 1 << zc->appliedParams.cParams.searchLog, zc->appliedParams.cParams.searchLength);
|
1862
|
+
ZSTD_updateTree(zc, iend-HASH_READ_SIZE, iend, (U32)1 << zc->appliedParams.cParams.searchLog, zc->appliedParams.cParams.searchLength);
|
3076
1863
|
break;
|
3077
1864
|
|
3078
1865
|
default:
|
@@ -3120,8 +1907,10 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_CCtx* cctx, const void* dict, size_t
|
|
3120
1907
|
cctx->dictID = cctx->appliedParams.fParams.noDictIDFlag ? 0 : MEM_readLE32(dictPtr);
|
3121
1908
|
dictPtr += 4;
|
3122
1909
|
|
3123
|
-
{
|
1910
|
+
{ unsigned maxSymbolValue = 255;
|
1911
|
+
size_t const hufHeaderSize = HUF_readCTable((HUF_CElt*)cctx->entropy->hufCTable, &maxSymbolValue, dictPtr, dictEnd-dictPtr);
|
3124
1912
|
if (HUF_isError(hufHeaderSize)) return ERROR(dictionary_corrupted);
|
1913
|
+
if (maxSymbolValue < 255) return ERROR(dictionary_corrupted);
|
3125
1914
|
dictPtr += hufHeaderSize;
|
3126
1915
|
}
|
3127
1916
|
|
@@ -3221,12 +2010,10 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
|
|
3221
2010
|
const void* dict, size_t dictSize,
|
3222
2011
|
ZSTD_dictMode_e dictMode,
|
3223
2012
|
const ZSTD_CDict* cdict,
|
3224
|
-
|
2013
|
+
ZSTD_CCtx_params params, U64 pledgedSrcSize,
|
3225
2014
|
ZSTD_buffered_policy_e zbuff)
|
3226
2015
|
{
|
3227
2016
|
DEBUGLOG(4, "ZSTD_compressBegin_internal");
|
3228
|
-
DEBUGLOG(4, "dict ? %s", dict ? "dict" : (cdict ? "cdict" : "none"));
|
3229
|
-
DEBUGLOG(4, "dictMode : %u", (U32)dictMode);
|
3230
2017
|
/* params are supposed to be fully validated at this point */
|
3231
2018
|
assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
|
3232
2019
|
assert(!((dict) && (cdict))); /* either dict or cdict, not both */
|
@@ -3242,6 +2029,19 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
|
|
3242
2029
|
return ZSTD_compress_insertDictionary(cctx, dict, dictSize, dictMode);
|
3243
2030
|
}
|
3244
2031
|
|
2032
|
+
size_t ZSTD_compressBegin_advanced_internal(
|
2033
|
+
ZSTD_CCtx* cctx,
|
2034
|
+
const void* dict, size_t dictSize,
|
2035
|
+
ZSTD_dictMode_e dictMode,
|
2036
|
+
ZSTD_CCtx_params params,
|
2037
|
+
unsigned long long pledgedSrcSize)
|
2038
|
+
{
|
2039
|
+
/* compression parameters verification and optimization */
|
2040
|
+
CHECK_F( ZSTD_checkCParams(params.cParams) );
|
2041
|
+
return ZSTD_compressBegin_internal(cctx, dict, dictSize, dictMode, NULL,
|
2042
|
+
params, pledgedSrcSize,
|
2043
|
+
ZSTDb_not_buffered);
|
2044
|
+
}
|
3245
2045
|
|
3246
2046
|
/*! ZSTD_compressBegin_advanced() :
|
3247
2047
|
* @return : 0, or an error code */
|
@@ -3249,21 +2049,22 @@ size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx,
|
|
3249
2049
|
const void* dict, size_t dictSize,
|
3250
2050
|
ZSTD_parameters params, unsigned long long pledgedSrcSize)
|
3251
2051
|
{
|
3252
|
-
|
3253
|
-
|
3254
|
-
return
|
3255
|
-
|
2052
|
+
ZSTD_CCtx_params const cctxParams =
|
2053
|
+
ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
|
2054
|
+
return ZSTD_compressBegin_advanced_internal(cctx, dict, dictSize, ZSTD_dm_auto,
|
2055
|
+
cctxParams,
|
2056
|
+
pledgedSrcSize);
|
3256
2057
|
}
|
3257
2058
|
|
3258
|
-
|
3259
2059
|
size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel)
|
3260
2060
|
{
|
3261
2061
|
ZSTD_parameters const params = ZSTD_getParams(compressionLevel, 0, dictSize);
|
2062
|
+
ZSTD_CCtx_params const cctxParams =
|
2063
|
+
ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
|
3262
2064
|
return ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dm_auto, NULL,
|
3263
|
-
|
2065
|
+
cctxParams, 0, ZSTDb_not_buffered);
|
3264
2066
|
}
|
3265
2067
|
|
3266
|
-
|
3267
2068
|
size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel)
|
3268
2069
|
{
|
3269
2070
|
return ZSTD_compressBegin_usingDict(cctx, NULL, 0, compressionLevel);
|
@@ -3324,9 +2125,9 @@ size_t ZSTD_compressEnd (ZSTD_CCtx* cctx,
|
|
3324
2125
|
endResult = ZSTD_writeEpilogue(cctx, (char*)dst + cSize, dstCapacity-cSize);
|
3325
2126
|
if (ZSTD_isError(endResult)) return endResult;
|
3326
2127
|
if (cctx->appliedParams.fParams.contentSizeFlag) { /* control src size */
|
3327
|
-
DEBUGLOG(
|
2128
|
+
DEBUGLOG(4, "end of frame : controlling src size");
|
3328
2129
|
if (cctx->pledgedSrcSizePlusOne != cctx->consumedSrcSize+1) {
|
3329
|
-
DEBUGLOG(
|
2130
|
+
DEBUGLOG(4, "error : pledgedSrcSize = %u, while realSrcSize = %u",
|
3330
2131
|
(U32)cctx->pledgedSrcSizePlusOne-1, (U32)cctx->consumedSrcSize);
|
3331
2132
|
return ERROR(srcSize_wrong);
|
3332
2133
|
} }
|
@@ -3340,9 +2141,13 @@ static size_t ZSTD_compress_internal (ZSTD_CCtx* cctx,
|
|
3340
2141
|
const void* dict,size_t dictSize,
|
3341
2142
|
ZSTD_parameters params)
|
3342
2143
|
{
|
3343
|
-
|
3344
|
-
|
3345
|
-
return
|
2144
|
+
ZSTD_CCtx_params const cctxParams =
|
2145
|
+
ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
|
2146
|
+
return ZSTD_compress_advanced_internal(cctx,
|
2147
|
+
dst, dstCapacity,
|
2148
|
+
src, srcSize,
|
2149
|
+
dict, dictSize,
|
2150
|
+
cctxParams);
|
3346
2151
|
}
|
3347
2152
|
|
3348
2153
|
size_t ZSTD_compress_advanced (ZSTD_CCtx* ctx,
|
@@ -3355,6 +2160,19 @@ size_t ZSTD_compress_advanced (ZSTD_CCtx* ctx,
|
|
3355
2160
|
return ZSTD_compress_internal(ctx, dst, dstCapacity, src, srcSize, dict, dictSize, params);
|
3356
2161
|
}
|
3357
2162
|
|
2163
|
+
/* Internal */
|
2164
|
+
size_t ZSTD_compress_advanced_internal(
|
2165
|
+
ZSTD_CCtx* cctx,
|
2166
|
+
void* dst, size_t dstCapacity,
|
2167
|
+
const void* src, size_t srcSize,
|
2168
|
+
const void* dict,size_t dictSize,
|
2169
|
+
ZSTD_CCtx_params params)
|
2170
|
+
{
|
2171
|
+
CHECK_F( ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dm_auto, NULL,
|
2172
|
+
params, srcSize, ZSTDb_not_buffered) );
|
2173
|
+
return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize);
|
2174
|
+
}
|
2175
|
+
|
3358
2176
|
size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize,
|
3359
2177
|
const void* dict, size_t dictSize, int compressionLevel)
|
3360
2178
|
{
|
@@ -3384,18 +2202,21 @@ size_t ZSTD_compress(void* dst, size_t dstCapacity, const void* src, size_t srcS
|
|
3384
2202
|
|
3385
2203
|
/*! ZSTD_estimateCDictSize_advanced() :
|
3386
2204
|
* Estimate amount of memory that will be needed to create a dictionary with following arguments */
|
3387
|
-
size_t ZSTD_estimateCDictSize_advanced(
|
2205
|
+
size_t ZSTD_estimateCDictSize_advanced(
|
2206
|
+
size_t dictSize, ZSTD_compressionParameters cParams,
|
2207
|
+
ZSTD_dictLoadMethod_e dictLoadMethod)
|
3388
2208
|
{
|
3389
2209
|
DEBUGLOG(5, "sizeof(ZSTD_CDict) : %u", (U32)sizeof(ZSTD_CDict));
|
3390
|
-
DEBUGLOG(5, "CCtx estimate : %u",
|
3391
|
-
|
3392
|
-
|
2210
|
+
DEBUGLOG(5, "CCtx estimate : %u",
|
2211
|
+
(U32)ZSTD_estimateCCtxSize_usingCParams(cParams));
|
2212
|
+
return sizeof(ZSTD_CDict) + ZSTD_estimateCCtxSize_usingCParams(cParams)
|
2213
|
+
+ (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize);
|
3393
2214
|
}
|
3394
2215
|
|
3395
2216
|
size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel)
|
3396
2217
|
{
|
3397
2218
|
ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, 0, dictSize);
|
3398
|
-
return ZSTD_estimateCDictSize_advanced(dictSize, cParams,
|
2219
|
+
return ZSTD_estimateCDictSize_advanced(dictSize, cParams, ZSTD_dlm_byCopy);
|
3399
2220
|
}
|
3400
2221
|
|
3401
2222
|
size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict)
|
@@ -3406,22 +2227,15 @@ size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict)
|
|
3406
2227
|
return ZSTD_sizeof_CCtx(cdict->refContext) + (cdict->dictBuffer ? cdict->dictContentSize : 0) + sizeof(*cdict);
|
3407
2228
|
}
|
3408
2229
|
|
3409
|
-
static ZSTD_parameters ZSTD_makeParams(ZSTD_compressionParameters cParams, ZSTD_frameParameters fParams)
|
3410
|
-
{
|
3411
|
-
ZSTD_parameters params;
|
3412
|
-
params.cParams = cParams;
|
3413
|
-
params.fParams = fParams;
|
3414
|
-
return params;
|
3415
|
-
}
|
3416
|
-
|
3417
2230
|
static size_t ZSTD_initCDict_internal(
|
3418
2231
|
ZSTD_CDict* cdict,
|
3419
2232
|
const void* dictBuffer, size_t dictSize,
|
3420
|
-
|
2233
|
+
ZSTD_dictLoadMethod_e dictLoadMethod,
|
2234
|
+
ZSTD_dictMode_e dictMode,
|
3421
2235
|
ZSTD_compressionParameters cParams)
|
3422
2236
|
{
|
3423
2237
|
DEBUGLOG(5, "ZSTD_initCDict_internal, mode %u", (U32)dictMode);
|
3424
|
-
if ((
|
2238
|
+
if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dictBuffer) || (!dictSize)) {
|
3425
2239
|
cdict->dictBuffer = NULL;
|
3426
2240
|
cdict->dictContent = dictBuffer;
|
3427
2241
|
} else {
|
@@ -3433,13 +2247,12 @@ static size_t ZSTD_initCDict_internal(
|
|
3433
2247
|
}
|
3434
2248
|
cdict->dictContentSize = dictSize;
|
3435
2249
|
|
3436
|
-
{
|
3437
|
-
|
3438
|
-
ZSTD_parameters const params = ZSTD_makeParams(cParams, fParams);
|
2250
|
+
{ ZSTD_CCtx_params cctxParams = cdict->refContext->requestedParams;
|
2251
|
+
cctxParams.cParams = cParams;
|
3439
2252
|
CHECK_F( ZSTD_compressBegin_internal(cdict->refContext,
|
3440
2253
|
cdict->dictContent, dictSize, dictMode,
|
3441
2254
|
NULL,
|
3442
|
-
|
2255
|
+
cctxParams, ZSTD_CONTENTSIZE_UNKNOWN,
|
3443
2256
|
ZSTDb_not_buffered) );
|
3444
2257
|
}
|
3445
2258
|
|
@@ -3447,7 +2260,8 @@ static size_t ZSTD_initCDict_internal(
|
|
3447
2260
|
}
|
3448
2261
|
|
3449
2262
|
ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize,
|
3450
|
-
|
2263
|
+
ZSTD_dictLoadMethod_e dictLoadMethod,
|
2264
|
+
ZSTD_dictMode_e dictMode,
|
3451
2265
|
ZSTD_compressionParameters cParams, ZSTD_customMem customMem)
|
3452
2266
|
{
|
3453
2267
|
DEBUGLOG(5, "ZSTD_createCDict_advanced, mode %u", (U32)dictMode);
|
@@ -3462,10 +2276,9 @@ ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize,
|
|
3462
2276
|
return NULL;
|
3463
2277
|
}
|
3464
2278
|
cdict->refContext = cctx;
|
3465
|
-
|
3466
2279
|
if (ZSTD_isError( ZSTD_initCDict_internal(cdict,
|
3467
2280
|
dictBuffer, dictSize,
|
3468
|
-
|
2281
|
+
dictLoadMethod, dictMode,
|
3469
2282
|
cParams) )) {
|
3470
2283
|
ZSTD_freeCDict(cdict);
|
3471
2284
|
return NULL;
|
@@ -3479,7 +2292,7 @@ ZSTD_CDict* ZSTD_createCDict(const void* dict, size_t dictSize, int compressionL
|
|
3479
2292
|
{
|
3480
2293
|
ZSTD_compressionParameters cParams = ZSTD_getCParams(compressionLevel, 0, dictSize);
|
3481
2294
|
return ZSTD_createCDict_advanced(dict, dictSize,
|
3482
|
-
|
2295
|
+
ZSTD_dlm_byCopy, ZSTD_dm_auto,
|
3483
2296
|
cParams, ZSTD_defaultCMem);
|
3484
2297
|
}
|
3485
2298
|
|
@@ -3487,7 +2300,7 @@ ZSTD_CDict* ZSTD_createCDict_byReference(const void* dict, size_t dictSize, int
|
|
3487
2300
|
{
|
3488
2301
|
ZSTD_compressionParameters cParams = ZSTD_getCParams(compressionLevel, 0, dictSize);
|
3489
2302
|
return ZSTD_createCDict_advanced(dict, dictSize,
|
3490
|
-
|
2303
|
+
ZSTD_dlm_byRef, ZSTD_dm_auto,
|
3491
2304
|
cParams, ZSTD_defaultCMem);
|
3492
2305
|
}
|
3493
2306
|
|
@@ -3517,11 +2330,12 @@ size_t ZSTD_freeCDict(ZSTD_CDict* cdict)
|
|
3517
2330
|
*/
|
3518
2331
|
ZSTD_CDict* ZSTD_initStaticCDict(void* workspace, size_t workspaceSize,
|
3519
2332
|
const void* dict, size_t dictSize,
|
3520
|
-
|
2333
|
+
ZSTD_dictLoadMethod_e dictLoadMethod,
|
2334
|
+
ZSTD_dictMode_e dictMode,
|
3521
2335
|
ZSTD_compressionParameters cParams)
|
3522
2336
|
{
|
3523
|
-
size_t const cctxSize =
|
3524
|
-
size_t const neededSize = sizeof(ZSTD_CDict) + (
|
2337
|
+
size_t const cctxSize = ZSTD_estimateCCtxSize_usingCParams(cParams);
|
2338
|
+
size_t const neededSize = sizeof(ZSTD_CDict) + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize)
|
3525
2339
|
+ cctxSize;
|
3526
2340
|
ZSTD_CDict* const cdict = (ZSTD_CDict*) workspace;
|
3527
2341
|
void* ptr;
|
@@ -3531,7 +2345,7 @@ ZSTD_CDict* ZSTD_initStaticCDict(void* workspace, size_t workspaceSize,
|
|
3531
2345
|
(U32)workspaceSize, (U32)neededSize, (U32)(workspaceSize < neededSize));
|
3532
2346
|
if (workspaceSize < neededSize) return NULL;
|
3533
2347
|
|
3534
|
-
if (
|
2348
|
+
if (dictLoadMethod == ZSTD_dlm_byCopy) {
|
3535
2349
|
memcpy(cdict+1, dict, dictSize);
|
3536
2350
|
dict = cdict+1;
|
3537
2351
|
ptr = (char*)workspace + sizeof(ZSTD_CDict) + dictSize;
|
@@ -3542,15 +2356,15 @@ ZSTD_CDict* ZSTD_initStaticCDict(void* workspace, size_t workspaceSize,
|
|
3542
2356
|
|
3543
2357
|
if (ZSTD_isError( ZSTD_initCDict_internal(cdict,
|
3544
2358
|
dict, dictSize,
|
3545
|
-
|
2359
|
+
ZSTD_dlm_byRef, dictMode,
|
3546
2360
|
cParams) ))
|
3547
2361
|
return NULL;
|
3548
2362
|
|
3549
2363
|
return cdict;
|
3550
2364
|
}
|
3551
2365
|
|
3552
|
-
|
3553
|
-
return
|
2366
|
+
ZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict) {
|
2367
|
+
return cdict->refContext->appliedParams.cParams;
|
3554
2368
|
}
|
3555
2369
|
|
3556
2370
|
/* ZSTD_compressBegin_usingCDict_advanced() :
|
@@ -3560,7 +2374,8 @@ size_t ZSTD_compressBegin_usingCDict_advanced(
|
|
3560
2374
|
ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize)
|
3561
2375
|
{
|
3562
2376
|
if (cdict==NULL) return ERROR(dictionary_wrong);
|
3563
|
-
{
|
2377
|
+
{ ZSTD_CCtx_params params = cctx->requestedParams;
|
2378
|
+
params.cParams = ZSTD_getCParamsFromCDict(cdict);
|
3564
2379
|
params.fParams = fParams;
|
3565
2380
|
DEBUGLOG(5, "ZSTD_compressBegin_usingCDict_advanced");
|
3566
2381
|
return ZSTD_compressBegin_internal(cctx,
|
@@ -3644,7 +2459,7 @@ size_t ZSTD_CStreamOutSize(void)
|
|
3644
2459
|
static size_t ZSTD_resetCStream_internal(ZSTD_CStream* zcs,
|
3645
2460
|
const void* dict, size_t dictSize, ZSTD_dictMode_e dictMode,
|
3646
2461
|
const ZSTD_CDict* cdict,
|
3647
|
-
|
2462
|
+
const ZSTD_CCtx_params params, unsigned long long pledgedSrcSize)
|
3648
2463
|
{
|
3649
2464
|
DEBUGLOG(4, "ZSTD_resetCStream_internal");
|
3650
2465
|
/* params are supposed to be fully validated at this point */
|
@@ -3668,13 +2483,11 @@ static size_t ZSTD_resetCStream_internal(ZSTD_CStream* zcs,
|
|
3668
2483
|
|
3669
2484
|
size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize)
|
3670
2485
|
{
|
3671
|
-
|
2486
|
+
ZSTD_CCtx_params params = zcs->requestedParams;
|
3672
2487
|
params.fParams.contentSizeFlag = (pledgedSrcSize > 0);
|
3673
|
-
|
3674
|
-
|
3675
|
-
|
3676
|
-
}
|
3677
|
-
return ZSTD_resetCStream_internal(zcs, NULL, 0, zcs->dictMode, zcs->cdict, params, pledgedSrcSize);
|
2488
|
+
params.cParams = ZSTD_getCParamsFromCCtxParams(params, pledgedSrcSize, 0);
|
2489
|
+
DEBUGLOG(4, "ZSTD_resetCStream");
|
2490
|
+
return ZSTD_resetCStream_internal(zcs, NULL, 0, ZSTD_dm_auto, zcs->cdict, params, pledgedSrcSize);
|
3678
2491
|
}
|
3679
2492
|
|
3680
2493
|
/*! ZSTD_initCStream_internal() :
|
@@ -3683,9 +2496,9 @@ size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize)
|
|
3683
2496
|
* Assumption 2 : either dict, or cdict, is defined, not both */
|
3684
2497
|
size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
|
3685
2498
|
const void* dict, size_t dictSize, const ZSTD_CDict* cdict,
|
3686
|
-
|
2499
|
+
ZSTD_CCtx_params params, unsigned long long pledgedSrcSize)
|
3687
2500
|
{
|
3688
|
-
DEBUGLOG(
|
2501
|
+
DEBUGLOG(4, "ZSTD_initCStream_internal");
|
3689
2502
|
assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
|
3690
2503
|
assert(!((dict) && (cdict))); /* either dict or cdict, not both */
|
3691
2504
|
|
@@ -3697,23 +2510,23 @@ size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
|
|
3697
2510
|
}
|
3698
2511
|
ZSTD_freeCDict(zcs->cdictLocal);
|
3699
2512
|
zcs->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize,
|
3700
|
-
|
2513
|
+
ZSTD_dlm_byCopy, ZSTD_dm_auto,
|
3701
2514
|
params.cParams, zcs->customMem);
|
3702
2515
|
zcs->cdict = zcs->cdictLocal;
|
3703
2516
|
if (zcs->cdictLocal == NULL) return ERROR(memory_allocation);
|
3704
2517
|
} else {
|
3705
2518
|
if (cdict) {
|
3706
|
-
|
3707
|
-
params.cParams = cdictParams.cParams; /* cParams are enforced from cdict */
|
2519
|
+
params.cParams = ZSTD_getCParamsFromCDict(cdict); /* cParams are enforced from cdict */
|
3708
2520
|
}
|
3709
2521
|
ZSTD_freeCDict(zcs->cdictLocal);
|
3710
2522
|
zcs->cdictLocal = NULL;
|
3711
2523
|
zcs->cdict = cdict;
|
3712
2524
|
}
|
3713
2525
|
|
2526
|
+
params.compressionLevel = ZSTD_CLEVEL_CUSTOM;
|
3714
2527
|
zcs->requestedParams = params;
|
3715
|
-
|
3716
|
-
return ZSTD_resetCStream_internal(zcs, NULL, 0,
|
2528
|
+
|
2529
|
+
return ZSTD_resetCStream_internal(zcs, NULL, 0, ZSTD_dm_auto, zcs->cdict, params, pledgedSrcSize);
|
3717
2530
|
}
|
3718
2531
|
|
3719
2532
|
/* ZSTD_initCStream_usingCDict_advanced() :
|
@@ -3724,7 +2537,8 @@ size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs,
|
|
3724
2537
|
unsigned long long pledgedSrcSize)
|
3725
2538
|
{ /* cannot handle NULL cdict (does not know what to do) */
|
3726
2539
|
if (!cdict) return ERROR(dictionary_wrong);
|
3727
|
-
{
|
2540
|
+
{ ZSTD_CCtx_params params = zcs->requestedParams;
|
2541
|
+
params.cParams = ZSTD_getCParamsFromCDict(cdict);
|
3728
2542
|
params.fParams = fParams;
|
3729
2543
|
return ZSTD_initCStream_internal(zcs,
|
3730
2544
|
NULL, 0, cdict,
|
@@ -3743,30 +2557,32 @@ size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,
|
|
3743
2557
|
const void* dict, size_t dictSize,
|
3744
2558
|
ZSTD_parameters params, unsigned long long pledgedSrcSize)
|
3745
2559
|
{
|
2560
|
+
ZSTD_CCtx_params const cctxParams =
|
2561
|
+
ZSTD_assignParamsToCCtxParams(zcs->requestedParams, params);
|
3746
2562
|
CHECK_F( ZSTD_checkCParams(params.cParams) );
|
3747
|
-
zcs
|
3748
|
-
zcs->compressionLevel = ZSTD_CLEVEL_CUSTOM;
|
3749
|
-
return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL, params, pledgedSrcSize);
|
2563
|
+
return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL, cctxParams, pledgedSrcSize);
|
3750
2564
|
}
|
3751
2565
|
|
3752
2566
|
size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel)
|
3753
2567
|
{
|
3754
2568
|
ZSTD_parameters const params = ZSTD_getParams(compressionLevel, 0, dictSize);
|
3755
|
-
|
3756
|
-
|
2569
|
+
ZSTD_CCtx_params const cctxParams =
|
2570
|
+
ZSTD_assignParamsToCCtxParams(zcs->requestedParams, params);
|
2571
|
+
return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL, cctxParams, 0);
|
3757
2572
|
}
|
3758
2573
|
|
3759
2574
|
size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize)
|
3760
2575
|
{
|
3761
|
-
|
3762
|
-
params
|
3763
|
-
|
2576
|
+
ZSTD_CCtx_params cctxParams;
|
2577
|
+
ZSTD_parameters const params = ZSTD_getParams(compressionLevel, pledgedSrcSize, 0);
|
2578
|
+
cctxParams = ZSTD_assignParamsToCCtxParams(zcs->requestedParams, params);
|
2579
|
+
cctxParams.fParams.contentSizeFlag = (pledgedSrcSize>0);
|
2580
|
+
return ZSTD_initCStream_internal(zcs, NULL, 0, NULL, cctxParams, pledgedSrcSize);
|
3764
2581
|
}
|
3765
2582
|
|
3766
2583
|
size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel)
|
3767
2584
|
{
|
3768
|
-
|
3769
|
-
return ZSTD_initCStream_internal(zcs, NULL, 0, NULL, params, 0);
|
2585
|
+
return ZSTD_initCStream_srcSize(zcs, compressionLevel, 0);
|
3770
2586
|
}
|
3771
2587
|
|
3772
2588
|
/*====== Compression ======*/
|
@@ -3781,6 +2597,7 @@ MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity,
|
|
3781
2597
|
|
3782
2598
|
/** ZSTD_compressStream_generic():
|
3783
2599
|
* internal function for all *compressStream*() variants and *compress_generic()
|
2600
|
+
* non-static, because can be called from zstdmt.c
|
3784
2601
|
* @return : hint size for next input */
|
3785
2602
|
size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
|
3786
2603
|
ZSTD_outBuffer* output,
|
@@ -3934,21 +2751,13 @@ size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuf
|
|
3934
2751
|
return ZSTD_compressStream_generic(zcs, output, input, ZSTD_e_continue);
|
3935
2752
|
}
|
3936
2753
|
|
3937
|
-
/*! ZSTDMT_initCStream_internal() :
|
3938
|
-
* Private use only. Init streaming operation.
|
3939
|
-
* expects params to be valid.
|
3940
|
-
* must receive dict, or cdict, or none, but not both.
|
3941
|
-
* @return : 0, or an error code */
|
3942
|
-
size_t ZSTDMT_initCStream_internal(ZSTDMT_CCtx* zcs,
|
3943
|
-
const void* dict, size_t dictSize, const ZSTD_CDict* cdict,
|
3944
|
-
ZSTD_parameters params, unsigned long long pledgedSrcSize);
|
3945
|
-
|
3946
2754
|
|
3947
2755
|
size_t ZSTD_compress_generic (ZSTD_CCtx* cctx,
|
3948
2756
|
ZSTD_outBuffer* output,
|
3949
2757
|
ZSTD_inBuffer* input,
|
3950
2758
|
ZSTD_EndDirective endOp)
|
3951
2759
|
{
|
2760
|
+
DEBUGLOG(5, "ZSTD_compress_generic");
|
3952
2761
|
/* check conditions */
|
3953
2762
|
if (output->pos > output->size) return ERROR(GENERIC);
|
3954
2763
|
if (input->pos > input->size) return ERROR(GENERIC);
|
@@ -3956,31 +2765,42 @@ size_t ZSTD_compress_generic (ZSTD_CCtx* cctx,
|
|
3956
2765
|
|
3957
2766
|
/* transparent initialization stage */
|
3958
2767
|
if (cctx->streamStage == zcss_init) {
|
3959
|
-
|
3960
|
-
|
3961
|
-
|
3962
|
-
|
3963
|
-
|
3964
|
-
|
3965
|
-
|
3966
|
-
assert(prefix==NULL || cctx->cdict==NULL); /* only one can be set */
|
2768
|
+
ZSTD_prefixDict const prefixDict = cctx->prefixDict;
|
2769
|
+
ZSTD_CCtx_params params = cctx->requestedParams;
|
2770
|
+
params.cParams = ZSTD_getCParamsFromCCtxParams(
|
2771
|
+
cctx->requestedParams, cctx->pledgedSrcSizePlusOne-1, 0 /*dictSize*/);
|
2772
|
+
memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); /* single usage */
|
2773
|
+
assert(prefixDict.dict==NULL || cctx->cdict==NULL); /* only one can be set */
|
2774
|
+
DEBUGLOG(4, "ZSTD_compress_generic : transparent init stage");
|
3967
2775
|
|
3968
2776
|
#ifdef ZSTD_MULTITHREAD
|
3969
|
-
if (
|
3970
|
-
|
3971
|
-
|
2777
|
+
if (params.nbThreads > 1) {
|
2778
|
+
if (cctx->mtctx == NULL || cctx->appliedParams.nbThreads != params.nbThreads) {
|
2779
|
+
ZSTDMT_freeCCtx(cctx->mtctx);
|
2780
|
+
cctx->mtctx = ZSTDMT_createCCtx_advanced(params.nbThreads, cctx->customMem);
|
2781
|
+
if (cctx->mtctx == NULL) return ERROR(memory_allocation);
|
2782
|
+
}
|
2783
|
+
DEBUGLOG(4, "call ZSTDMT_initCStream_internal as nbThreads=%u", params.nbThreads);
|
2784
|
+
CHECK_F( ZSTDMT_initCStream_internal(
|
2785
|
+
cctx->mtctx,
|
2786
|
+
prefixDict.dict, prefixDict.dictSize, ZSTD_dm_rawContent,
|
2787
|
+
cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) );
|
3972
2788
|
cctx->streamStage = zcss_load;
|
2789
|
+
cctx->appliedParams.nbThreads = params.nbThreads;
|
3973
2790
|
} else
|
3974
2791
|
#endif
|
3975
2792
|
{
|
3976
|
-
CHECK_F( ZSTD_resetCStream_internal(
|
2793
|
+
CHECK_F( ZSTD_resetCStream_internal(
|
2794
|
+
cctx, prefixDict.dict, prefixDict.dictSize,
|
2795
|
+
prefixDict.dictMode, cctx->cdict, params,
|
2796
|
+
cctx->pledgedSrcSizePlusOne-1) );
|
3977
2797
|
} }
|
3978
2798
|
|
3979
2799
|
/* compression stage */
|
3980
2800
|
#ifdef ZSTD_MULTITHREAD
|
3981
|
-
if (cctx->nbThreads > 1) {
|
2801
|
+
if (cctx->appliedParams.nbThreads > 1) {
|
3982
2802
|
size_t const flushMin = ZSTDMT_compressStream_generic(cctx->mtctx, output, input, endOp);
|
3983
|
-
DEBUGLOG(5, "ZSTDMT_compressStream_generic : %u", (U32)flushMin);
|
2803
|
+
DEBUGLOG(5, "ZSTDMT_compressStream_generic result : %u", (U32)flushMin);
|
3984
2804
|
if ( ZSTD_isError(flushMin)
|
3985
2805
|
|| (endOp == ZSTD_e_end && flushMin == 0) ) { /* compression completed */
|
3986
2806
|
ZSTD_startNewCompression(cctx);
|
@@ -3988,7 +2808,6 @@ size_t ZSTD_compress_generic (ZSTD_CCtx* cctx,
|
|
3988
2808
|
return flushMin;
|
3989
2809
|
}
|
3990
2810
|
#endif
|
3991
|
-
|
3992
2811
|
CHECK_F( ZSTD_compressStream_generic(cctx, output, input, endOp) );
|
3993
2812
|
DEBUGLOG(5, "completed ZSTD_compress_generic");
|
3994
2813
|
return cctx->outBuffContentSize - cctx->outBuffFlushedSize; /* remaining to flush */
|
@@ -4189,6 +3008,7 @@ ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long l
|
|
4189
3008
|
if (compressionLevel > ZSTD_MAX_CLEVEL) compressionLevel = ZSTD_MAX_CLEVEL;
|
4190
3009
|
{ ZSTD_compressionParameters const cp = ZSTD_defaultCParameters[tableID][compressionLevel];
|
4191
3010
|
return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize); }
|
3011
|
+
|
4192
3012
|
}
|
4193
3013
|
|
4194
3014
|
/*! ZSTD_getParams() :
|