zstd-ruby 1.4.5.0 → 1.4.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +35 -0
- data/README.md +2 -2
- data/ext/zstdruby/libzstd/Makefile +237 -138
- data/ext/zstdruby/libzstd/README.md +28 -0
- data/ext/zstdruby/libzstd/common/bitstream.h +25 -16
- data/ext/zstdruby/libzstd/common/compiler.h +118 -4
- data/ext/zstdruby/libzstd/common/cpu.h +1 -3
- data/ext/zstdruby/libzstd/common/debug.c +1 -1
- data/ext/zstdruby/libzstd/common/debug.h +12 -19
- data/ext/zstdruby/libzstd/common/entropy_common.c +189 -43
- data/ext/zstdruby/libzstd/common/error_private.c +2 -1
- data/ext/zstdruby/libzstd/common/error_private.h +2 -2
- data/ext/zstdruby/libzstd/common/fse.h +40 -12
- data/ext/zstdruby/libzstd/common/fse_decompress.c +124 -17
- data/ext/zstdruby/libzstd/common/huf.h +27 -6
- data/ext/zstdruby/libzstd/common/mem.h +67 -94
- data/ext/zstdruby/libzstd/common/pool.c +23 -17
- data/ext/zstdruby/libzstd/common/pool.h +2 -2
- data/ext/zstdruby/libzstd/common/threading.c +6 -5
- data/ext/zstdruby/libzstd/common/xxhash.c +19 -57
- data/ext/zstdruby/libzstd/common/xxhash.h +2 -2
- data/ext/zstdruby/libzstd/common/zstd_common.c +10 -10
- data/ext/zstdruby/libzstd/common/zstd_deps.h +111 -0
- data/ext/zstdruby/libzstd/common/zstd_errors.h +2 -1
- data/ext/zstdruby/libzstd/common/zstd_internal.h +90 -59
- data/ext/zstdruby/libzstd/common/zstd_trace.c +42 -0
- data/ext/zstdruby/libzstd/common/zstd_trace.h +152 -0
- data/ext/zstdruby/libzstd/compress/fse_compress.c +31 -24
- data/ext/zstdruby/libzstd/compress/hist.c +27 -29
- data/ext/zstdruby/libzstd/compress/hist.h +2 -2
- data/ext/zstdruby/libzstd/compress/huf_compress.c +217 -101
- data/ext/zstdruby/libzstd/compress/zstd_compress.c +1495 -478
- data/ext/zstdruby/libzstd/compress/zstd_compress_internal.h +143 -44
- data/ext/zstdruby/libzstd/compress/zstd_compress_literals.c +7 -7
- data/ext/zstdruby/libzstd/compress/zstd_compress_literals.h +1 -1
- data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.c +18 -4
- data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.h +1 -1
- data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.c +25 -21
- data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.h +1 -1
- data/ext/zstdruby/libzstd/compress/zstd_cwksp.h +62 -26
- data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +23 -23
- data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +1 -1
- data/ext/zstdruby/libzstd/compress/zstd_fast.c +21 -21
- data/ext/zstdruby/libzstd/compress/zstd_fast.h +1 -1
- data/ext/zstdruby/libzstd/compress/zstd_lazy.c +352 -78
- data/ext/zstdruby/libzstd/compress/zstd_lazy.h +21 -1
- data/ext/zstdruby/libzstd/compress/zstd_ldm.c +276 -209
- data/ext/zstdruby/libzstd/compress/zstd_ldm.h +8 -2
- data/ext/zstdruby/libzstd/compress/zstd_ldm_geartab.h +103 -0
- data/ext/zstdruby/libzstd/compress/zstd_opt.c +191 -46
- data/ext/zstdruby/libzstd/compress/zstd_opt.h +1 -1
- data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +79 -410
- data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +27 -109
- data/ext/zstdruby/libzstd/decompress/huf_decompress.c +303 -201
- data/ext/zstdruby/libzstd/decompress/zstd_ddict.c +9 -9
- data/ext/zstdruby/libzstd/decompress/zstd_ddict.h +2 -2
- data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +370 -87
- data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.c +153 -45
- data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.h +6 -3
- data/ext/zstdruby/libzstd/decompress/zstd_decompress_internal.h +28 -11
- data/ext/zstdruby/libzstd/deprecated/zbuff.h +1 -1
- data/ext/zstdruby/libzstd/deprecated/zbuff_common.c +1 -1
- data/ext/zstdruby/libzstd/deprecated/zbuff_compress.c +1 -1
- data/ext/zstdruby/libzstd/deprecated/zbuff_decompress.c +1 -1
- data/ext/zstdruby/libzstd/dictBuilder/cover.c +40 -31
- data/ext/zstdruby/libzstd/dictBuilder/cover.h +2 -2
- data/ext/zstdruby/libzstd/dictBuilder/divsufsort.c +1 -1
- data/ext/zstdruby/libzstd/dictBuilder/fastcover.c +26 -25
- data/ext/zstdruby/libzstd/dictBuilder/zdict.c +22 -24
- data/ext/zstdruby/libzstd/dictBuilder/zdict.h +5 -4
- data/ext/zstdruby/libzstd/dll/example/Makefile +1 -1
- data/ext/zstdruby/libzstd/dll/example/README.md +16 -22
- data/ext/zstdruby/libzstd/legacy/zstd_legacy.h +1 -1
- data/ext/zstdruby/libzstd/legacy/zstd_v01.c +6 -2
- data/ext/zstdruby/libzstd/legacy/zstd_v01.h +1 -1
- data/ext/zstdruby/libzstd/legacy/zstd_v02.c +6 -2
- data/ext/zstdruby/libzstd/legacy/zstd_v02.h +1 -1
- data/ext/zstdruby/libzstd/legacy/zstd_v03.c +6 -2
- data/ext/zstdruby/libzstd/legacy/zstd_v03.h +1 -1
- data/ext/zstdruby/libzstd/legacy/zstd_v04.c +7 -3
- data/ext/zstdruby/libzstd/legacy/zstd_v04.h +1 -1
- data/ext/zstdruby/libzstd/legacy/zstd_v05.c +10 -6
- data/ext/zstdruby/libzstd/legacy/zstd_v05.h +1 -1
- data/ext/zstdruby/libzstd/legacy/zstd_v06.c +10 -6
- data/ext/zstdruby/libzstd/legacy/zstd_v06.h +1 -1
- data/ext/zstdruby/libzstd/legacy/zstd_v07.c +10 -6
- data/ext/zstdruby/libzstd/legacy/zstd_v07.h +1 -1
- data/ext/zstdruby/libzstd/libzstd.pc.in +3 -3
- data/ext/zstdruby/libzstd/zstd.h +414 -54
- data/lib/zstd-ruby/version.rb +1 -1
- metadata +7 -3
- data/.travis.yml +0 -14
@@ -1,5 +1,5 @@
|
|
1
1
|
/*
|
2
|
-
* Copyright (c) 2016-
|
2
|
+
* Copyright (c) 2016-2021, Yann Collet, Facebook, Inc.
|
3
3
|
* All rights reserved.
|
4
4
|
*
|
5
5
|
* This source code is licensed under both the BSD-style license (found in the
|
@@ -11,10 +11,10 @@
|
|
11
11
|
/*-*************************************
|
12
12
|
* Dependencies
|
13
13
|
***************************************/
|
14
|
-
#include
|
15
|
-
#include <string.h> /* memset */
|
14
|
+
#include "../common/zstd_deps.h" /* INT_MAX, ZSTD_memset, ZSTD_memcpy */
|
16
15
|
#include "../common/cpu.h"
|
17
16
|
#include "../common/mem.h"
|
17
|
+
#include "../common/zstd_trace.h"
|
18
18
|
#include "hist.h" /* HIST_countFast_wksp */
|
19
19
|
#define FSE_STATIC_LINKING_ONLY /* FSE_encodeSymbol */
|
20
20
|
#include "../common/fse.h"
|
@@ -30,6 +30,19 @@
|
|
30
30
|
#include "zstd_ldm.h"
|
31
31
|
#include "zstd_compress_superblock.h"
|
32
32
|
|
33
|
+
/* ***************************************************************
|
34
|
+
* Tuning parameters
|
35
|
+
*****************************************************************/
|
36
|
+
/*!
|
37
|
+
* COMPRESS_HEAPMODE :
|
38
|
+
* Select how default decompression function ZSTD_compress() allocates its context,
|
39
|
+
* on stack (0, default), or into heap (1).
|
40
|
+
* Note that functions with explicit context such as ZSTD_compressCCtx() are unaffected.
|
41
|
+
*/
|
42
|
+
#ifndef ZSTD_COMPRESS_HEAPMODE
|
43
|
+
# define ZSTD_COMPRESS_HEAPMODE 0
|
44
|
+
#endif
|
45
|
+
|
33
46
|
|
34
47
|
/*-*************************************
|
35
48
|
* Helper functions
|
@@ -52,6 +65,7 @@ size_t ZSTD_compressBound(size_t srcSize) {
|
|
52
65
|
struct ZSTD_CDict_s {
|
53
66
|
const void* dictContent;
|
54
67
|
size_t dictContentSize;
|
68
|
+
ZSTD_dictContentType_e dictContentType; /* The dictContentType the CDict was created with */
|
55
69
|
U32* entropyWorkspace; /* entropy workspace of HUF_WORKSPACE_SIZE bytes */
|
56
70
|
ZSTD_cwksp workspace;
|
57
71
|
ZSTD_matchState_t matchState;
|
@@ -69,7 +83,7 @@ ZSTD_CCtx* ZSTD_createCCtx(void)
|
|
69
83
|
static void ZSTD_initCCtx(ZSTD_CCtx* cctx, ZSTD_customMem memManager)
|
70
84
|
{
|
71
85
|
assert(cctx != NULL);
|
72
|
-
|
86
|
+
ZSTD_memset(cctx, 0, sizeof(*cctx));
|
73
87
|
cctx->customMem = memManager;
|
74
88
|
cctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
|
75
89
|
{ size_t const err = ZSTD_CCtx_reset(cctx, ZSTD_reset_parameters);
|
@@ -82,8 +96,8 @@ ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem)
|
|
82
96
|
{
|
83
97
|
ZSTD_STATIC_ASSERT(zcss_init==0);
|
84
98
|
ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN==(0ULL - 1));
|
85
|
-
if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
|
86
|
-
{ ZSTD_CCtx* const cctx = (ZSTD_CCtx*)
|
99
|
+
if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;
|
100
|
+
{ ZSTD_CCtx* const cctx = (ZSTD_CCtx*)ZSTD_customMalloc(sizeof(ZSTD_CCtx), customMem);
|
87
101
|
if (!cctx) return NULL;
|
88
102
|
ZSTD_initCCtx(cctx, customMem);
|
89
103
|
return cctx;
|
@@ -96,20 +110,20 @@ ZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize)
|
|
96
110
|
ZSTD_CCtx* cctx;
|
97
111
|
if (workspaceSize <= sizeof(ZSTD_CCtx)) return NULL; /* minimum size */
|
98
112
|
if ((size_t)workspace & 7) return NULL; /* must be 8-aligned */
|
99
|
-
ZSTD_cwksp_init(&ws, workspace, workspaceSize);
|
113
|
+
ZSTD_cwksp_init(&ws, workspace, workspaceSize, ZSTD_cwksp_static_alloc);
|
100
114
|
|
101
115
|
cctx = (ZSTD_CCtx*)ZSTD_cwksp_reserve_object(&ws, sizeof(ZSTD_CCtx));
|
102
116
|
if (cctx == NULL) return NULL;
|
103
117
|
|
104
|
-
|
118
|
+
ZSTD_memset(cctx, 0, sizeof(ZSTD_CCtx));
|
105
119
|
ZSTD_cwksp_move(&cctx->workspace, &ws);
|
106
120
|
cctx->staticSize = workspaceSize;
|
107
121
|
|
108
122
|
/* statically sized space. entropyWorkspace never moves (but prev/next block swap places) */
|
109
|
-
if (!ZSTD_cwksp_check_available(&cctx->workspace,
|
123
|
+
if (!ZSTD_cwksp_check_available(&cctx->workspace, ENTROPY_WORKSPACE_SIZE + 2 * sizeof(ZSTD_compressedBlockState_t))) return NULL;
|
110
124
|
cctx->blockState.prevCBlock = (ZSTD_compressedBlockState_t*)ZSTD_cwksp_reserve_object(&cctx->workspace, sizeof(ZSTD_compressedBlockState_t));
|
111
125
|
cctx->blockState.nextCBlock = (ZSTD_compressedBlockState_t*)ZSTD_cwksp_reserve_object(&cctx->workspace, sizeof(ZSTD_compressedBlockState_t));
|
112
|
-
cctx->entropyWorkspace = (U32*)ZSTD_cwksp_reserve_object(&cctx->workspace,
|
126
|
+
cctx->entropyWorkspace = (U32*)ZSTD_cwksp_reserve_object(&cctx->workspace, ENTROPY_WORKSPACE_SIZE);
|
113
127
|
cctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
|
114
128
|
return cctx;
|
115
129
|
}
|
@@ -119,10 +133,10 @@ ZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize)
|
|
119
133
|
*/
|
120
134
|
static void ZSTD_clearAllDicts(ZSTD_CCtx* cctx)
|
121
135
|
{
|
122
|
-
|
136
|
+
ZSTD_customFree(cctx->localDict.dictBuffer, cctx->customMem);
|
123
137
|
ZSTD_freeCDict(cctx->localDict.cdict);
|
124
|
-
|
125
|
-
|
138
|
+
ZSTD_memset(&cctx->localDict, 0, sizeof(cctx->localDict));
|
139
|
+
ZSTD_memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict));
|
126
140
|
cctx->cdict = NULL;
|
127
141
|
}
|
128
142
|
|
@@ -153,7 +167,7 @@ size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
|
|
153
167
|
int cctxInWorkspace = ZSTD_cwksp_owns_buffer(&cctx->workspace, cctx);
|
154
168
|
ZSTD_freeCCtxContent(cctx);
|
155
169
|
if (!cctxInWorkspace) {
|
156
|
-
|
170
|
+
ZSTD_customFree(cctx, cctx->customMem);
|
157
171
|
}
|
158
172
|
}
|
159
173
|
return 0;
|
@@ -189,15 +203,32 @@ size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs)
|
|
189
203
|
/* private API call, for dictBuilder only */
|
190
204
|
const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx) { return &(ctx->seqStore); }
|
191
205
|
|
206
|
+
/* Returns 1 if compression parameters are such that we should
|
207
|
+
* enable long distance matching (wlog >= 27, strategy >= btopt).
|
208
|
+
* Returns 0 otherwise.
|
209
|
+
*/
|
210
|
+
static U32 ZSTD_CParams_shouldEnableLdm(const ZSTD_compressionParameters* const cParams) {
|
211
|
+
return cParams->strategy >= ZSTD_btopt && cParams->windowLog >= 27;
|
212
|
+
}
|
213
|
+
|
192
214
|
static ZSTD_CCtx_params ZSTD_makeCCtxParamsFromCParams(
|
193
215
|
ZSTD_compressionParameters cParams)
|
194
216
|
{
|
195
217
|
ZSTD_CCtx_params cctxParams;
|
196
|
-
|
218
|
+
/* should not matter, as all cParams are presumed properly defined */
|
219
|
+
ZSTD_CCtxParams_init(&cctxParams, ZSTD_CLEVEL_DEFAULT);
|
197
220
|
cctxParams.cParams = cParams;
|
198
|
-
|
221
|
+
|
222
|
+
if (ZSTD_CParams_shouldEnableLdm(&cParams)) {
|
223
|
+
DEBUGLOG(4, "ZSTD_makeCCtxParamsFromCParams(): Including LDM into cctx params");
|
224
|
+
cctxParams.ldmParams.enableLdm = 1;
|
225
|
+
/* LDM is enabled by default for optimal parser and window size >= 128MB */
|
226
|
+
ZSTD_ldm_adjustParameters(&cctxParams.ldmParams, &cParams);
|
227
|
+
assert(cctxParams.ldmParams.hashLog >= cctxParams.ldmParams.bucketSizeLog);
|
228
|
+
assert(cctxParams.ldmParams.hashRateLog < 32);
|
229
|
+
}
|
230
|
+
|
199
231
|
assert(!ZSTD_checkCParams(cParams));
|
200
|
-
cctxParams.fParams.contentSizeFlag = 1;
|
201
232
|
return cctxParams;
|
202
233
|
}
|
203
234
|
|
@@ -205,13 +236,12 @@ static ZSTD_CCtx_params* ZSTD_createCCtxParams_advanced(
|
|
205
236
|
ZSTD_customMem customMem)
|
206
237
|
{
|
207
238
|
ZSTD_CCtx_params* params;
|
208
|
-
if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
|
209
|
-
params = (ZSTD_CCtx_params*)
|
239
|
+
if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;
|
240
|
+
params = (ZSTD_CCtx_params*)ZSTD_customCalloc(
|
210
241
|
sizeof(ZSTD_CCtx_params), customMem);
|
211
242
|
if (!params) { return NULL; }
|
243
|
+
ZSTD_CCtxParams_init(params, ZSTD_CLEVEL_DEFAULT);
|
212
244
|
params->customMem = customMem;
|
213
|
-
params->compressionLevel = ZSTD_CLEVEL_DEFAULT;
|
214
|
-
params->fParams.contentSizeFlag = 1;
|
215
245
|
return params;
|
216
246
|
}
|
217
247
|
|
@@ -223,7 +253,7 @@ ZSTD_CCtx_params* ZSTD_createCCtxParams(void)
|
|
223
253
|
size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params)
|
224
254
|
{
|
225
255
|
if (params == NULL) { return 0; }
|
226
|
-
|
256
|
+
ZSTD_customFree(params, params->customMem);
|
227
257
|
return 0;
|
228
258
|
}
|
229
259
|
|
@@ -234,35 +264,52 @@ size_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params)
|
|
234
264
|
|
235
265
|
size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel) {
|
236
266
|
RETURN_ERROR_IF(!cctxParams, GENERIC, "NULL pointer!");
|
237
|
-
|
267
|
+
ZSTD_memset(cctxParams, 0, sizeof(*cctxParams));
|
238
268
|
cctxParams->compressionLevel = compressionLevel;
|
239
269
|
cctxParams->fParams.contentSizeFlag = 1;
|
240
270
|
return 0;
|
241
271
|
}
|
242
272
|
|
273
|
+
#define ZSTD_NO_CLEVEL 0
|
274
|
+
|
275
|
+
/**
|
276
|
+
* Initializes the cctxParams from params and compressionLevel.
|
277
|
+
* @param compressionLevel If params are derived from a compression level then that compression level, otherwise ZSTD_NO_CLEVEL.
|
278
|
+
*/
|
279
|
+
static void ZSTD_CCtxParams_init_internal(ZSTD_CCtx_params* cctxParams, ZSTD_parameters const* params, int compressionLevel)
|
280
|
+
{
|
281
|
+
assert(!ZSTD_checkCParams(params->cParams));
|
282
|
+
ZSTD_memset(cctxParams, 0, sizeof(*cctxParams));
|
283
|
+
cctxParams->cParams = params->cParams;
|
284
|
+
cctxParams->fParams = params->fParams;
|
285
|
+
/* Should not matter, as all cParams are presumed properly defined.
|
286
|
+
* But, set it for tracing anyway.
|
287
|
+
*/
|
288
|
+
cctxParams->compressionLevel = compressionLevel;
|
289
|
+
}
|
290
|
+
|
243
291
|
size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params)
|
244
292
|
{
|
245
293
|
RETURN_ERROR_IF(!cctxParams, GENERIC, "NULL pointer!");
|
246
294
|
FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) , "");
|
247
|
-
|
248
|
-
assert(!ZSTD_checkCParams(params.cParams));
|
249
|
-
cctxParams->cParams = params.cParams;
|
250
|
-
cctxParams->fParams = params.fParams;
|
251
|
-
cctxParams->compressionLevel = ZSTD_CLEVEL_DEFAULT; /* should not matter, as all cParams are presumed properly defined */
|
295
|
+
ZSTD_CCtxParams_init_internal(cctxParams, ¶ms, ZSTD_NO_CLEVEL);
|
252
296
|
return 0;
|
253
297
|
}
|
254
298
|
|
255
|
-
|
256
|
-
*
|
257
|
-
|
258
|
-
|
299
|
+
/**
|
300
|
+
* Sets cctxParams' cParams and fParams from params, but otherwise leaves them alone.
|
301
|
+
* @param param Validated zstd parameters.
|
302
|
+
*/
|
303
|
+
static void ZSTD_CCtxParams_setZstdParams(
|
304
|
+
ZSTD_CCtx_params* cctxParams, const ZSTD_parameters* params)
|
259
305
|
{
|
260
|
-
ZSTD_CCtx_params ret = *cctxParams;
|
261
306
|
assert(!ZSTD_checkCParams(params->cParams));
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
307
|
+
cctxParams->cParams = params->cParams;
|
308
|
+
cctxParams->fParams = params->fParams;
|
309
|
+
/* Should not matter, as all cParams are presumed properly defined.
|
310
|
+
* But, set it for tracing anyway.
|
311
|
+
*/
|
312
|
+
cctxParams->compressionLevel = ZSTD_NO_CLEVEL;
|
266
313
|
}
|
267
314
|
|
268
315
|
ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param)
|
@@ -354,6 +401,11 @@ ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param)
|
|
354
401
|
#endif
|
355
402
|
return bounds;
|
356
403
|
|
404
|
+
case ZSTD_c_enableDedicatedDictSearch:
|
405
|
+
bounds.lowerBound = 0;
|
406
|
+
bounds.upperBound = 1;
|
407
|
+
return bounds;
|
408
|
+
|
357
409
|
case ZSTD_c_enableLongDistanceMatching:
|
358
410
|
bounds.lowerBound = 0;
|
359
411
|
bounds.upperBound = 1;
|
@@ -397,7 +449,7 @@ ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param)
|
|
397
449
|
return bounds;
|
398
450
|
|
399
451
|
case ZSTD_c_forceAttachDict:
|
400
|
-
ZSTD_STATIC_ASSERT(ZSTD_dictDefaultAttach <
|
452
|
+
ZSTD_STATIC_ASSERT(ZSTD_dictDefaultAttach < ZSTD_dictForceLoad);
|
401
453
|
bounds.lowerBound = ZSTD_dictDefaultAttach;
|
402
454
|
bounds.upperBound = ZSTD_dictForceLoad; /* note : how to ensure at compile time that this is the highest value enum ? */
|
403
455
|
return bounds;
|
@@ -418,6 +470,22 @@ ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param)
|
|
418
470
|
bounds.upperBound = ZSTD_SRCSIZEHINT_MAX;
|
419
471
|
return bounds;
|
420
472
|
|
473
|
+
case ZSTD_c_stableInBuffer:
|
474
|
+
case ZSTD_c_stableOutBuffer:
|
475
|
+
bounds.lowerBound = (int)ZSTD_bm_buffered;
|
476
|
+
bounds.upperBound = (int)ZSTD_bm_stable;
|
477
|
+
return bounds;
|
478
|
+
|
479
|
+
case ZSTD_c_blockDelimiters:
|
480
|
+
bounds.lowerBound = (int)ZSTD_sf_noBlockDelimiters;
|
481
|
+
bounds.upperBound = (int)ZSTD_sf_explicitBlockDelimiters;
|
482
|
+
return bounds;
|
483
|
+
|
484
|
+
case ZSTD_c_validateSequences:
|
485
|
+
bounds.lowerBound = 0;
|
486
|
+
bounds.upperBound = 1;
|
487
|
+
return bounds;
|
488
|
+
|
421
489
|
default:
|
422
490
|
bounds.error = ERROR(parameter_unsupported);
|
423
491
|
return bounds;
|
@@ -465,6 +533,7 @@ static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param)
|
|
465
533
|
case ZSTD_c_jobSize:
|
466
534
|
case ZSTD_c_overlapLog:
|
467
535
|
case ZSTD_c_rsyncable:
|
536
|
+
case ZSTD_c_enableDedicatedDictSearch:
|
468
537
|
case ZSTD_c_enableLongDistanceMatching:
|
469
538
|
case ZSTD_c_ldmHashLog:
|
470
539
|
case ZSTD_c_ldmMinMatch:
|
@@ -474,6 +543,10 @@ static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param)
|
|
474
543
|
case ZSTD_c_literalCompressionMode:
|
475
544
|
case ZSTD_c_targetCBlockSize:
|
476
545
|
case ZSTD_c_srcSizeHint:
|
546
|
+
case ZSTD_c_stableInBuffer:
|
547
|
+
case ZSTD_c_stableOutBuffer:
|
548
|
+
case ZSTD_c_blockDelimiters:
|
549
|
+
case ZSTD_c_validateSequences:
|
477
550
|
default:
|
478
551
|
return 0;
|
479
552
|
}
|
@@ -515,12 +588,17 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value)
|
|
515
588
|
case ZSTD_c_jobSize:
|
516
589
|
case ZSTD_c_overlapLog:
|
517
590
|
case ZSTD_c_rsyncable:
|
591
|
+
case ZSTD_c_enableDedicatedDictSearch:
|
518
592
|
case ZSTD_c_enableLongDistanceMatching:
|
519
593
|
case ZSTD_c_ldmHashLog:
|
520
594
|
case ZSTD_c_ldmMinMatch:
|
521
595
|
case ZSTD_c_ldmBucketSizeLog:
|
522
596
|
case ZSTD_c_targetCBlockSize:
|
523
597
|
case ZSTD_c_srcSizeHint:
|
598
|
+
case ZSTD_c_stableInBuffer:
|
599
|
+
case ZSTD_c_stableOutBuffer:
|
600
|
+
case ZSTD_c_blockDelimiters:
|
601
|
+
case ZSTD_c_validateSequences:
|
524
602
|
break;
|
525
603
|
|
526
604
|
default: RETURN_ERROR(parameter_unsupported, "unknown parameter");
|
@@ -541,9 +619,10 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
|
|
541
619
|
|
542
620
|
case ZSTD_c_compressionLevel : {
|
543
621
|
FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value), "");
|
544
|
-
if (value
|
622
|
+
if (value == 0)
|
623
|
+
CCtxParams->compressionLevel = ZSTD_CLEVEL_DEFAULT; /* 0 == default */
|
624
|
+
else
|
545
625
|
CCtxParams->compressionLevel = value;
|
546
|
-
}
|
547
626
|
if (CCtxParams->compressionLevel >= 0) return (size_t)CCtxParams->compressionLevel;
|
548
627
|
return 0; /* return type (size_t) cannot represent negative values */
|
549
628
|
}
|
@@ -667,6 +746,10 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
|
|
667
746
|
return CCtxParams->rsyncable;
|
668
747
|
#endif
|
669
748
|
|
749
|
+
case ZSTD_c_enableDedicatedDictSearch :
|
750
|
+
CCtxParams->enableDedicatedDictSearch = (value!=0);
|
751
|
+
return CCtxParams->enableDedicatedDictSearch;
|
752
|
+
|
670
753
|
case ZSTD_c_enableLongDistanceMatching :
|
671
754
|
CCtxParams->ldmParams.enableLdm = (value!=0);
|
672
755
|
return CCtxParams->ldmParams.enableLdm;
|
@@ -707,17 +790,37 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
|
|
707
790
|
CCtxParams->srcSizeHint = value;
|
708
791
|
return CCtxParams->srcSizeHint;
|
709
792
|
|
793
|
+
case ZSTD_c_stableInBuffer:
|
794
|
+
BOUNDCHECK(ZSTD_c_stableInBuffer, value);
|
795
|
+
CCtxParams->inBufferMode = (ZSTD_bufferMode_e)value;
|
796
|
+
return CCtxParams->inBufferMode;
|
797
|
+
|
798
|
+
case ZSTD_c_stableOutBuffer:
|
799
|
+
BOUNDCHECK(ZSTD_c_stableOutBuffer, value);
|
800
|
+
CCtxParams->outBufferMode = (ZSTD_bufferMode_e)value;
|
801
|
+
return CCtxParams->outBufferMode;
|
802
|
+
|
803
|
+
case ZSTD_c_blockDelimiters:
|
804
|
+
BOUNDCHECK(ZSTD_c_blockDelimiters, value);
|
805
|
+
CCtxParams->blockDelimiters = (ZSTD_sequenceFormat_e)value;
|
806
|
+
return CCtxParams->blockDelimiters;
|
807
|
+
|
808
|
+
case ZSTD_c_validateSequences:
|
809
|
+
BOUNDCHECK(ZSTD_c_validateSequences, value);
|
810
|
+
CCtxParams->validateSequences = value;
|
811
|
+
return CCtxParams->validateSequences;
|
812
|
+
|
710
813
|
default: RETURN_ERROR(parameter_unsupported, "unknown parameter");
|
711
814
|
}
|
712
815
|
}
|
713
816
|
|
714
|
-
size_t ZSTD_CCtx_getParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int* value)
|
817
|
+
size_t ZSTD_CCtx_getParameter(ZSTD_CCtx const* cctx, ZSTD_cParameter param, int* value)
|
715
818
|
{
|
716
819
|
return ZSTD_CCtxParams_getParameter(&cctx->requestedParams, param, value);
|
717
820
|
}
|
718
821
|
|
719
822
|
size_t ZSTD_CCtxParams_getParameter(
|
720
|
-
ZSTD_CCtx_params* CCtxParams, ZSTD_cParameter param, int* value)
|
823
|
+
ZSTD_CCtx_params const* CCtxParams, ZSTD_cParameter param, int* value)
|
721
824
|
{
|
722
825
|
switch(param)
|
723
826
|
{
|
@@ -794,6 +897,9 @@ size_t ZSTD_CCtxParams_getParameter(
|
|
794
897
|
*value = CCtxParams->rsyncable;
|
795
898
|
break;
|
796
899
|
#endif
|
900
|
+
case ZSTD_c_enableDedicatedDictSearch :
|
901
|
+
*value = CCtxParams->enableDedicatedDictSearch;
|
902
|
+
break;
|
797
903
|
case ZSTD_c_enableLongDistanceMatching :
|
798
904
|
*value = CCtxParams->ldmParams.enableLdm;
|
799
905
|
break;
|
@@ -815,6 +921,18 @@ size_t ZSTD_CCtxParams_getParameter(
|
|
815
921
|
case ZSTD_c_srcSizeHint :
|
816
922
|
*value = (int)CCtxParams->srcSizeHint;
|
817
923
|
break;
|
924
|
+
case ZSTD_c_stableInBuffer :
|
925
|
+
*value = (int)CCtxParams->inBufferMode;
|
926
|
+
break;
|
927
|
+
case ZSTD_c_stableOutBuffer :
|
928
|
+
*value = (int)CCtxParams->outBufferMode;
|
929
|
+
break;
|
930
|
+
case ZSTD_c_blockDelimiters :
|
931
|
+
*value = (int)CCtxParams->blockDelimiters;
|
932
|
+
break;
|
933
|
+
case ZSTD_c_validateSequences :
|
934
|
+
*value = (int)CCtxParams->validateSequences;
|
935
|
+
break;
|
818
936
|
default: RETURN_ERROR(parameter_unsupported, "unknown parameter");
|
819
937
|
}
|
820
938
|
return 0;
|
@@ -850,6 +968,14 @@ ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long lo
|
|
850
968
|
return 0;
|
851
969
|
}
|
852
970
|
|
971
|
+
static ZSTD_compressionParameters ZSTD_dedicatedDictSearch_getCParams(
|
972
|
+
int const compressionLevel,
|
973
|
+
size_t const dictSize);
|
974
|
+
static int ZSTD_dedicatedDictSearch_isSupported(
|
975
|
+
const ZSTD_compressionParameters* cParams);
|
976
|
+
static void ZSTD_dedicatedDictSearch_revertCParams(
|
977
|
+
ZSTD_compressionParameters* cParams);
|
978
|
+
|
853
979
|
/**
|
854
980
|
* Initializes the local dict using the requested parameters.
|
855
981
|
* NOTE: This does not use the pledged src size, because it may be used for more
|
@@ -858,8 +984,6 @@ ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long lo
|
|
858
984
|
static size_t ZSTD_initLocalDict(ZSTD_CCtx* cctx)
|
859
985
|
{
|
860
986
|
ZSTD_localDict* const dl = &cctx->localDict;
|
861
|
-
ZSTD_compressionParameters const cParams = ZSTD_getCParamsFromCCtxParams(
|
862
|
-
&cctx->requestedParams, ZSTD_CONTENTSIZE_UNKNOWN, dl->dictSize);
|
863
987
|
if (dl->dict == NULL) {
|
864
988
|
/* No local dictionary. */
|
865
989
|
assert(dl->dictBuffer == NULL);
|
@@ -876,12 +1000,12 @@ static size_t ZSTD_initLocalDict(ZSTD_CCtx* cctx)
|
|
876
1000
|
assert(cctx->cdict == NULL);
|
877
1001
|
assert(cctx->prefixDict.dict == NULL);
|
878
1002
|
|
879
|
-
dl->cdict =
|
1003
|
+
dl->cdict = ZSTD_createCDict_advanced2(
|
880
1004
|
dl->dict,
|
881
1005
|
dl->dictSize,
|
882
1006
|
ZSTD_dlm_byRef,
|
883
1007
|
dl->dictContentType,
|
884
|
-
|
1008
|
+
&cctx->requestedParams,
|
885
1009
|
cctx->customMem);
|
886
1010
|
RETURN_ERROR_IF(!dl->cdict, memory_allocation, "ZSTD_createCDict_advanced failed");
|
887
1011
|
cctx->cdict = dl->cdict;
|
@@ -894,8 +1018,6 @@ size_t ZSTD_CCtx_loadDictionary_advanced(
|
|
894
1018
|
{
|
895
1019
|
RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
|
896
1020
|
"Can't load a dictionary when ctx is not in init stage.");
|
897
|
-
RETURN_ERROR_IF(cctx->staticSize, memory_allocation,
|
898
|
-
"no malloc for static CCtx");
|
899
1021
|
DEBUGLOG(4, "ZSTD_CCtx_loadDictionary_advanced (size: %u)", (U32)dictSize);
|
900
1022
|
ZSTD_clearAllDicts(cctx); /* in case one already exists */
|
901
1023
|
if (dict == NULL || dictSize == 0) /* no dictionary mode */
|
@@ -903,9 +1025,12 @@ size_t ZSTD_CCtx_loadDictionary_advanced(
|
|
903
1025
|
if (dictLoadMethod == ZSTD_dlm_byRef) {
|
904
1026
|
cctx->localDict.dict = dict;
|
905
1027
|
} else {
|
906
|
-
void* dictBuffer
|
1028
|
+
void* dictBuffer;
|
1029
|
+
RETURN_ERROR_IF(cctx->staticSize, memory_allocation,
|
1030
|
+
"no malloc for static CCtx");
|
1031
|
+
dictBuffer = ZSTD_customMalloc(dictSize, cctx->customMem);
|
907
1032
|
RETURN_ERROR_IF(!dictBuffer, memory_allocation, "NULL pointer!");
|
908
|
-
|
1033
|
+
ZSTD_memcpy(dictBuffer, dict, dictSize);
|
909
1034
|
cctx->localDict.dictBuffer = dictBuffer;
|
910
1035
|
cctx->localDict.dict = dictBuffer;
|
911
1036
|
}
|
@@ -938,6 +1063,14 @@ size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict)
|
|
938
1063
|
return 0;
|
939
1064
|
}
|
940
1065
|
|
1066
|
+
size_t ZSTD_CCtx_refThreadPool(ZSTD_CCtx* cctx, ZSTD_threadPool* pool)
|
1067
|
+
{
|
1068
|
+
RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
|
1069
|
+
"Can't ref a pool when ctx not in init stage.");
|
1070
|
+
cctx->pool = pool;
|
1071
|
+
return 0;
|
1072
|
+
}
|
1073
|
+
|
941
1074
|
size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize)
|
942
1075
|
{
|
943
1076
|
return ZSTD_CCtx_refPrefix_advanced(cctx, prefix, prefixSize, ZSTD_dct_rawContent);
|
@@ -1022,23 +1155,83 @@ U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat)
|
|
1022
1155
|
return hashLog - btScale;
|
1023
1156
|
}
|
1024
1157
|
|
1158
|
+
/** ZSTD_dictAndWindowLog() :
|
1159
|
+
* Returns an adjusted window log that is large enough to fit the source and the dictionary.
|
1160
|
+
* The zstd format says that the entire dictionary is valid if one byte of the dictionary
|
1161
|
+
* is within the window. So the hashLog and chainLog should be large enough to reference both
|
1162
|
+
* the dictionary and the window. So we must use this adjusted dictAndWindowLog when downsizing
|
1163
|
+
* the hashLog and windowLog.
|
1164
|
+
* NOTE: srcSize must not be ZSTD_CONTENTSIZE_UNKNOWN.
|
1165
|
+
*/
|
1166
|
+
static U32 ZSTD_dictAndWindowLog(U32 windowLog, U64 srcSize, U64 dictSize)
|
1167
|
+
{
|
1168
|
+
const U64 maxWindowSize = 1ULL << ZSTD_WINDOWLOG_MAX;
|
1169
|
+
/* No dictionary ==> No change */
|
1170
|
+
if (dictSize == 0) {
|
1171
|
+
return windowLog;
|
1172
|
+
}
|
1173
|
+
assert(windowLog <= ZSTD_WINDOWLOG_MAX);
|
1174
|
+
assert(srcSize != ZSTD_CONTENTSIZE_UNKNOWN); /* Handled in ZSTD_adjustCParams_internal() */
|
1175
|
+
{
|
1176
|
+
U64 const windowSize = 1ULL << windowLog;
|
1177
|
+
U64 const dictAndWindowSize = dictSize + windowSize;
|
1178
|
+
/* If the window size is already large enough to fit both the source and the dictionary
|
1179
|
+
* then just use the window size. Otherwise adjust so that it fits the dictionary and
|
1180
|
+
* the window.
|
1181
|
+
*/
|
1182
|
+
if (windowSize >= dictSize + srcSize) {
|
1183
|
+
return windowLog; /* Window size large enough already */
|
1184
|
+
} else if (dictAndWindowSize >= maxWindowSize) {
|
1185
|
+
return ZSTD_WINDOWLOG_MAX; /* Larger than max window log */
|
1186
|
+
} else {
|
1187
|
+
return ZSTD_highbit32((U32)dictAndWindowSize - 1) + 1;
|
1188
|
+
}
|
1189
|
+
}
|
1190
|
+
}
|
1191
|
+
|
1025
1192
|
/** ZSTD_adjustCParams_internal() :
|
1026
1193
|
* optimize `cPar` for a specified input (`srcSize` and `dictSize`).
|
1027
1194
|
* mostly downsize to reduce memory consumption and initialization latency.
|
1028
1195
|
* `srcSize` can be ZSTD_CONTENTSIZE_UNKNOWN when not known.
|
1196
|
+
* `mode` is the mode for parameter adjustment. See docs for `ZSTD_cParamMode_e`.
|
1029
1197
|
* note : `srcSize==0` means 0!
|
1030
1198
|
* condition : cPar is presumed validated (can be checked using ZSTD_checkCParams()). */
|
1031
1199
|
static ZSTD_compressionParameters
|
1032
1200
|
ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar,
|
1033
1201
|
unsigned long long srcSize,
|
1034
|
-
size_t dictSize
|
1202
|
+
size_t dictSize,
|
1203
|
+
ZSTD_cParamMode_e mode)
|
1035
1204
|
{
|
1036
|
-
|
1037
|
-
|
1205
|
+
const U64 minSrcSize = 513; /* (1<<9) + 1 */
|
1206
|
+
const U64 maxWindowResize = 1ULL << (ZSTD_WINDOWLOG_MAX-1);
|
1038
1207
|
assert(ZSTD_checkCParams(cPar)==0);
|
1039
1208
|
|
1040
|
-
|
1041
|
-
|
1209
|
+
switch (mode) {
|
1210
|
+
case ZSTD_cpm_unknown:
|
1211
|
+
case ZSTD_cpm_noAttachDict:
|
1212
|
+
/* If we don't know the source size, don't make any
|
1213
|
+
* assumptions about it. We will already have selected
|
1214
|
+
* smaller parameters if a dictionary is in use.
|
1215
|
+
*/
|
1216
|
+
break;
|
1217
|
+
case ZSTD_cpm_createCDict:
|
1218
|
+
/* Assume a small source size when creating a dictionary
|
1219
|
+
* with an unkown source size.
|
1220
|
+
*/
|
1221
|
+
if (dictSize && srcSize == ZSTD_CONTENTSIZE_UNKNOWN)
|
1222
|
+
srcSize = minSrcSize;
|
1223
|
+
break;
|
1224
|
+
case ZSTD_cpm_attachDict:
|
1225
|
+
/* Dictionary has its own dedicated parameters which have
|
1226
|
+
* already been selected. We are selecting parameters
|
1227
|
+
* for only the source.
|
1228
|
+
*/
|
1229
|
+
dictSize = 0;
|
1230
|
+
break;
|
1231
|
+
default:
|
1232
|
+
assert(0);
|
1233
|
+
break;
|
1234
|
+
}
|
1042
1235
|
|
1043
1236
|
/* resize windowLog if input is small enough, to use less memory */
|
1044
1237
|
if ( (srcSize < maxWindowResize)
|
@@ -1049,10 +1242,12 @@ ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar,
|
|
1049
1242
|
ZSTD_highbit32(tSize-1) + 1;
|
1050
1243
|
if (cPar.windowLog > srcLog) cPar.windowLog = srcLog;
|
1051
1244
|
}
|
1052
|
-
if (
|
1053
|
-
|
1054
|
-
|
1055
|
-
|
1245
|
+
if (srcSize != ZSTD_CONTENTSIZE_UNKNOWN) {
|
1246
|
+
U32 const dictAndWindowLog = ZSTD_dictAndWindowLog(cPar.windowLog, (U64)srcSize, (U64)dictSize);
|
1247
|
+
U32 const cycleLog = ZSTD_cycleLog(cPar.chainLog, cPar.strategy);
|
1248
|
+
if (cPar.hashLog > dictAndWindowLog+1) cPar.hashLog = dictAndWindowLog+1;
|
1249
|
+
if (cycleLog > dictAndWindowLog)
|
1250
|
+
cPar.chainLog -= (cycleLog - dictAndWindowLog);
|
1056
1251
|
}
|
1057
1252
|
|
1058
1253
|
if (cPar.windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN)
|
@@ -1068,31 +1263,38 @@ ZSTD_adjustCParams(ZSTD_compressionParameters cPar,
|
|
1068
1263
|
{
|
1069
1264
|
cPar = ZSTD_clampCParams(cPar); /* resulting cPar is necessarily valid (all parameters within range) */
|
1070
1265
|
if (srcSize == 0) srcSize = ZSTD_CONTENTSIZE_UNKNOWN;
|
1071
|
-
return ZSTD_adjustCParams_internal(cPar, srcSize, dictSize);
|
1266
|
+
return ZSTD_adjustCParams_internal(cPar, srcSize, dictSize, ZSTD_cpm_unknown);
|
1072
1267
|
}
|
1073
1268
|
|
1074
|
-
static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize);
|
1075
|
-
static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize);
|
1269
|
+
static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode);
|
1270
|
+
static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode);
|
1271
|
+
|
1272
|
+
static void ZSTD_overrideCParams(
|
1273
|
+
ZSTD_compressionParameters* cParams,
|
1274
|
+
const ZSTD_compressionParameters* overrides)
|
1275
|
+
{
|
1276
|
+
if (overrides->windowLog) cParams->windowLog = overrides->windowLog;
|
1277
|
+
if (overrides->hashLog) cParams->hashLog = overrides->hashLog;
|
1278
|
+
if (overrides->chainLog) cParams->chainLog = overrides->chainLog;
|
1279
|
+
if (overrides->searchLog) cParams->searchLog = overrides->searchLog;
|
1280
|
+
if (overrides->minMatch) cParams->minMatch = overrides->minMatch;
|
1281
|
+
if (overrides->targetLength) cParams->targetLength = overrides->targetLength;
|
1282
|
+
if (overrides->strategy) cParams->strategy = overrides->strategy;
|
1283
|
+
}
|
1076
1284
|
|
1077
1285
|
ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
|
1078
|
-
const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize)
|
1286
|
+
const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode)
|
1079
1287
|
{
|
1080
1288
|
ZSTD_compressionParameters cParams;
|
1081
1289
|
if (srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN && CCtxParams->srcSizeHint > 0) {
|
1082
1290
|
srcSizeHint = CCtxParams->srcSizeHint;
|
1083
1291
|
}
|
1084
|
-
cParams = ZSTD_getCParams_internal(CCtxParams->compressionLevel, srcSizeHint, dictSize);
|
1292
|
+
cParams = ZSTD_getCParams_internal(CCtxParams->compressionLevel, srcSizeHint, dictSize, mode);
|
1085
1293
|
if (CCtxParams->ldmParams.enableLdm) cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG;
|
1086
|
-
|
1087
|
-
if (CCtxParams->cParams.hashLog) cParams.hashLog = CCtxParams->cParams.hashLog;
|
1088
|
-
if (CCtxParams->cParams.chainLog) cParams.chainLog = CCtxParams->cParams.chainLog;
|
1089
|
-
if (CCtxParams->cParams.searchLog) cParams.searchLog = CCtxParams->cParams.searchLog;
|
1090
|
-
if (CCtxParams->cParams.minMatch) cParams.minMatch = CCtxParams->cParams.minMatch;
|
1091
|
-
if (CCtxParams->cParams.targetLength) cParams.targetLength = CCtxParams->cParams.targetLength;
|
1092
|
-
if (CCtxParams->cParams.strategy) cParams.strategy = CCtxParams->cParams.strategy;
|
1294
|
+
ZSTD_overrideCParams(&cParams, &CCtxParams->cParams);
|
1093
1295
|
assert(!ZSTD_checkCParams(cParams));
|
1094
1296
|
/* srcSizeHint == 0 means 0 */
|
1095
|
-
return ZSTD_adjustCParams_internal(cParams, srcSizeHint, dictSize);
|
1297
|
+
return ZSTD_adjustCParams_internal(cParams, srcSizeHint, dictSize, mode);
|
1096
1298
|
}
|
1097
1299
|
|
1098
1300
|
static size_t
|
@@ -1123,45 +1325,61 @@ ZSTD_sizeof_matchState(const ZSTD_compressionParameters* const cParams,
|
|
1123
1325
|
return tableSpace + optSpace;
|
1124
1326
|
}
|
1125
1327
|
|
1126
|
-
size_t
|
1328
|
+
static size_t ZSTD_estimateCCtxSize_usingCCtxParams_internal(
|
1329
|
+
const ZSTD_compressionParameters* cParams,
|
1330
|
+
const ldmParams_t* ldmParams,
|
1331
|
+
const int isStatic,
|
1332
|
+
const size_t buffInSize,
|
1333
|
+
const size_t buffOutSize,
|
1334
|
+
const U64 pledgedSrcSize)
|
1127
1335
|
{
|
1128
|
-
|
1129
|
-
|
1130
|
-
|
1131
|
-
|
1132
|
-
|
1133
|
-
|
1134
|
-
|
1135
|
-
|
1136
|
-
|
1137
|
-
|
1138
|
-
size_t const blockStateSpace = 2 * ZSTD_cwksp_alloc_size(sizeof(ZSTD_compressedBlockState_t));
|
1139
|
-
size_t const matchStateSize = ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 1);
|
1336
|
+
size_t const windowSize = MAX(1, (size_t)MIN(((U64)1 << cParams->windowLog), pledgedSrcSize));
|
1337
|
+
size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, windowSize);
|
1338
|
+
U32 const divider = (cParams->minMatch==3) ? 3 : 4;
|
1339
|
+
size_t const maxNbSeq = blockSize / divider;
|
1340
|
+
size_t const tokenSpace = ZSTD_cwksp_alloc_size(WILDCOPY_OVERLENGTH + blockSize)
|
1341
|
+
+ ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(seqDef))
|
1342
|
+
+ 3 * ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(BYTE));
|
1343
|
+
size_t const entropySpace = ZSTD_cwksp_alloc_size(ENTROPY_WORKSPACE_SIZE);
|
1344
|
+
size_t const blockStateSpace = 2 * ZSTD_cwksp_alloc_size(sizeof(ZSTD_compressedBlockState_t));
|
1345
|
+
size_t const matchStateSize = ZSTD_sizeof_matchState(cParams, /* forCCtx */ 1);
|
1140
1346
|
|
1141
|
-
|
1142
|
-
|
1347
|
+
size_t const ldmSpace = ZSTD_ldm_getTableSize(*ldmParams);
|
1348
|
+
size_t const maxNbLdmSeq = ZSTD_ldm_getMaxNbSeq(*ldmParams, blockSize);
|
1349
|
+
size_t const ldmSeqSpace = ldmParams->enableLdm ?
|
1350
|
+
ZSTD_cwksp_alloc_size(maxNbLdmSeq * sizeof(rawSeq)) : 0;
|
1143
1351
|
|
1144
|
-
/* estimateCCtxSize is for one-shot compression. So no buffers should
|
1145
|
-
* be needed. However, we still allocate two 0-sized buffers, which can
|
1146
|
-
* take space under ASAN. */
|
1147
|
-
size_t const bufferSpace = ZSTD_cwksp_alloc_size(0)
|
1148
|
-
+ ZSTD_cwksp_alloc_size(0);
|
1149
1352
|
|
1150
|
-
|
1353
|
+
size_t const bufferSpace = ZSTD_cwksp_alloc_size(buffInSize)
|
1354
|
+
+ ZSTD_cwksp_alloc_size(buffOutSize);
|
1151
1355
|
|
1152
|
-
|
1153
|
-
cctxSpace +
|
1154
|
-
entropySpace +
|
1155
|
-
blockStateSpace +
|
1156
|
-
ldmSpace +
|
1157
|
-
ldmSeqSpace +
|
1158
|
-
matchStateSize +
|
1159
|
-
tokenSpace +
|
1160
|
-
bufferSpace;
|
1356
|
+
size_t const cctxSpace = isStatic ? ZSTD_cwksp_alloc_size(sizeof(ZSTD_CCtx)) : 0;
|
1161
1357
|
|
1162
|
-
|
1163
|
-
|
1164
|
-
|
1358
|
+
size_t const neededSpace =
|
1359
|
+
cctxSpace +
|
1360
|
+
entropySpace +
|
1361
|
+
blockStateSpace +
|
1362
|
+
ldmSpace +
|
1363
|
+
ldmSeqSpace +
|
1364
|
+
matchStateSize +
|
1365
|
+
tokenSpace +
|
1366
|
+
bufferSpace;
|
1367
|
+
|
1368
|
+
DEBUGLOG(5, "estimate workspace : %u", (U32)neededSpace);
|
1369
|
+
return neededSpace;
|
1370
|
+
}
|
1371
|
+
|
1372
|
+
size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params)
|
1373
|
+
{
|
1374
|
+
ZSTD_compressionParameters const cParams =
|
1375
|
+
ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict);
|
1376
|
+
|
1377
|
+
RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only.");
|
1378
|
+
/* estimateCCtxSize is for one-shot compression. So no buffers should
|
1379
|
+
* be needed. However, we still allocate two 0-sized buffers, which can
|
1380
|
+
* take space under ASAN. */
|
1381
|
+
return ZSTD_estimateCCtxSize_usingCCtxParams_internal(
|
1382
|
+
&cParams, ¶ms->ldmParams, 1, 0, 0, ZSTD_CONTENTSIZE_UNKNOWN);
|
1165
1383
|
}
|
1166
1384
|
|
1167
1385
|
size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams)
|
@@ -1172,7 +1390,7 @@ size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams)
|
|
1172
1390
|
|
1173
1391
|
static size_t ZSTD_estimateCCtxSize_internal(int compressionLevel)
|
1174
1392
|
{
|
1175
|
-
ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0);
|
1393
|
+
ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict);
|
1176
1394
|
return ZSTD_estimateCCtxSize_usingCParams(cParams);
|
1177
1395
|
}
|
1178
1396
|
|
@@ -1191,15 +1409,18 @@ size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params)
|
|
1191
1409
|
{
|
1192
1410
|
RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only.");
|
1193
1411
|
{ ZSTD_compressionParameters const cParams =
|
1194
|
-
ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0);
|
1195
|
-
size_t const CCtxSize = ZSTD_estimateCCtxSize_usingCCtxParams(params);
|
1412
|
+
ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict);
|
1196
1413
|
size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog);
|
1197
|
-
size_t const inBuffSize = (
|
1198
|
-
|
1199
|
-
|
1200
|
-
|
1201
|
-
|
1202
|
-
|
1414
|
+
size_t const inBuffSize = (params->inBufferMode == ZSTD_bm_buffered)
|
1415
|
+
? ((size_t)1 << cParams.windowLog) + blockSize
|
1416
|
+
: 0;
|
1417
|
+
size_t const outBuffSize = (params->outBufferMode == ZSTD_bm_buffered)
|
1418
|
+
? ZSTD_compressBound(blockSize) + 1
|
1419
|
+
: 0;
|
1420
|
+
|
1421
|
+
return ZSTD_estimateCCtxSize_usingCCtxParams_internal(
|
1422
|
+
&cParams, ¶ms->ldmParams, 1, inBuffSize, outBuffSize,
|
1423
|
+
ZSTD_CONTENTSIZE_UNKNOWN);
|
1203
1424
|
}
|
1204
1425
|
}
|
1205
1426
|
|
@@ -1211,7 +1432,7 @@ size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams)
|
|
1211
1432
|
|
1212
1433
|
static size_t ZSTD_estimateCStreamSize_internal(int compressionLevel)
|
1213
1434
|
{
|
1214
|
-
ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0);
|
1435
|
+
ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict);
|
1215
1436
|
return ZSTD_estimateCStreamSize_usingCParams(cParams);
|
1216
1437
|
}
|
1217
1438
|
|
@@ -1304,16 +1525,6 @@ static void ZSTD_invalidateMatchState(ZSTD_matchState_t* ms)
|
|
1304
1525
|
ms->dictMatchState = NULL;
|
1305
1526
|
}
|
1306
1527
|
|
1307
|
-
/**
|
1308
|
-
* Indicates whether this compression proceeds directly from user-provided
|
1309
|
-
* source buffer to user-provided destination buffer (ZSTDb_not_buffered), or
|
1310
|
-
* whether the context needs to buffer the input/output (ZSTDb_buffered).
|
1311
|
-
*/
|
1312
|
-
typedef enum {
|
1313
|
-
ZSTDb_not_buffered,
|
1314
|
-
ZSTDb_buffered
|
1315
|
-
} ZSTD_buffered_policy_e;
|
1316
|
-
|
1317
1528
|
/**
|
1318
1529
|
* Controls, for this matchState reset, whether the tables need to be cleared /
|
1319
1530
|
* prepared for the coming compression (ZSTDcrp_makeClean), or whether the
|
@@ -1434,52 +1645,38 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
|
|
1434
1645
|
ZSTD_ldm_adjustParameters(¶ms.ldmParams, ¶ms.cParams);
|
1435
1646
|
assert(params.ldmParams.hashLog >= params.ldmParams.bucketSizeLog);
|
1436
1647
|
assert(params.ldmParams.hashRateLog < 32);
|
1437
|
-
zc->ldmState.hashPower = ZSTD_rollingHash_primePower(params.ldmParams.minMatchLength);
|
1438
1648
|
}
|
1439
1649
|
|
1440
1650
|
{ size_t const windowSize = MAX(1, (size_t)MIN(((U64)1 << params.cParams.windowLog), pledgedSrcSize));
|
1441
1651
|
size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, windowSize);
|
1442
1652
|
U32 const divider = (params.cParams.minMatch==3) ? 3 : 4;
|
1443
1653
|
size_t const maxNbSeq = blockSize / divider;
|
1444
|
-
size_t const
|
1445
|
-
|
1446
|
-
|
1447
|
-
size_t const
|
1448
|
-
|
1449
|
-
|
1654
|
+
size_t const buffOutSize = (zbuff == ZSTDb_buffered && params.outBufferMode == ZSTD_bm_buffered)
|
1655
|
+
? ZSTD_compressBound(blockSize) + 1
|
1656
|
+
: 0;
|
1657
|
+
size_t const buffInSize = (zbuff == ZSTDb_buffered && params.inBufferMode == ZSTD_bm_buffered)
|
1658
|
+
? windowSize + blockSize
|
1659
|
+
: 0;
|
1450
1660
|
size_t const maxNbLdmSeq = ZSTD_ldm_getMaxNbSeq(params.ldmParams, blockSize);
|
1451
1661
|
|
1452
|
-
|
1662
|
+
int const indexTooClose = ZSTD_indexTooCloseToMax(zc->blockState.matchState.window);
|
1663
|
+
ZSTD_indexResetPolicy_e needsIndexReset =
|
1664
|
+
(!indexTooClose && zc->initialized) ? ZSTDirp_continue : ZSTDirp_reset;
|
1453
1665
|
|
1454
|
-
|
1455
|
-
|
1456
|
-
|
1666
|
+
size_t const neededSpace =
|
1667
|
+
ZSTD_estimateCCtxSize_usingCCtxParams_internal(
|
1668
|
+
¶ms.cParams, ¶ms.ldmParams, zc->staticSize != 0,
|
1669
|
+
buffInSize, buffOutSize, pledgedSrcSize);
|
1670
|
+
FORWARD_IF_ERROR(neededSpace, "cctx size estimate failed!");
|
1457
1671
|
|
1458
1672
|
if (!zc->staticSize) ZSTD_cwksp_bump_oversized_duration(ws, 0);
|
1459
1673
|
|
1460
1674
|
/* Check if workspace is large enough, alloc a new one if needed */
|
1461
|
-
{
|
1462
|
-
size_t const entropySpace = ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE);
|
1463
|
-
size_t const blockStateSpace = 2 * ZSTD_cwksp_alloc_size(sizeof(ZSTD_compressedBlockState_t));
|
1464
|
-
size_t const bufferSpace = ZSTD_cwksp_alloc_size(buffInSize) + ZSTD_cwksp_alloc_size(buffOutSize);
|
1465
|
-
size_t const ldmSpace = ZSTD_ldm_getTableSize(params.ldmParams);
|
1466
|
-
size_t const ldmSeqSpace = ZSTD_cwksp_alloc_size(maxNbLdmSeq * sizeof(rawSeq));
|
1467
|
-
|
1468
|
-
size_t const neededSpace =
|
1469
|
-
cctxSpace +
|
1470
|
-
entropySpace +
|
1471
|
-
blockStateSpace +
|
1472
|
-
ldmSpace +
|
1473
|
-
ldmSeqSpace +
|
1474
|
-
matchStateSize +
|
1475
|
-
tokenSpace +
|
1476
|
-
bufferSpace;
|
1477
|
-
|
1675
|
+
{
|
1478
1676
|
int const workspaceTooSmall = ZSTD_cwksp_sizeof(ws) < neededSpace;
|
1479
1677
|
int const workspaceWasteful = ZSTD_cwksp_check_wasteful(ws, neededSpace);
|
1480
1678
|
|
1481
|
-
DEBUGLOG(4, "Need %
|
1482
|
-
neededSpace>>10, matchStateSize>>10, bufferSpace>>10);
|
1679
|
+
DEBUGLOG(4, "Need %zu B workspace", neededSpace);
|
1483
1680
|
DEBUGLOG(4, "windowSize: %zu - blockSize: %zu", windowSize, blockSize);
|
1484
1681
|
|
1485
1682
|
if (workspaceTooSmall || workspaceWasteful) {
|
@@ -1503,7 +1700,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
|
|
1503
1700
|
RETURN_ERROR_IF(zc->blockState.prevCBlock == NULL, memory_allocation, "couldn't allocate prevCBlock");
|
1504
1701
|
zc->blockState.nextCBlock = (ZSTD_compressedBlockState_t*) ZSTD_cwksp_reserve_object(ws, sizeof(ZSTD_compressedBlockState_t));
|
1505
1702
|
RETURN_ERROR_IF(zc->blockState.nextCBlock == NULL, memory_allocation, "couldn't allocate nextCBlock");
|
1506
|
-
zc->entropyWorkspace = (U32*) ZSTD_cwksp_reserve_object(ws,
|
1703
|
+
zc->entropyWorkspace = (U32*) ZSTD_cwksp_reserve_object(ws, ENTROPY_WORKSPACE_SIZE);
|
1507
1704
|
RETURN_ERROR_IF(zc->blockState.nextCBlock == NULL, memory_allocation, "couldn't allocate entropyWorkspace");
|
1508
1705
|
} }
|
1509
1706
|
|
@@ -1524,6 +1721,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
|
|
1524
1721
|
XXH64_reset(&zc->xxhState, 0);
|
1525
1722
|
zc->stage = ZSTDcs_init;
|
1526
1723
|
zc->dictID = 0;
|
1724
|
+
zc->dictContentSize = 0;
|
1527
1725
|
|
1528
1726
|
ZSTD_reset_compressedBlockState(zc->blockState.prevCBlock);
|
1529
1727
|
|
@@ -1534,6 +1732,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
|
|
1534
1732
|
zc->seqStore.maxNbLit = blockSize;
|
1535
1733
|
|
1536
1734
|
/* buffers */
|
1735
|
+
zc->bufferedPolicy = zbuff;
|
1537
1736
|
zc->inBuffSize = buffInSize;
|
1538
1737
|
zc->inBuff = (char*)ZSTD_cwksp_reserve_buffer(ws, buffInSize);
|
1539
1738
|
zc->outBuffSize = buffOutSize;
|
@@ -1542,11 +1741,11 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
|
|
1542
1741
|
/* ldm bucketOffsets table */
|
1543
1742
|
if (params.ldmParams.enableLdm) {
|
1544
1743
|
/* TODO: avoid memset? */
|
1545
|
-
size_t const
|
1744
|
+
size_t const numBuckets =
|
1546
1745
|
((size_t)1) << (params.ldmParams.hashLog -
|
1547
1746
|
params.ldmParams.bucketSizeLog);
|
1548
|
-
zc->ldmState.bucketOffsets = ZSTD_cwksp_reserve_buffer(ws,
|
1549
|
-
|
1747
|
+
zc->ldmState.bucketOffsets = ZSTD_cwksp_reserve_buffer(ws, numBuckets);
|
1748
|
+
ZSTD_memset(zc->ldmState.bucketOffsets, 0, numBuckets);
|
1550
1749
|
}
|
1551
1750
|
|
1552
1751
|
/* sequences storage */
|
@@ -1570,7 +1769,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
|
|
1570
1769
|
/* TODO: avoid memset? */
|
1571
1770
|
size_t const ldmHSize = ((size_t)1) << params.ldmParams.hashLog;
|
1572
1771
|
zc->ldmState.hashTable = (ldmEntry_t*)ZSTD_cwksp_reserve_aligned(ws, ldmHSize * sizeof(ldmEntry_t));
|
1573
|
-
|
1772
|
+
ZSTD_memset(zc->ldmState.hashTable, 0, ldmHSize * sizeof(ldmEntry_t));
|
1574
1773
|
zc->ldmSequences = (rawSeq*)ZSTD_cwksp_reserve_aligned(ws, maxNbLdmSeq * sizeof(rawSeq));
|
1575
1774
|
zc->maxNbLdmSequences = maxNbLdmSeq;
|
1576
1775
|
|
@@ -1579,6 +1778,12 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
|
|
1579
1778
|
zc->ldmState.loadedDictEnd = 0;
|
1580
1779
|
}
|
1581
1780
|
|
1781
|
+
/* Due to alignment, when reusing a workspace, we can actually consume
|
1782
|
+
* up to 3 extra bytes for alignment. See the comments in zstd_cwksp.h
|
1783
|
+
*/
|
1784
|
+
assert(ZSTD_cwksp_used(ws) >= neededSpace &&
|
1785
|
+
ZSTD_cwksp_used(ws) <= neededSpace + 3);
|
1786
|
+
|
1582
1787
|
DEBUGLOG(3, "wksp: finished allocating, %zd bytes remain available", ZSTD_cwksp_available_space(ws));
|
1583
1788
|
zc->initialized = 1;
|
1584
1789
|
|
@@ -1618,12 +1823,14 @@ static int ZSTD_shouldAttachDict(const ZSTD_CDict* cdict,
|
|
1618
1823
|
U64 pledgedSrcSize)
|
1619
1824
|
{
|
1620
1825
|
size_t cutoff = attachDictSizeCutoffs[cdict->matchState.cParams.strategy];
|
1621
|
-
|
1622
|
-
|
1623
|
-
|
1624
|
-
|
1625
|
-
|
1626
|
-
|
1826
|
+
int const dedicatedDictSearch = cdict->matchState.dedicatedDictSearch;
|
1827
|
+
return dedicatedDictSearch
|
1828
|
+
|| ( ( pledgedSrcSize <= cutoff
|
1829
|
+
|| pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN
|
1830
|
+
|| params->attachDictPref == ZSTD_dictForceAttach )
|
1831
|
+
&& params->attachDictPref != ZSTD_dictForceCopy
|
1832
|
+
&& !params->forceWindow ); /* dictMatchState isn't correctly
|
1833
|
+
* handled in _enforceMaxDist */
|
1627
1834
|
}
|
1628
1835
|
|
1629
1836
|
static size_t
|
@@ -1633,17 +1840,24 @@ ZSTD_resetCCtx_byAttachingCDict(ZSTD_CCtx* cctx,
|
|
1633
1840
|
U64 pledgedSrcSize,
|
1634
1841
|
ZSTD_buffered_policy_e zbuff)
|
1635
1842
|
{
|
1636
|
-
{
|
1843
|
+
{
|
1844
|
+
ZSTD_compressionParameters adjusted_cdict_cParams = cdict->matchState.cParams;
|
1637
1845
|
unsigned const windowLog = params.cParams.windowLog;
|
1638
1846
|
assert(windowLog != 0);
|
1639
1847
|
/* Resize working context table params for input only, since the dict
|
1640
1848
|
* has its own tables. */
|
1641
|
-
/*
|
1642
|
-
|
1849
|
+
/* pledgedSrcSize == 0 means 0! */
|
1850
|
+
|
1851
|
+
if (cdict->matchState.dedicatedDictSearch) {
|
1852
|
+
ZSTD_dedicatedDictSearch_revertCParams(&adjusted_cdict_cParams);
|
1853
|
+
}
|
1854
|
+
|
1855
|
+
params.cParams = ZSTD_adjustCParams_internal(adjusted_cdict_cParams, pledgedSrcSize,
|
1856
|
+
cdict->dictContentSize, ZSTD_cpm_attachDict);
|
1643
1857
|
params.cParams.windowLog = windowLog;
|
1644
1858
|
FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
|
1645
1859
|
ZSTDcrp_makeClean, zbuff), "");
|
1646
|
-
assert(cctx->appliedParams.cParams.strategy ==
|
1860
|
+
assert(cctx->appliedParams.cParams.strategy == adjusted_cdict_cParams.strategy);
|
1647
1861
|
}
|
1648
1862
|
|
1649
1863
|
{ const U32 cdictEnd = (U32)( cdict->matchState.window.nextSrc
|
@@ -1668,9 +1882,10 @@ ZSTD_resetCCtx_byAttachingCDict(ZSTD_CCtx* cctx,
|
|
1668
1882
|
} }
|
1669
1883
|
|
1670
1884
|
cctx->dictID = cdict->dictID;
|
1885
|
+
cctx->dictContentSize = cdict->dictContentSize;
|
1671
1886
|
|
1672
1887
|
/* copy block state */
|
1673
|
-
|
1888
|
+
ZSTD_memcpy(cctx->blockState.prevCBlock, &cdict->cBlockState, sizeof(cdict->cBlockState));
|
1674
1889
|
|
1675
1890
|
return 0;
|
1676
1891
|
}
|
@@ -1683,6 +1898,8 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx,
|
|
1683
1898
|
{
|
1684
1899
|
const ZSTD_compressionParameters *cdict_cParams = &cdict->matchState.cParams;
|
1685
1900
|
|
1901
|
+
assert(!cdict->matchState.dedicatedDictSearch);
|
1902
|
+
|
1686
1903
|
DEBUGLOG(4, "copying dictionary into context");
|
1687
1904
|
|
1688
1905
|
{ unsigned const windowLog = params.cParams.windowLog;
|
@@ -1703,10 +1920,10 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx,
|
|
1703
1920
|
{ size_t const chainSize = (cdict_cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cdict_cParams->chainLog);
|
1704
1921
|
size_t const hSize = (size_t)1 << cdict_cParams->hashLog;
|
1705
1922
|
|
1706
|
-
|
1923
|
+
ZSTD_memcpy(cctx->blockState.matchState.hashTable,
|
1707
1924
|
cdict->matchState.hashTable,
|
1708
1925
|
hSize * sizeof(U32));
|
1709
|
-
|
1926
|
+
ZSTD_memcpy(cctx->blockState.matchState.chainTable,
|
1710
1927
|
cdict->matchState.chainTable,
|
1711
1928
|
chainSize * sizeof(U32));
|
1712
1929
|
}
|
@@ -1715,7 +1932,7 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx,
|
|
1715
1932
|
{ int const h3log = cctx->blockState.matchState.hashLog3;
|
1716
1933
|
size_t const h3Size = h3log ? ((size_t)1 << h3log) : 0;
|
1717
1934
|
assert(cdict->matchState.hashLog3 == 0);
|
1718
|
-
|
1935
|
+
ZSTD_memset(cctx->blockState.matchState.hashTable3, 0, h3Size * sizeof(U32));
|
1719
1936
|
}
|
1720
1937
|
|
1721
1938
|
ZSTD_cwksp_mark_tables_clean(&cctx->workspace);
|
@@ -1729,9 +1946,10 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx,
|
|
1729
1946
|
}
|
1730
1947
|
|
1731
1948
|
cctx->dictID = cdict->dictID;
|
1949
|
+
cctx->dictContentSize = cdict->dictContentSize;
|
1732
1950
|
|
1733
1951
|
/* copy block state */
|
1734
|
-
|
1952
|
+
ZSTD_memcpy(cctx->blockState.prevCBlock, &cdict->cBlockState, sizeof(cdict->cBlockState));
|
1735
1953
|
|
1736
1954
|
return 0;
|
1737
1955
|
}
|
@@ -1775,7 +1993,7 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
|
|
1775
1993
|
RETURN_ERROR_IF(srcCCtx->stage!=ZSTDcs_init, stage_wrong,
|
1776
1994
|
"Can't copy a ctx that's not in init stage.");
|
1777
1995
|
|
1778
|
-
|
1996
|
+
ZSTD_memcpy(&dstCCtx->customMem, &srcCCtx->customMem, sizeof(ZSTD_customMem));
|
1779
1997
|
{ ZSTD_CCtx_params params = dstCCtx->requestedParams;
|
1780
1998
|
/* Copy only compression parameters related to tables. */
|
1781
1999
|
params.cParams = srcCCtx->appliedParams.cParams;
|
@@ -1797,13 +2015,13 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
|
|
1797
2015
|
int const h3log = srcCCtx->blockState.matchState.hashLog3;
|
1798
2016
|
size_t const h3Size = h3log ? ((size_t)1 << h3log) : 0;
|
1799
2017
|
|
1800
|
-
|
2018
|
+
ZSTD_memcpy(dstCCtx->blockState.matchState.hashTable,
|
1801
2019
|
srcCCtx->blockState.matchState.hashTable,
|
1802
2020
|
hSize * sizeof(U32));
|
1803
|
-
|
2021
|
+
ZSTD_memcpy(dstCCtx->blockState.matchState.chainTable,
|
1804
2022
|
srcCCtx->blockState.matchState.chainTable,
|
1805
2023
|
chainSize * sizeof(U32));
|
1806
|
-
|
2024
|
+
ZSTD_memcpy(dstCCtx->blockState.matchState.hashTable3,
|
1807
2025
|
srcCCtx->blockState.matchState.hashTable3,
|
1808
2026
|
h3Size * sizeof(U32));
|
1809
2027
|
}
|
@@ -1819,9 +2037,10 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
|
|
1819
2037
|
dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd;
|
1820
2038
|
}
|
1821
2039
|
dstCCtx->dictID = srcCCtx->dictID;
|
2040
|
+
dstCCtx->dictContentSize = srcCCtx->dictContentSize;
|
1822
2041
|
|
1823
2042
|
/* copy block state */
|
1824
|
-
|
2043
|
+
ZSTD_memcpy(dstCCtx->blockState.prevCBlock, srcCCtx->blockState.prevCBlock, sizeof(*srcCCtx->blockState.prevCBlock));
|
1825
2044
|
|
1826
2045
|
return 0;
|
1827
2046
|
}
|
@@ -1834,7 +2053,7 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
|
|
1834
2053
|
size_t ZSTD_copyCCtx(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx, unsigned long long pledgedSrcSize)
|
1835
2054
|
{
|
1836
2055
|
ZSTD_frameParameters fParams = { 1 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ };
|
1837
|
-
ZSTD_buffered_policy_e const zbuff =
|
2056
|
+
ZSTD_buffered_policy_e const zbuff = srcCCtx->bufferedPolicy;
|
1838
2057
|
ZSTD_STATIC_ASSERT((U32)ZSTDb_buffered==1);
|
1839
2058
|
if (pledgedSrcSize==0) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN;
|
1840
2059
|
fParams.contentSizeFlag = (pledgedSrcSize != ZSTD_CONTENTSIZE_UNKNOWN);
|
@@ -1861,7 +2080,7 @@ ZSTD_reduceTable_internal (U32* const table, U32 const size, U32 const reducerVa
|
|
1861
2080
|
assert((size & (ZSTD_ROWSIZE-1)) == 0); /* multiple of ZSTD_ROWSIZE */
|
1862
2081
|
assert(size < (1U<<31)); /* can be casted to int */
|
1863
2082
|
|
1864
|
-
#if
|
2083
|
+
#if ZSTD_MEMORY_SANITIZER && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE)
|
1865
2084
|
/* To validate that the table re-use logic is sound, and that we don't
|
1866
2085
|
* access table space that we haven't cleaned, we re-"poison" the table
|
1867
2086
|
* space every time we mark it dirty.
|
@@ -1958,10 +2177,10 @@ static int ZSTD_useTargetCBlockSize(const ZSTD_CCtx_params* cctxParams)
|
|
1958
2177
|
return (cctxParams->targetCBlockSize != 0);
|
1959
2178
|
}
|
1960
2179
|
|
1961
|
-
/*
|
2180
|
+
/* ZSTD_entropyCompressSequences_internal():
|
1962
2181
|
* actually compresses both literals and sequences */
|
1963
2182
|
MEM_STATIC size_t
|
1964
|
-
|
2183
|
+
ZSTD_entropyCompressSequences_internal(seqStore_t* seqStorePtr,
|
1965
2184
|
const ZSTD_entropyCTables_t* prevEntropy,
|
1966
2185
|
ZSTD_entropyCTables_t* nextEntropy,
|
1967
2186
|
const ZSTD_CCtx_params* cctxParams,
|
@@ -1971,7 +2190,7 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
|
|
1971
2190
|
{
|
1972
2191
|
const int longOffsets = cctxParams->cParams.windowLog > STREAM_ACCUMULATOR_MIN;
|
1973
2192
|
ZSTD_strategy const strategy = cctxParams->cParams.strategy;
|
1974
|
-
unsigned count
|
2193
|
+
unsigned* count = (unsigned*)entropyWorkspace;
|
1975
2194
|
FSE_CTable* CTable_LitLength = nextEntropy->fse.litlengthCTable;
|
1976
2195
|
FSE_CTable* CTable_OffsetBits = nextEntropy->fse.offcodeCTable;
|
1977
2196
|
FSE_CTable* CTable_MatchLength = nextEntropy->fse.matchlengthCTable;
|
@@ -1987,8 +2206,12 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
|
|
1987
2206
|
BYTE* seqHead;
|
1988
2207
|
BYTE* lastNCount = NULL;
|
1989
2208
|
|
1990
|
-
|
2209
|
+
entropyWorkspace = count + (MaxSeq + 1);
|
2210
|
+
entropyWkspSize -= (MaxSeq + 1) * sizeof(*count);
|
2211
|
+
|
2212
|
+
DEBUGLOG(4, "ZSTD_entropyCompressSequences_internal (nbSeq=%zu)", nbSeq);
|
1991
2213
|
ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<<MAX(MLFSELog,LLFSELog)));
|
2214
|
+
assert(entropyWkspSize >= HUF_WORKSPACE_SIZE);
|
1992
2215
|
|
1993
2216
|
/* Compress literals */
|
1994
2217
|
{ const BYTE* const literals = seqStorePtr->litStart;
|
@@ -2023,7 +2246,7 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
|
|
2023
2246
|
assert(op <= oend);
|
2024
2247
|
if (nbSeq==0) {
|
2025
2248
|
/* Copy the old tables over as if we repeated them */
|
2026
|
-
|
2249
|
+
ZSTD_memcpy(&nextEntropy->fse, &prevEntropy->fse, sizeof(prevEntropy->fse));
|
2027
2250
|
return (size_t)(op - ostart);
|
2028
2251
|
}
|
2029
2252
|
|
@@ -2148,7 +2371,7 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
|
|
2148
2371
|
}
|
2149
2372
|
|
2150
2373
|
MEM_STATIC size_t
|
2151
|
-
|
2374
|
+
ZSTD_entropyCompressSequences(seqStore_t* seqStorePtr,
|
2152
2375
|
const ZSTD_entropyCTables_t* prevEntropy,
|
2153
2376
|
ZSTD_entropyCTables_t* nextEntropy,
|
2154
2377
|
const ZSTD_CCtx_params* cctxParams,
|
@@ -2157,7 +2380,7 @@ ZSTD_compressSequences(seqStore_t* seqStorePtr,
|
|
2157
2380
|
void* entropyWorkspace, size_t entropyWkspSize,
|
2158
2381
|
int bmi2)
|
2159
2382
|
{
|
2160
|
-
size_t const cSize =
|
2383
|
+
size_t const cSize = ZSTD_entropyCompressSequences_internal(
|
2161
2384
|
seqStorePtr, prevEntropy, nextEntropy, cctxParams,
|
2162
2385
|
dst, dstCapacity,
|
2163
2386
|
entropyWorkspace, entropyWkspSize, bmi2);
|
@@ -2167,13 +2390,13 @@ ZSTD_compressSequences(seqStore_t* seqStorePtr,
|
|
2167
2390
|
*/
|
2168
2391
|
if ((cSize == ERROR(dstSize_tooSmall)) & (srcSize <= dstCapacity))
|
2169
2392
|
return 0; /* block not compressed */
|
2170
|
-
FORWARD_IF_ERROR(cSize, "
|
2393
|
+
FORWARD_IF_ERROR(cSize, "ZSTD_entropyCompressSequences_internal failed");
|
2171
2394
|
|
2172
2395
|
/* Check compressibility */
|
2173
2396
|
{ size_t const maxCSize = srcSize - ZSTD_minGain(srcSize, cctxParams->cParams.strategy);
|
2174
2397
|
if (cSize >= maxCSize) return 0; /* block not compressed */
|
2175
2398
|
}
|
2176
|
-
|
2399
|
+
DEBUGLOG(4, "ZSTD_entropyCompressSequences() cSize: %zu\n", cSize);
|
2177
2400
|
return cSize;
|
2178
2401
|
}
|
2179
2402
|
|
@@ -2182,7 +2405,7 @@ ZSTD_compressSequences(seqStore_t* seqStorePtr,
|
|
2182
2405
|
* assumption : strat is a valid strategy */
|
2183
2406
|
ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_dictMode_e dictMode)
|
2184
2407
|
{
|
2185
|
-
static const ZSTD_blockCompressor blockCompressor[
|
2408
|
+
static const ZSTD_blockCompressor blockCompressor[4][ZSTD_STRATEGY_MAX+1] = {
|
2186
2409
|
{ ZSTD_compressBlock_fast /* default for 0 */,
|
2187
2410
|
ZSTD_compressBlock_fast,
|
2188
2411
|
ZSTD_compressBlock_doubleFast,
|
@@ -2212,7 +2435,17 @@ ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_dictMo
|
|
2212
2435
|
ZSTD_compressBlock_btlazy2_dictMatchState,
|
2213
2436
|
ZSTD_compressBlock_btopt_dictMatchState,
|
2214
2437
|
ZSTD_compressBlock_btultra_dictMatchState,
|
2215
|
-
ZSTD_compressBlock_btultra_dictMatchState }
|
2438
|
+
ZSTD_compressBlock_btultra_dictMatchState },
|
2439
|
+
{ NULL /* default for 0 */,
|
2440
|
+
NULL,
|
2441
|
+
NULL,
|
2442
|
+
ZSTD_compressBlock_greedy_dedicatedDictSearch,
|
2443
|
+
ZSTD_compressBlock_lazy_dedicatedDictSearch,
|
2444
|
+
ZSTD_compressBlock_lazy2_dedicatedDictSearch,
|
2445
|
+
NULL,
|
2446
|
+
NULL,
|
2447
|
+
NULL,
|
2448
|
+
NULL }
|
2216
2449
|
};
|
2217
2450
|
ZSTD_blockCompressor selectedCompressor;
|
2218
2451
|
ZSTD_STATIC_ASSERT((unsigned)ZSTD_fast == 1);
|
@@ -2226,7 +2459,7 @@ ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_dictMo
|
|
2226
2459
|
static void ZSTD_storeLastLiterals(seqStore_t* seqStorePtr,
|
2227
2460
|
const BYTE* anchor, size_t lastLLSize)
|
2228
2461
|
{
|
2229
|
-
|
2462
|
+
ZSTD_memcpy(seqStorePtr->lit, anchor, lastLLSize);
|
2230
2463
|
seqStorePtr->lit += lastLLSize;
|
2231
2464
|
}
|
2232
2465
|
|
@@ -2247,7 +2480,11 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
|
|
2247
2480
|
/* Assert that we have correctly flushed the ctx params into the ms's copy */
|
2248
2481
|
ZSTD_assertEqualCParams(zc->appliedParams.cParams, ms->cParams);
|
2249
2482
|
if (srcSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1) {
|
2250
|
-
|
2483
|
+
if (zc->appliedParams.cParams.strategy >= ZSTD_btopt) {
|
2484
|
+
ZSTD_ldm_skipRawSeqStoreBytes(&zc->externSeqStore, srcSize);
|
2485
|
+
} else {
|
2486
|
+
ZSTD_ldm_skipSequences(&zc->externSeqStore, srcSize, zc->appliedParams.cParams.minMatch);
|
2487
|
+
}
|
2251
2488
|
return ZSTDbss_noCompress; /* don't even attempt compression below a certain srcSize */
|
2252
2489
|
}
|
2253
2490
|
ZSTD_resetSeqStore(&(zc->seqStore));
|
@@ -2263,10 +2500,10 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
|
|
2263
2500
|
/* limited update after a very long match */
|
2264
2501
|
{ const BYTE* const base = ms->window.base;
|
2265
2502
|
const BYTE* const istart = (const BYTE*)src;
|
2266
|
-
const U32
|
2503
|
+
const U32 curr = (U32)(istart-base);
|
2267
2504
|
if (sizeof(ptrdiff_t)==8) assert(istart - base < (ptrdiff_t)(U32)(-1)); /* ensure no overflow */
|
2268
|
-
if (
|
2269
|
-
ms->nextToUpdate =
|
2505
|
+
if (curr > ms->nextToUpdate + 384)
|
2506
|
+
ms->nextToUpdate = curr - MIN(192, (U32)(curr - ms->nextToUpdate - 384));
|
2270
2507
|
}
|
2271
2508
|
|
2272
2509
|
/* select and store sequences */
|
@@ -2286,7 +2523,7 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
|
|
2286
2523
|
src, srcSize);
|
2287
2524
|
assert(zc->externSeqStore.pos <= zc->externSeqStore.size);
|
2288
2525
|
} else if (zc->appliedParams.ldmParams.enableLdm) {
|
2289
|
-
rawSeqStore_t ldmSeqStore =
|
2526
|
+
rawSeqStore_t ldmSeqStore = kNullRawSeqStore;
|
2290
2527
|
|
2291
2528
|
ldmSeqStore.seq = zc->ldmSequences;
|
2292
2529
|
ldmSeqStore.capacity = zc->maxNbLdmSequences;
|
@@ -2303,6 +2540,7 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
|
|
2303
2540
|
assert(ldmSeqStore.pos == ldmSeqStore.size);
|
2304
2541
|
} else { /* not long range mode */
|
2305
2542
|
ZSTD_blockCompressor const blockCompressor = ZSTD_selectBlockCompressor(zc->appliedParams.cParams.strategy, dictMode);
|
2543
|
+
ms->ldmSeqStore = NULL;
|
2306
2544
|
lastLLSize = blockCompressor(ms, &zc->seqStore, zc->blockState.nextCBlock->rep, src, srcSize);
|
2307
2545
|
}
|
2308
2546
|
{ const BYTE* const lastLiterals = (const BYTE*)src + srcSize - lastLLSize;
|
@@ -2314,17 +2552,25 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
|
|
2314
2552
|
static void ZSTD_copyBlockSequences(ZSTD_CCtx* zc)
|
2315
2553
|
{
|
2316
2554
|
const seqStore_t* seqStore = ZSTD_getSeqStore(zc);
|
2317
|
-
const seqDef*
|
2318
|
-
size_t
|
2555
|
+
const seqDef* seqStoreSeqs = seqStore->sequencesStart;
|
2556
|
+
size_t seqStoreSeqSize = seqStore->sequences - seqStoreSeqs;
|
2557
|
+
size_t seqStoreLiteralsSize = (size_t)(seqStore->lit - seqStore->litStart);
|
2558
|
+
size_t literalsRead = 0;
|
2559
|
+
size_t lastLLSize;
|
2319
2560
|
|
2320
2561
|
ZSTD_Sequence* outSeqs = &zc->seqCollector.seqStart[zc->seqCollector.seqIndex];
|
2321
|
-
size_t i;
|
2562
|
+
size_t i;
|
2563
|
+
repcodes_t updatedRepcodes;
|
2322
2564
|
|
2323
2565
|
assert(zc->seqCollector.seqIndex + 1 < zc->seqCollector.maxSequences);
|
2324
|
-
|
2325
|
-
|
2326
|
-
|
2327
|
-
|
2566
|
+
/* Ensure we have enough space for last literals "sequence" */
|
2567
|
+
assert(zc->seqCollector.maxSequences >= seqStoreSeqSize + 1);
|
2568
|
+
ZSTD_memcpy(updatedRepcodes.rep, zc->blockState.prevCBlock->rep, sizeof(repcodes_t));
|
2569
|
+
for (i = 0; i < seqStoreSeqSize; ++i) {
|
2570
|
+
U32 rawOffset = seqStoreSeqs[i].offset - ZSTD_REP_NUM;
|
2571
|
+
outSeqs[i].litLength = seqStoreSeqs[i].litLength;
|
2572
|
+
outSeqs[i].matchLength = seqStoreSeqs[i].matchLength + MINMATCH;
|
2573
|
+
outSeqs[i].rep = 0;
|
2328
2574
|
|
2329
2575
|
if (i == seqStore->longLengthPos) {
|
2330
2576
|
if (seqStore->longLengthID == 1) {
|
@@ -2334,39 +2580,44 @@ static void ZSTD_copyBlockSequences(ZSTD_CCtx* zc)
|
|
2334
2580
|
}
|
2335
2581
|
}
|
2336
2582
|
|
2337
|
-
if (
|
2338
|
-
|
2339
|
-
|
2340
|
-
|
2341
|
-
|
2342
|
-
|
2343
|
-
|
2583
|
+
if (seqStoreSeqs[i].offset <= ZSTD_REP_NUM) {
|
2584
|
+
/* Derive the correct offset corresponding to a repcode */
|
2585
|
+
outSeqs[i].rep = seqStoreSeqs[i].offset;
|
2586
|
+
if (outSeqs[i].litLength != 0) {
|
2587
|
+
rawOffset = updatedRepcodes.rep[outSeqs[i].rep - 1];
|
2588
|
+
} else {
|
2589
|
+
if (outSeqs[i].rep == 3) {
|
2590
|
+
rawOffset = updatedRepcodes.rep[0] - 1;
|
2344
2591
|
} else {
|
2345
|
-
|
2592
|
+
rawOffset = updatedRepcodes.rep[outSeqs[i].rep];
|
2346
2593
|
}
|
2347
|
-
++outSeqs[i].rep;
|
2348
2594
|
}
|
2349
|
-
assert(repIdx >= -3);
|
2350
|
-
outSeqs[i].offset = repIdx >= 0 ? outSeqs[repIdx].offset : repStartValue[-repIdx - 1];
|
2351
|
-
if (outSeqs[i].rep == 4) {
|
2352
|
-
--outSeqs[i].offset;
|
2353
|
-
}
|
2354
|
-
} else {
|
2355
|
-
outSeqs[i].offset -= ZSTD_REP_NUM;
|
2356
2595
|
}
|
2357
|
-
|
2358
|
-
|
2359
|
-
|
2360
|
-
|
2596
|
+
outSeqs[i].offset = rawOffset;
|
2597
|
+
/* seqStoreSeqs[i].offset == offCode+1, and ZSTD_updateRep() expects offCode
|
2598
|
+
so we provide seqStoreSeqs[i].offset - 1 */
|
2599
|
+
updatedRepcodes = ZSTD_updateRep(updatedRepcodes.rep,
|
2600
|
+
seqStoreSeqs[i].offset - 1,
|
2601
|
+
seqStoreSeqs[i].litLength == 0);
|
2602
|
+
literalsRead += outSeqs[i].litLength;
|
2361
2603
|
}
|
2362
|
-
|
2604
|
+
/* Insert last literals (if any exist) in the block as a sequence with ml == off == 0.
|
2605
|
+
* If there are no last literals, then we'll emit (of: 0, ml: 0, ll: 0), which is a marker
|
2606
|
+
* for the block boundary, according to the API.
|
2607
|
+
*/
|
2608
|
+
assert(seqStoreLiteralsSize >= literalsRead);
|
2609
|
+
lastLLSize = seqStoreLiteralsSize - literalsRead;
|
2610
|
+
outSeqs[i].litLength = (U32)lastLLSize;
|
2611
|
+
outSeqs[i].matchLength = outSeqs[i].offset = outSeqs[i].rep = 0;
|
2612
|
+
seqStoreSeqSize++;
|
2613
|
+
zc->seqCollector.seqIndex += seqStoreSeqSize;
|
2363
2614
|
}
|
2364
2615
|
|
2365
|
-
size_t
|
2366
|
-
|
2616
|
+
size_t ZSTD_generateSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs,
|
2617
|
+
size_t outSeqsSize, const void* src, size_t srcSize)
|
2367
2618
|
{
|
2368
2619
|
const size_t dstCapacity = ZSTD_compressBound(srcSize);
|
2369
|
-
void* dst =
|
2620
|
+
void* dst = ZSTD_customMalloc(dstCapacity, ZSTD_defaultCMem);
|
2370
2621
|
SeqCollector seqCollector;
|
2371
2622
|
|
2372
2623
|
RETURN_ERROR_IF(dst == NULL, memory_allocation, "NULL pointer!");
|
@@ -2378,16 +2629,47 @@ size_t ZSTD_getSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs,
|
|
2378
2629
|
zc->seqCollector = seqCollector;
|
2379
2630
|
|
2380
2631
|
ZSTD_compress2(zc, dst, dstCapacity, src, srcSize);
|
2381
|
-
|
2632
|
+
ZSTD_customFree(dst, ZSTD_defaultCMem);
|
2382
2633
|
return zc->seqCollector.seqIndex;
|
2383
2634
|
}
|
2384
2635
|
|
2385
|
-
|
2386
|
-
|
2636
|
+
size_t ZSTD_mergeBlockDelimiters(ZSTD_Sequence* sequences, size_t seqsSize) {
|
2637
|
+
size_t in = 0;
|
2638
|
+
size_t out = 0;
|
2639
|
+
for (; in < seqsSize; ++in) {
|
2640
|
+
if (sequences[in].offset == 0 && sequences[in].matchLength == 0) {
|
2641
|
+
if (in != seqsSize - 1) {
|
2642
|
+
sequences[in+1].litLength += sequences[in].litLength;
|
2643
|
+
}
|
2644
|
+
} else {
|
2645
|
+
sequences[out] = sequences[in];
|
2646
|
+
++out;
|
2647
|
+
}
|
2648
|
+
}
|
2649
|
+
return out;
|
2650
|
+
}
|
2651
|
+
|
2652
|
+
/* Unrolled loop to read four size_ts of input at a time. Returns 1 if is RLE, 0 if not. */
|
2653
|
+
static int ZSTD_isRLE(const BYTE* src, size_t length) {
|
2654
|
+
const BYTE* ip = src;
|
2655
|
+
const BYTE value = ip[0];
|
2656
|
+
const size_t valueST = (size_t)((U64)value * 0x0101010101010101ULL);
|
2657
|
+
const size_t unrollSize = sizeof(size_t) * 4;
|
2658
|
+
const size_t unrollMask = unrollSize - 1;
|
2659
|
+
const size_t prefixLength = length & unrollMask;
|
2387
2660
|
size_t i;
|
2388
|
-
|
2389
|
-
|
2390
|
-
|
2661
|
+
size_t u;
|
2662
|
+
if (length == 1) return 1;
|
2663
|
+
/* Check if prefix is RLE first before using unrolled loop */
|
2664
|
+
if (prefixLength && ZSTD_count(ip+1, ip, ip+prefixLength) != prefixLength-1) {
|
2665
|
+
return 0;
|
2666
|
+
}
|
2667
|
+
for (i = prefixLength; i != length; i += unrollSize) {
|
2668
|
+
for (u = 0; u < unrollSize; u += sizeof(size_t)) {
|
2669
|
+
if (MEM_readST(ip + i + u) != valueST) {
|
2670
|
+
return 0;
|
2671
|
+
}
|
2672
|
+
}
|
2391
2673
|
}
|
2392
2674
|
return 1;
|
2393
2675
|
}
|
@@ -2434,18 +2716,25 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
|
|
2434
2716
|
|
2435
2717
|
if (zc->seqCollector.collectSequences) {
|
2436
2718
|
ZSTD_copyBlockSequences(zc);
|
2719
|
+
ZSTD_confirmRepcodesAndEntropyTables(zc);
|
2437
2720
|
return 0;
|
2438
2721
|
}
|
2439
2722
|
|
2440
2723
|
/* encode sequences and literals */
|
2441
|
-
cSize =
|
2724
|
+
cSize = ZSTD_entropyCompressSequences(&zc->seqStore,
|
2442
2725
|
&zc->blockState.prevCBlock->entropy, &zc->blockState.nextCBlock->entropy,
|
2443
2726
|
&zc->appliedParams,
|
2444
2727
|
dst, dstCapacity,
|
2445
2728
|
srcSize,
|
2446
|
-
zc->entropyWorkspace,
|
2729
|
+
zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */,
|
2447
2730
|
zc->bmi2);
|
2448
2731
|
|
2732
|
+
if (zc->seqCollector.collectSequences) {
|
2733
|
+
ZSTD_copyBlockSequences(zc);
|
2734
|
+
return 0;
|
2735
|
+
}
|
2736
|
+
|
2737
|
+
|
2449
2738
|
if (frame &&
|
2450
2739
|
/* We don't want to emit our first block as a RLE even if it qualifies because
|
2451
2740
|
* doing so will cause the decoder (cli only) to throw a "should consume all input error."
|
@@ -2593,7 +2882,7 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
|
|
2593
2882
|
|
2594
2883
|
assert(cctx->appliedParams.cParams.windowLog <= ZSTD_WINDOWLOG_MAX);
|
2595
2884
|
|
2596
|
-
DEBUGLOG(
|
2885
|
+
DEBUGLOG(4, "ZSTD_compress_frameChunk (blockSize=%u)", (unsigned)blockSize);
|
2597
2886
|
if (cctx->appliedParams.fParams.checksumFlag && srcSize)
|
2598
2887
|
XXH64_update(&cctx->xxhState, src, srcSize);
|
2599
2888
|
|
@@ -2673,7 +2962,6 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
|
|
2673
2962
|
"dst buf is too small to fit worst-case frame header size.");
|
2674
2963
|
DEBUGLOG(4, "ZSTD_writeFrameHeader : dictIDFlag : %u ; dictID : %u ; dictIDSizeCode : %u",
|
2675
2964
|
!params->fParams.noDictIDFlag, (unsigned)dictID, (unsigned)dictIDSizeCode);
|
2676
|
-
|
2677
2965
|
if (params->format == ZSTD_f_zstd1) {
|
2678
2966
|
MEM_writeLE32(dst, ZSTD_MAGICNUMBER);
|
2679
2967
|
pos = 4;
|
@@ -2699,6 +2987,26 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
|
|
2699
2987
|
return pos;
|
2700
2988
|
}
|
2701
2989
|
|
2990
|
+
/* ZSTD_writeSkippableFrame_advanced() :
|
2991
|
+
* Writes out a skippable frame with the specified magic number variant (16 are supported),
|
2992
|
+
* from ZSTD_MAGIC_SKIPPABLE_START to ZSTD_MAGIC_SKIPPABLE_START+15, and the desired source data.
|
2993
|
+
*
|
2994
|
+
* Returns the total number of bytes written, or a ZSTD error code.
|
2995
|
+
*/
|
2996
|
+
size_t ZSTD_writeSkippableFrame(void* dst, size_t dstCapacity,
|
2997
|
+
const void* src, size_t srcSize, unsigned magicVariant) {
|
2998
|
+
BYTE* op = (BYTE*)dst;
|
2999
|
+
RETURN_ERROR_IF(dstCapacity < srcSize + ZSTD_SKIPPABLEHEADERSIZE /* Skippable frame overhead */,
|
3000
|
+
dstSize_tooSmall, "Not enough room for skippable frame");
|
3001
|
+
RETURN_ERROR_IF(srcSize > (unsigned)0xFFFFFFFF, srcSize_wrong, "Src size too large for skippable frame");
|
3002
|
+
RETURN_ERROR_IF(magicVariant > 15, parameter_outOfBound, "Skippable frame magic number variant not supported");
|
3003
|
+
|
3004
|
+
MEM_writeLE32(op, (U32)(ZSTD_MAGIC_SKIPPABLE_START + magicVariant));
|
3005
|
+
MEM_writeLE32(op+4, (U32)srcSize);
|
3006
|
+
ZSTD_memcpy(op+8, src, srcSize);
|
3007
|
+
return srcSize + ZSTD_SKIPPABLEHEADERSIZE;
|
3008
|
+
}
|
3009
|
+
|
2702
3010
|
/* ZSTD_writeLastEmptyBlock() :
|
2703
3011
|
* output an empty Block with end-of-frame mark to complete a frame
|
2704
3012
|
* @return : size of data written into `dst` (== ZSTD_blockHeaderSize (defined in zstd_internal.h))
|
@@ -2725,6 +3033,7 @@ size_t ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSe
|
|
2725
3033
|
cctx->externSeqStore.size = nbSeq;
|
2726
3034
|
cctx->externSeqStore.capacity = nbSeq;
|
2727
3035
|
cctx->externSeqStore.pos = 0;
|
3036
|
+
cctx->externSeqStore.posInSequence = 0;
|
2728
3037
|
return 0;
|
2729
3038
|
}
|
2730
3039
|
|
@@ -2862,8 +3171,12 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms,
|
|
2862
3171
|
case ZSTD_greedy:
|
2863
3172
|
case ZSTD_lazy:
|
2864
3173
|
case ZSTD_lazy2:
|
2865
|
-
if (chunk >= HASH_READ_SIZE)
|
3174
|
+
if (chunk >= HASH_READ_SIZE && ms->dedicatedDictSearch) {
|
3175
|
+
assert(chunk == remaining); /* must load everything in one go */
|
3176
|
+
ZSTD_dedicatedDictSearch_lazy_loadDictionary(ms, ichunk-HASH_READ_SIZE);
|
3177
|
+
} else if (chunk >= HASH_READ_SIZE) {
|
2866
3178
|
ZSTD_insertAndFindFirstIndex(ms, ichunk-HASH_READ_SIZE);
|
3179
|
+
}
|
2867
3180
|
break;
|
2868
3181
|
|
2869
3182
|
case ZSTD_btlazy2: /* we want the dictionary table fully sorted */
|
@@ -2887,22 +3200,28 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms,
|
|
2887
3200
|
|
2888
3201
|
|
2889
3202
|
/* Dictionaries that assign zero probability to symbols that show up causes problems
|
2890
|
-
|
2891
|
-
|
2892
|
-
|
2893
|
-
static
|
3203
|
+
* when FSE encoding. Mark dictionaries with zero probability symbols as FSE_repeat_check
|
3204
|
+
* and only dictionaries with 100% valid symbols can be assumed valid.
|
3205
|
+
*/
|
3206
|
+
static FSE_repeat ZSTD_dictNCountRepeat(short* normalizedCounter, unsigned dictMaxSymbolValue, unsigned maxSymbolValue)
|
3207
|
+
{
|
2894
3208
|
U32 s;
|
2895
|
-
|
3209
|
+
if (dictMaxSymbolValue < maxSymbolValue) {
|
3210
|
+
return FSE_repeat_check;
|
3211
|
+
}
|
2896
3212
|
for (s = 0; s <= maxSymbolValue; ++s) {
|
2897
|
-
|
3213
|
+
if (normalizedCounter[s] == 0) {
|
3214
|
+
return FSE_repeat_check;
|
3215
|
+
}
|
2898
3216
|
}
|
2899
|
-
return
|
3217
|
+
return FSE_repeat_valid;
|
2900
3218
|
}
|
2901
3219
|
|
2902
3220
|
size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace,
|
2903
|
-
short* offcodeNCount, unsigned* offcodeMaxValue,
|
2904
3221
|
const void* const dict, size_t dictSize)
|
2905
3222
|
{
|
3223
|
+
short offcodeNCount[MaxOff+1];
|
3224
|
+
unsigned offcodeMaxValue = MaxOff;
|
2906
3225
|
const BYTE* dictPtr = (const BYTE*)dict; /* skip magic num and dict ID */
|
2907
3226
|
const BYTE* const dictEnd = dictPtr + dictSize;
|
2908
3227
|
dictPtr += 8;
|
@@ -2924,16 +3243,16 @@ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace,
|
|
2924
3243
|
}
|
2925
3244
|
|
2926
3245
|
{ unsigned offcodeLog;
|
2927
|
-
size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
|
3246
|
+
size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
|
2928
3247
|
RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted, "");
|
2929
3248
|
RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted, "");
|
2930
|
-
/* Defer checking offcodeMaxValue because we need to know the size of the dictionary content */
|
2931
3249
|
/* fill all offset symbols to avoid garbage at end of table */
|
2932
3250
|
RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(
|
2933
3251
|
bs->entropy.fse.offcodeCTable,
|
2934
3252
|
offcodeNCount, MaxOff, offcodeLog,
|
2935
3253
|
workspace, HUF_WORKSPACE_SIZE)),
|
2936
3254
|
dictionary_corrupted, "");
|
3255
|
+
/* Defer checking offcodeMaxValue because we need to know the size of the dictionary content */
|
2937
3256
|
dictPtr += offcodeHeaderSize;
|
2938
3257
|
}
|
2939
3258
|
|
@@ -2942,13 +3261,12 @@ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace,
|
|
2942
3261
|
size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
|
2943
3262
|
RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted, "");
|
2944
3263
|
RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted, "");
|
2945
|
-
/* Every match length code must have non-zero probability */
|
2946
|
-
FORWARD_IF_ERROR( ZSTD_checkDictNCount(matchlengthNCount, matchlengthMaxValue, MaxML), "");
|
2947
3264
|
RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(
|
2948
3265
|
bs->entropy.fse.matchlengthCTable,
|
2949
3266
|
matchlengthNCount, matchlengthMaxValue, matchlengthLog,
|
2950
3267
|
workspace, HUF_WORKSPACE_SIZE)),
|
2951
3268
|
dictionary_corrupted, "");
|
3269
|
+
bs->entropy.fse.matchlength_repeatMode = ZSTD_dictNCountRepeat(matchlengthNCount, matchlengthMaxValue, MaxML);
|
2952
3270
|
dictPtr += matchlengthHeaderSize;
|
2953
3271
|
}
|
2954
3272
|
|
@@ -2957,13 +3275,12 @@ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace,
|
|
2957
3275
|
size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
|
2958
3276
|
RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted, "");
|
2959
3277
|
RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted, "");
|
2960
|
-
/* Every literal length code must have non-zero probability */
|
2961
|
-
FORWARD_IF_ERROR( ZSTD_checkDictNCount(litlengthNCount, litlengthMaxValue, MaxLL), "");
|
2962
3278
|
RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(
|
2963
3279
|
bs->entropy.fse.litlengthCTable,
|
2964
3280
|
litlengthNCount, litlengthMaxValue, litlengthLog,
|
2965
3281
|
workspace, HUF_WORKSPACE_SIZE)),
|
2966
3282
|
dictionary_corrupted, "");
|
3283
|
+
bs->entropy.fse.litlength_repeatMode = ZSTD_dictNCountRepeat(litlengthNCount, litlengthMaxValue, MaxLL);
|
2967
3284
|
dictPtr += litlengthHeaderSize;
|
2968
3285
|
}
|
2969
3286
|
|
@@ -2973,12 +3290,28 @@ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace,
|
|
2973
3290
|
bs->rep[2] = MEM_readLE32(dictPtr+8);
|
2974
3291
|
dictPtr += 12;
|
2975
3292
|
|
3293
|
+
{ size_t const dictContentSize = (size_t)(dictEnd - dictPtr);
|
3294
|
+
U32 offcodeMax = MaxOff;
|
3295
|
+
if (dictContentSize <= ((U32)-1) - 128 KB) {
|
3296
|
+
U32 const maxOffset = (U32)dictContentSize + 128 KB; /* The maximum offset that must be supported */
|
3297
|
+
offcodeMax = ZSTD_highbit32(maxOffset); /* Calculate minimum offset code required to represent maxOffset */
|
3298
|
+
}
|
3299
|
+
/* All offset values <= dictContentSize + 128 KB must be representable for a valid table */
|
3300
|
+
bs->entropy.fse.offcode_repeatMode = ZSTD_dictNCountRepeat(offcodeNCount, offcodeMaxValue, MIN(offcodeMax, MaxOff));
|
3301
|
+
|
3302
|
+
/* All repCodes must be <= dictContentSize and != 0 */
|
3303
|
+
{ U32 u;
|
3304
|
+
for (u=0; u<3; u++) {
|
3305
|
+
RETURN_ERROR_IF(bs->rep[u] == 0, dictionary_corrupted, "");
|
3306
|
+
RETURN_ERROR_IF(bs->rep[u] > dictContentSize, dictionary_corrupted, "");
|
3307
|
+
} } }
|
3308
|
+
|
2976
3309
|
return dictPtr - (const BYTE*)dict;
|
2977
3310
|
}
|
2978
3311
|
|
2979
3312
|
/* Dictionary format :
|
2980
3313
|
* See :
|
2981
|
-
* https://github.com/facebook/zstd/blob/
|
3314
|
+
* https://github.com/facebook/zstd/blob/release/doc/zstd_compression_format.md#dictionary-format
|
2982
3315
|
*/
|
2983
3316
|
/*! ZSTD_loadZstdDictionary() :
|
2984
3317
|
* @return : dictID, or an error code
|
@@ -2995,8 +3328,6 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs,
|
|
2995
3328
|
{
|
2996
3329
|
const BYTE* dictPtr = (const BYTE*)dict;
|
2997
3330
|
const BYTE* const dictEnd = dictPtr + dictSize;
|
2998
|
-
short offcodeNCount[MaxOff+1];
|
2999
|
-
unsigned offcodeMaxValue = MaxOff;
|
3000
3331
|
size_t dictID;
|
3001
3332
|
size_t eSize;
|
3002
3333
|
|
@@ -3005,32 +3336,16 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs,
|
|
3005
3336
|
assert(MEM_readLE32(dictPtr) == ZSTD_MAGIC_DICTIONARY);
|
3006
3337
|
|
3007
3338
|
dictID = params->fParams.noDictIDFlag ? 0 : MEM_readLE32(dictPtr + 4 /* skip magic number */ );
|
3008
|
-
eSize = ZSTD_loadCEntropy(bs, workspace,
|
3339
|
+
eSize = ZSTD_loadCEntropy(bs, workspace, dict, dictSize);
|
3009
3340
|
FORWARD_IF_ERROR(eSize, "ZSTD_loadCEntropy failed");
|
3010
3341
|
dictPtr += eSize;
|
3011
3342
|
|
3012
|
-
{
|
3013
|
-
|
3014
|
-
if (dictContentSize <= ((U32)-1) - 128 KB) {
|
3015
|
-
U32 const maxOffset = (U32)dictContentSize + 128 KB; /* The maximum offset that must be supported */
|
3016
|
-
offcodeMax = ZSTD_highbit32(maxOffset); /* Calculate minimum offset code required to represent maxOffset */
|
3017
|
-
}
|
3018
|
-
/* All offset values <= dictContentSize + 128 KB must be representable */
|
3019
|
-
FORWARD_IF_ERROR(ZSTD_checkDictNCount(offcodeNCount, offcodeMaxValue, MIN(offcodeMax, MaxOff)), "");
|
3020
|
-
/* All repCodes must be <= dictContentSize and != 0*/
|
3021
|
-
{ U32 u;
|
3022
|
-
for (u=0; u<3; u++) {
|
3023
|
-
RETURN_ERROR_IF(bs->rep[u] == 0, dictionary_corrupted, "");
|
3024
|
-
RETURN_ERROR_IF(bs->rep[u] > dictContentSize, dictionary_corrupted, "");
|
3025
|
-
} }
|
3026
|
-
|
3027
|
-
bs->entropy.fse.offcode_repeatMode = FSE_repeat_valid;
|
3028
|
-
bs->entropy.fse.matchlength_repeatMode = FSE_repeat_valid;
|
3029
|
-
bs->entropy.fse.litlength_repeatMode = FSE_repeat_valid;
|
3343
|
+
{
|
3344
|
+
size_t const dictContentSize = (size_t)(dictEnd - dictPtr);
|
3030
3345
|
FORWARD_IF_ERROR(ZSTD_loadDictionaryContent(
|
3031
3346
|
ms, NULL, ws, params, dictPtr, dictContentSize, dtlm), "");
|
3032
|
-
return dictID;
|
3033
3347
|
}
|
3348
|
+
return dictID;
|
3034
3349
|
}
|
3035
3350
|
|
3036
3351
|
/** ZSTD_compress_insertDictionary() :
|
@@ -3074,7 +3389,7 @@ ZSTD_compress_insertDictionary(ZSTD_compressedBlockState_t* bs,
|
|
3074
3389
|
}
|
3075
3390
|
|
3076
3391
|
#define ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF (128 KB)
|
3077
|
-
#define ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER (
|
3392
|
+
#define ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER (6ULL)
|
3078
3393
|
|
3079
3394
|
/*! ZSTD_compressBegin_internal() :
|
3080
3395
|
* @return : 0, or an error code */
|
@@ -3086,6 +3401,9 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
|
|
3086
3401
|
const ZSTD_CCtx_params* params, U64 pledgedSrcSize,
|
3087
3402
|
ZSTD_buffered_policy_e zbuff)
|
3088
3403
|
{
|
3404
|
+
#if ZSTD_TRACE
|
3405
|
+
cctx->traceCtx = ZSTD_trace_compress_begin(cctx);
|
3406
|
+
#endif
|
3089
3407
|
DEBUGLOG(4, "ZSTD_compressBegin_internal: wlog=%u", params->cParams.windowLog);
|
3090
3408
|
/* params are supposed to be fully validated at this point */
|
3091
3409
|
assert(!ZSTD_isError(ZSTD_checkCParams(params->cParams)));
|
@@ -3106,7 +3424,7 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
|
|
3106
3424
|
ZSTD_compress_insertDictionary(
|
3107
3425
|
cctx->blockState.prevCBlock, &cctx->blockState.matchState,
|
3108
3426
|
&cctx->ldmState, &cctx->workspace, &cctx->appliedParams, cdict->dictContent,
|
3109
|
-
cdict->dictContentSize, dictContentType, dtlm,
|
3427
|
+
cdict->dictContentSize, cdict->dictContentType, dtlm,
|
3110
3428
|
cctx->entropyWorkspace)
|
3111
3429
|
: ZSTD_compress_insertDictionary(
|
3112
3430
|
cctx->blockState.prevCBlock, &cctx->blockState.matchState,
|
@@ -3115,6 +3433,7 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
|
|
3115
3433
|
FORWARD_IF_ERROR(dictID, "ZSTD_compress_insertDictionary failed");
|
3116
3434
|
assert(dictID <= UINT_MAX);
|
3117
3435
|
cctx->dictID = (U32)dictID;
|
3436
|
+
cctx->dictContentSize = cdict ? cdict->dictContentSize : dictSize;
|
3118
3437
|
}
|
3119
3438
|
return 0;
|
3120
3439
|
}
|
@@ -3143,8 +3462,8 @@ size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx,
|
|
3143
3462
|
const void* dict, size_t dictSize,
|
3144
3463
|
ZSTD_parameters params, unsigned long long pledgedSrcSize)
|
3145
3464
|
{
|
3146
|
-
ZSTD_CCtx_params
|
3147
|
-
|
3465
|
+
ZSTD_CCtx_params cctxParams;
|
3466
|
+
ZSTD_CCtxParams_init_internal(&cctxParams, ¶ms, ZSTD_NO_CLEVEL);
|
3148
3467
|
return ZSTD_compressBegin_advanced_internal(cctx,
|
3149
3468
|
dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast,
|
3150
3469
|
NULL /*cdict*/,
|
@@ -3153,9 +3472,11 @@ size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx,
|
|
3153
3472
|
|
3154
3473
|
size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel)
|
3155
3474
|
{
|
3156
|
-
|
3157
|
-
|
3158
|
-
|
3475
|
+
ZSTD_CCtx_params cctxParams;
|
3476
|
+
{
|
3477
|
+
ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_noAttachDict);
|
3478
|
+
ZSTD_CCtxParams_init_internal(&cctxParams, ¶ms, (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : compressionLevel);
|
3479
|
+
}
|
3159
3480
|
DEBUGLOG(4, "ZSTD_compressBegin_usingDict (dictSize=%u)", (unsigned)dictSize);
|
3160
3481
|
return ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, NULL,
|
3161
3482
|
&cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, ZSTDb_not_buffered);
|
@@ -3209,6 +3530,30 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
|
|
3209
3530
|
return op-ostart;
|
3210
3531
|
}
|
3211
3532
|
|
3533
|
+
void ZSTD_CCtx_trace(ZSTD_CCtx* cctx, size_t extraCSize)
|
3534
|
+
{
|
3535
|
+
#if ZSTD_TRACE
|
3536
|
+
if (cctx->traceCtx) {
|
3537
|
+
int const streaming = cctx->inBuffSize > 0 || cctx->outBuffSize > 0 || cctx->appliedParams.nbWorkers > 0;
|
3538
|
+
ZSTD_Trace trace;
|
3539
|
+
ZSTD_memset(&trace, 0, sizeof(trace));
|
3540
|
+
trace.version = ZSTD_VERSION_NUMBER;
|
3541
|
+
trace.streaming = streaming;
|
3542
|
+
trace.dictionaryID = cctx->dictID;
|
3543
|
+
trace.dictionarySize = cctx->dictContentSize;
|
3544
|
+
trace.uncompressedSize = cctx->consumedSrcSize;
|
3545
|
+
trace.compressedSize = cctx->producedCSize + extraCSize;
|
3546
|
+
trace.params = &cctx->appliedParams;
|
3547
|
+
trace.cctx = cctx;
|
3548
|
+
ZSTD_trace_compress_end(cctx->traceCtx, &trace);
|
3549
|
+
}
|
3550
|
+
cctx->traceCtx = 0;
|
3551
|
+
#else
|
3552
|
+
(void)cctx;
|
3553
|
+
(void)extraCSize;
|
3554
|
+
#endif
|
3555
|
+
}
|
3556
|
+
|
3212
3557
|
size_t ZSTD_compressEnd (ZSTD_CCtx* cctx,
|
3213
3558
|
void* dst, size_t dstCapacity,
|
3214
3559
|
const void* src, size_t srcSize)
|
@@ -3231,39 +3576,25 @@ size_t ZSTD_compressEnd (ZSTD_CCtx* cctx,
|
|
3231
3576
|
(unsigned)cctx->pledgedSrcSizePlusOne-1,
|
3232
3577
|
(unsigned)cctx->consumedSrcSize);
|
3233
3578
|
}
|
3579
|
+
ZSTD_CCtx_trace(cctx, endResult);
|
3234
3580
|
return cSize + endResult;
|
3235
3581
|
}
|
3236
3582
|
|
3237
|
-
|
3238
|
-
static size_t ZSTD_compress_internal (ZSTD_CCtx* cctx,
|
3239
|
-
void* dst, size_t dstCapacity,
|
3240
|
-
const void* src, size_t srcSize,
|
3241
|
-
const void* dict,size_t dictSize,
|
3242
|
-
const ZSTD_parameters* params)
|
3243
|
-
{
|
3244
|
-
ZSTD_CCtx_params const cctxParams =
|
3245
|
-
ZSTD_assignParamsToCCtxParams(&cctx->requestedParams, params);
|
3246
|
-
DEBUGLOG(4, "ZSTD_compress_internal");
|
3247
|
-
return ZSTD_compress_advanced_internal(cctx,
|
3248
|
-
dst, dstCapacity,
|
3249
|
-
src, srcSize,
|
3250
|
-
dict, dictSize,
|
3251
|
-
&cctxParams);
|
3252
|
-
}
|
3253
|
-
|
3254
3583
|
size_t ZSTD_compress_advanced (ZSTD_CCtx* cctx,
|
3255
3584
|
void* dst, size_t dstCapacity,
|
3256
3585
|
const void* src, size_t srcSize,
|
3257
3586
|
const void* dict,size_t dictSize,
|
3258
3587
|
ZSTD_parameters params)
|
3259
3588
|
{
|
3589
|
+
ZSTD_CCtx_params cctxParams;
|
3260
3590
|
DEBUGLOG(4, "ZSTD_compress_advanced");
|
3261
3591
|
FORWARD_IF_ERROR(ZSTD_checkCParams(params.cParams), "");
|
3262
|
-
|
3263
|
-
|
3264
|
-
|
3265
|
-
|
3266
|
-
|
3592
|
+
ZSTD_CCtxParams_init_internal(&cctxParams, ¶ms, ZSTD_NO_CLEVEL);
|
3593
|
+
return ZSTD_compress_advanced_internal(cctx,
|
3594
|
+
dst, dstCapacity,
|
3595
|
+
src, srcSize,
|
3596
|
+
dict, dictSize,
|
3597
|
+
&cctxParams);
|
3267
3598
|
}
|
3268
3599
|
|
3269
3600
|
/* Internal */
|
@@ -3287,10 +3618,13 @@ size_t ZSTD_compress_usingDict(ZSTD_CCtx* cctx,
|
|
3287
3618
|
const void* dict, size_t dictSize,
|
3288
3619
|
int compressionLevel)
|
3289
3620
|
{
|
3290
|
-
|
3291
|
-
|
3621
|
+
ZSTD_CCtx_params cctxParams;
|
3622
|
+
{
|
3623
|
+
ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, srcSize, dict ? dictSize : 0, ZSTD_cpm_noAttachDict);
|
3624
|
+
assert(params.fParams.contentSizeFlag == 1);
|
3625
|
+
ZSTD_CCtxParams_init_internal(&cctxParams, ¶ms, (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT: compressionLevel);
|
3626
|
+
}
|
3292
3627
|
DEBUGLOG(4, "ZSTD_compress_usingDict (srcSize=%u)", (unsigned)srcSize);
|
3293
|
-
assert(params.fParams.contentSizeFlag == 1);
|
3294
3628
|
return ZSTD_compress_advanced_internal(cctx, dst, dstCapacity, src, srcSize, dict, dictSize, &cctxParams);
|
3295
3629
|
}
|
3296
3630
|
|
@@ -3309,10 +3643,17 @@ size_t ZSTD_compress(void* dst, size_t dstCapacity,
|
|
3309
3643
|
int compressionLevel)
|
3310
3644
|
{
|
3311
3645
|
size_t result;
|
3646
|
+
#if ZSTD_COMPRESS_HEAPMODE
|
3647
|
+
ZSTD_CCtx* cctx = ZSTD_createCCtx();
|
3648
|
+
RETURN_ERROR_IF(!cctx, memory_allocation, "ZSTD_createCCtx failed");
|
3649
|
+
result = ZSTD_compressCCtx(cctx, dst, dstCapacity, src, srcSize, compressionLevel);
|
3650
|
+
ZSTD_freeCCtx(cctx);
|
3651
|
+
#else
|
3312
3652
|
ZSTD_CCtx ctxBody;
|
3313
3653
|
ZSTD_initCCtx(&ctxBody, ZSTD_defaultCMem);
|
3314
3654
|
result = ZSTD_compressCCtx(&ctxBody, dst, dstCapacity, src, srcSize, compressionLevel);
|
3315
3655
|
ZSTD_freeCCtxContent(&ctxBody); /* can't free ctxBody itself, as it's on stack; free only heap content */
|
3656
|
+
#endif
|
3316
3657
|
return result;
|
3317
3658
|
}
|
3318
3659
|
|
@@ -3335,7 +3676,7 @@ size_t ZSTD_estimateCDictSize_advanced(
|
|
3335
3676
|
|
3336
3677
|
size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel)
|
3337
3678
|
{
|
3338
|
-
ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize);
|
3679
|
+
ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict);
|
3339
3680
|
return ZSTD_estimateCDictSize_advanced(dictSize, cParams, ZSTD_dlm_byCopy);
|
3340
3681
|
}
|
3341
3682
|
|
@@ -3353,20 +3694,25 @@ static size_t ZSTD_initCDict_internal(
|
|
3353
3694
|
const void* dictBuffer, size_t dictSize,
|
3354
3695
|
ZSTD_dictLoadMethod_e dictLoadMethod,
|
3355
3696
|
ZSTD_dictContentType_e dictContentType,
|
3356
|
-
|
3697
|
+
ZSTD_CCtx_params params)
|
3357
3698
|
{
|
3358
3699
|
DEBUGLOG(3, "ZSTD_initCDict_internal (dictContentType:%u)", (unsigned)dictContentType);
|
3359
|
-
assert(!ZSTD_checkCParams(cParams));
|
3360
|
-
cdict->matchState.cParams = cParams;
|
3700
|
+
assert(!ZSTD_checkCParams(params.cParams));
|
3701
|
+
cdict->matchState.cParams = params.cParams;
|
3702
|
+
cdict->matchState.dedicatedDictSearch = params.enableDedicatedDictSearch;
|
3703
|
+
if (cdict->matchState.dedicatedDictSearch && dictSize > ZSTD_CHUNKSIZE_MAX) {
|
3704
|
+
cdict->matchState.dedicatedDictSearch = 0;
|
3705
|
+
}
|
3361
3706
|
if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dictBuffer) || (!dictSize)) {
|
3362
3707
|
cdict->dictContent = dictBuffer;
|
3363
3708
|
} else {
|
3364
3709
|
void *internalBuffer = ZSTD_cwksp_reserve_object(&cdict->workspace, ZSTD_cwksp_align(dictSize, sizeof(void*)));
|
3365
3710
|
RETURN_ERROR_IF(!internalBuffer, memory_allocation, "NULL pointer!");
|
3366
3711
|
cdict->dictContent = internalBuffer;
|
3367
|
-
|
3712
|
+
ZSTD_memcpy(internalBuffer, dictBuffer, dictSize);
|
3368
3713
|
}
|
3369
3714
|
cdict->dictContentSize = dictSize;
|
3715
|
+
cdict->dictContentType = dictContentType;
|
3370
3716
|
|
3371
3717
|
cdict->entropyWorkspace = (U32*)ZSTD_cwksp_reserve_object(&cdict->workspace, HUF_WORKSPACE_SIZE);
|
3372
3718
|
|
@@ -3376,18 +3722,15 @@ static size_t ZSTD_initCDict_internal(
|
|
3376
3722
|
FORWARD_IF_ERROR(ZSTD_reset_matchState(
|
3377
3723
|
&cdict->matchState,
|
3378
3724
|
&cdict->workspace,
|
3379
|
-
&cParams,
|
3725
|
+
¶ms.cParams,
|
3380
3726
|
ZSTDcrp_makeClean,
|
3381
3727
|
ZSTDirp_reset,
|
3382
3728
|
ZSTD_resetTarget_CDict), "");
|
3383
3729
|
/* (Maybe) load the dictionary
|
3384
3730
|
* Skips loading the dictionary if it is < 8 bytes.
|
3385
3731
|
*/
|
3386
|
-
{
|
3387
|
-
memset(¶ms, 0, sizeof(params));
|
3388
|
-
params.compressionLevel = ZSTD_CLEVEL_DEFAULT;
|
3732
|
+
{ params.compressionLevel = ZSTD_CLEVEL_DEFAULT;
|
3389
3733
|
params.fParams.contentSizeFlag = 1;
|
3390
|
-
params.cParams = cParams;
|
3391
3734
|
{ size_t const dictID = ZSTD_compress_insertDictionary(
|
3392
3735
|
&cdict->cBlockState, &cdict->matchState, NULL, &cdict->workspace,
|
3393
3736
|
¶ms, cdict->dictContent, cdict->dictContentSize,
|
@@ -3401,13 +3744,11 @@ static size_t ZSTD_initCDict_internal(
|
|
3401
3744
|
return 0;
|
3402
3745
|
}
|
3403
3746
|
|
3404
|
-
ZSTD_CDict*
|
3747
|
+
static ZSTD_CDict* ZSTD_createCDict_advanced_internal(size_t dictSize,
|
3405
3748
|
ZSTD_dictLoadMethod_e dictLoadMethod,
|
3406
|
-
ZSTD_dictContentType_e dictContentType,
|
3407
3749
|
ZSTD_compressionParameters cParams, ZSTD_customMem customMem)
|
3408
3750
|
{
|
3409
|
-
|
3410
|
-
if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
|
3751
|
+
if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;
|
3411
3752
|
|
3412
3753
|
{ size_t const workspaceSize =
|
3413
3754
|
ZSTD_cwksp_alloc_size(sizeof(ZSTD_CDict)) +
|
@@ -3415,52 +3756,111 @@ ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize,
|
|
3415
3756
|
ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 0) +
|
3416
3757
|
(dictLoadMethod == ZSTD_dlm_byRef ? 0
|
3417
3758
|
: ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(dictSize, sizeof(void*))));
|
3418
|
-
void* const workspace =
|
3759
|
+
void* const workspace = ZSTD_customMalloc(workspaceSize, customMem);
|
3419
3760
|
ZSTD_cwksp ws;
|
3420
3761
|
ZSTD_CDict* cdict;
|
3421
3762
|
|
3422
3763
|
if (!workspace) {
|
3423
|
-
|
3764
|
+
ZSTD_customFree(workspace, customMem);
|
3424
3765
|
return NULL;
|
3425
3766
|
}
|
3426
3767
|
|
3427
|
-
ZSTD_cwksp_init(&ws, workspace, workspaceSize);
|
3768
|
+
ZSTD_cwksp_init(&ws, workspace, workspaceSize, ZSTD_cwksp_dynamic_alloc);
|
3428
3769
|
|
3429
3770
|
cdict = (ZSTD_CDict*)ZSTD_cwksp_reserve_object(&ws, sizeof(ZSTD_CDict));
|
3430
3771
|
assert(cdict != NULL);
|
3431
3772
|
ZSTD_cwksp_move(&cdict->workspace, &ws);
|
3432
3773
|
cdict->customMem = customMem;
|
3433
|
-
cdict->compressionLevel =
|
3434
|
-
|
3435
|
-
if (ZSTD_isError( ZSTD_initCDict_internal(cdict,
|
3436
|
-
dictBuffer, dictSize,
|
3437
|
-
dictLoadMethod, dictContentType,
|
3438
|
-
cParams) )) {
|
3439
|
-
ZSTD_freeCDict(cdict);
|
3440
|
-
return NULL;
|
3441
|
-
}
|
3774
|
+
cdict->compressionLevel = ZSTD_NO_CLEVEL; /* signals advanced API usage */
|
3442
3775
|
|
3443
3776
|
return cdict;
|
3444
3777
|
}
|
3445
3778
|
}
|
3446
3779
|
|
3780
|
+
ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize,
|
3781
|
+
ZSTD_dictLoadMethod_e dictLoadMethod,
|
3782
|
+
ZSTD_dictContentType_e dictContentType,
|
3783
|
+
ZSTD_compressionParameters cParams,
|
3784
|
+
ZSTD_customMem customMem)
|
3785
|
+
{
|
3786
|
+
ZSTD_CCtx_params cctxParams;
|
3787
|
+
ZSTD_memset(&cctxParams, 0, sizeof(cctxParams));
|
3788
|
+
ZSTD_CCtxParams_init(&cctxParams, 0);
|
3789
|
+
cctxParams.cParams = cParams;
|
3790
|
+
cctxParams.customMem = customMem;
|
3791
|
+
return ZSTD_createCDict_advanced2(
|
3792
|
+
dictBuffer, dictSize,
|
3793
|
+
dictLoadMethod, dictContentType,
|
3794
|
+
&cctxParams, customMem);
|
3795
|
+
}
|
3796
|
+
|
3797
|
+
ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_advanced2(
|
3798
|
+
const void* dict, size_t dictSize,
|
3799
|
+
ZSTD_dictLoadMethod_e dictLoadMethod,
|
3800
|
+
ZSTD_dictContentType_e dictContentType,
|
3801
|
+
const ZSTD_CCtx_params* originalCctxParams,
|
3802
|
+
ZSTD_customMem customMem)
|
3803
|
+
{
|
3804
|
+
ZSTD_CCtx_params cctxParams = *originalCctxParams;
|
3805
|
+
ZSTD_compressionParameters cParams;
|
3806
|
+
ZSTD_CDict* cdict;
|
3807
|
+
|
3808
|
+
DEBUGLOG(3, "ZSTD_createCDict_advanced2, mode %u", (unsigned)dictContentType);
|
3809
|
+
if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
|
3810
|
+
|
3811
|
+
if (cctxParams.enableDedicatedDictSearch) {
|
3812
|
+
cParams = ZSTD_dedicatedDictSearch_getCParams(
|
3813
|
+
cctxParams.compressionLevel, dictSize);
|
3814
|
+
ZSTD_overrideCParams(&cParams, &cctxParams.cParams);
|
3815
|
+
} else {
|
3816
|
+
cParams = ZSTD_getCParamsFromCCtxParams(
|
3817
|
+
&cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict);
|
3818
|
+
}
|
3819
|
+
|
3820
|
+
if (!ZSTD_dedicatedDictSearch_isSupported(&cParams)) {
|
3821
|
+
/* Fall back to non-DDSS params */
|
3822
|
+
cctxParams.enableDedicatedDictSearch = 0;
|
3823
|
+
cParams = ZSTD_getCParamsFromCCtxParams(
|
3824
|
+
&cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict);
|
3825
|
+
}
|
3826
|
+
|
3827
|
+
cctxParams.cParams = cParams;
|
3828
|
+
|
3829
|
+
cdict = ZSTD_createCDict_advanced_internal(dictSize,
|
3830
|
+
dictLoadMethod, cctxParams.cParams,
|
3831
|
+
customMem);
|
3832
|
+
|
3833
|
+
if (ZSTD_isError( ZSTD_initCDict_internal(cdict,
|
3834
|
+
dict, dictSize,
|
3835
|
+
dictLoadMethod, dictContentType,
|
3836
|
+
cctxParams) )) {
|
3837
|
+
ZSTD_freeCDict(cdict);
|
3838
|
+
return NULL;
|
3839
|
+
}
|
3840
|
+
|
3841
|
+
return cdict;
|
3842
|
+
}
|
3843
|
+
|
3447
3844
|
ZSTD_CDict* ZSTD_createCDict(const void* dict, size_t dictSize, int compressionLevel)
|
3448
3845
|
{
|
3449
|
-
ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize);
|
3450
|
-
ZSTD_CDict* cdict = ZSTD_createCDict_advanced(dict, dictSize,
|
3846
|
+
ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict);
|
3847
|
+
ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dict, dictSize,
|
3451
3848
|
ZSTD_dlm_byCopy, ZSTD_dct_auto,
|
3452
3849
|
cParams, ZSTD_defaultCMem);
|
3453
3850
|
if (cdict)
|
3454
|
-
cdict->compressionLevel = compressionLevel == 0 ? ZSTD_CLEVEL_DEFAULT : compressionLevel;
|
3851
|
+
cdict->compressionLevel = (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : compressionLevel;
|
3455
3852
|
return cdict;
|
3456
3853
|
}
|
3457
3854
|
|
3458
3855
|
ZSTD_CDict* ZSTD_createCDict_byReference(const void* dict, size_t dictSize, int compressionLevel)
|
3459
3856
|
{
|
3460
|
-
ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize);
|
3461
|
-
|
3857
|
+
ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict);
|
3858
|
+
ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dict, dictSize,
|
3462
3859
|
ZSTD_dlm_byRef, ZSTD_dct_auto,
|
3463
3860
|
cParams, ZSTD_defaultCMem);
|
3861
|
+
if (cdict)
|
3862
|
+
cdict->compressionLevel = (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : compressionLevel;
|
3863
|
+
return cdict;
|
3464
3864
|
}
|
3465
3865
|
|
3466
3866
|
size_t ZSTD_freeCDict(ZSTD_CDict* cdict)
|
@@ -3470,7 +3870,7 @@ size_t ZSTD_freeCDict(ZSTD_CDict* cdict)
|
|
3470
3870
|
int cdictInWorkspace = ZSTD_cwksp_owns_buffer(&cdict->workspace, cdict);
|
3471
3871
|
ZSTD_cwksp_free(&cdict->workspace, cMem);
|
3472
3872
|
if (!cdictInWorkspace) {
|
3473
|
-
|
3873
|
+
ZSTD_customFree(cdict, cMem);
|
3474
3874
|
}
|
3475
3875
|
return 0;
|
3476
3876
|
}
|
@@ -3503,12 +3903,13 @@ const ZSTD_CDict* ZSTD_initStaticCDict(
|
|
3503
3903
|
+ ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE)
|
3504
3904
|
+ matchStateSize;
|
3505
3905
|
ZSTD_CDict* cdict;
|
3906
|
+
ZSTD_CCtx_params params;
|
3506
3907
|
|
3507
3908
|
if ((size_t)workspace & 7) return NULL; /* 8-aligned */
|
3508
3909
|
|
3509
3910
|
{
|
3510
3911
|
ZSTD_cwksp ws;
|
3511
|
-
ZSTD_cwksp_init(&ws, workspace, workspaceSize);
|
3912
|
+
ZSTD_cwksp_init(&ws, workspace, workspaceSize, ZSTD_cwksp_static_alloc);
|
3512
3913
|
cdict = (ZSTD_CDict*)ZSTD_cwksp_reserve_object(&ws, sizeof(ZSTD_CDict));
|
3513
3914
|
if (cdict == NULL) return NULL;
|
3514
3915
|
ZSTD_cwksp_move(&cdict->workspace, &ws);
|
@@ -3518,10 +3919,13 @@ const ZSTD_CDict* ZSTD_initStaticCDict(
|
|
3518
3919
|
(unsigned)workspaceSize, (unsigned)neededSize, (unsigned)(workspaceSize < neededSize));
|
3519
3920
|
if (workspaceSize < neededSize) return NULL;
|
3520
3921
|
|
3922
|
+
ZSTD_CCtxParams_init(¶ms, 0);
|
3923
|
+
params.cParams = cParams;
|
3924
|
+
|
3521
3925
|
if (ZSTD_isError( ZSTD_initCDict_internal(cdict,
|
3522
3926
|
dict, dictSize,
|
3523
3927
|
dictLoadMethod, dictContentType,
|
3524
|
-
|
3928
|
+
params) ))
|
3525
3929
|
return NULL;
|
3526
3930
|
|
3527
3931
|
return cdict;
|
@@ -3533,40 +3937,54 @@ ZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict)
|
|
3533
3937
|
return cdict->matchState.cParams;
|
3534
3938
|
}
|
3535
3939
|
|
3940
|
+
/*! ZSTD_getDictID_fromCDict() :
|
3941
|
+
* Provides the dictID of the dictionary loaded into `cdict`.
|
3942
|
+
* If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.
|
3943
|
+
* Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */
|
3944
|
+
unsigned ZSTD_getDictID_fromCDict(const ZSTD_CDict* cdict)
|
3945
|
+
{
|
3946
|
+
if (cdict==NULL) return 0;
|
3947
|
+
return cdict->dictID;
|
3948
|
+
}
|
3949
|
+
|
3950
|
+
|
3536
3951
|
/* ZSTD_compressBegin_usingCDict_advanced() :
|
3537
3952
|
* cdict must be != NULL */
|
3538
3953
|
size_t ZSTD_compressBegin_usingCDict_advanced(
|
3539
3954
|
ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict,
|
3540
3955
|
ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize)
|
3541
3956
|
{
|
3957
|
+
ZSTD_CCtx_params cctxParams;
|
3542
3958
|
DEBUGLOG(4, "ZSTD_compressBegin_usingCDict_advanced");
|
3543
3959
|
RETURN_ERROR_IF(cdict==NULL, dictionary_wrong, "NULL pointer!");
|
3544
|
-
|
3960
|
+
/* Initialize the cctxParams from the cdict */
|
3961
|
+
{
|
3962
|
+
ZSTD_parameters params;
|
3963
|
+
params.fParams = fParams;
|
3545
3964
|
params.cParams = ( pledgedSrcSize < ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF
|
3546
3965
|
|| pledgedSrcSize < cdict->dictContentSize * ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER
|
3547
3966
|
|| pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN
|
3548
|
-
|| cdict->compressionLevel == 0 )
|
3549
|
-
&& (params.attachDictPref != ZSTD_dictForceLoad) ?
|
3967
|
+
|| cdict->compressionLevel == 0 ) ?
|
3550
3968
|
ZSTD_getCParamsFromCDict(cdict)
|
3551
3969
|
: ZSTD_getCParams(cdict->compressionLevel,
|
3552
3970
|
pledgedSrcSize,
|
3553
3971
|
cdict->dictContentSize);
|
3554
|
-
|
3555
|
-
* source size is known. Limit the increase to 19, which is the
|
3556
|
-
* window log for compression level 1 with the largest source size.
|
3557
|
-
*/
|
3558
|
-
if (pledgedSrcSize != ZSTD_CONTENTSIZE_UNKNOWN) {
|
3559
|
-
U32 const limitedSrcSize = (U32)MIN(pledgedSrcSize, 1U << 19);
|
3560
|
-
U32 const limitedSrcLog = limitedSrcSize > 1 ? ZSTD_highbit32(limitedSrcSize - 1) + 1 : 1;
|
3561
|
-
params.cParams.windowLog = MAX(params.cParams.windowLog, limitedSrcLog);
|
3562
|
-
}
|
3563
|
-
params.fParams = fParams;
|
3564
|
-
return ZSTD_compressBegin_internal(cctx,
|
3565
|
-
NULL, 0, ZSTD_dct_auto, ZSTD_dtlm_fast,
|
3566
|
-
cdict,
|
3567
|
-
¶ms, pledgedSrcSize,
|
3568
|
-
ZSTDb_not_buffered);
|
3972
|
+
ZSTD_CCtxParams_init_internal(&cctxParams, ¶ms, cdict->compressionLevel);
|
3569
3973
|
}
|
3974
|
+
/* Increase window log to fit the entire dictionary and source if the
|
3975
|
+
* source size is known. Limit the increase to 19, which is the
|
3976
|
+
* window log for compression level 1 with the largest source size.
|
3977
|
+
*/
|
3978
|
+
if (pledgedSrcSize != ZSTD_CONTENTSIZE_UNKNOWN) {
|
3979
|
+
U32 const limitedSrcSize = (U32)MIN(pledgedSrcSize, 1U << 19);
|
3980
|
+
U32 const limitedSrcLog = limitedSrcSize > 1 ? ZSTD_highbit32(limitedSrcSize - 1) + 1 : 1;
|
3981
|
+
cctxParams.cParams.windowLog = MAX(cctxParams.cParams.windowLog, limitedSrcLog);
|
3982
|
+
}
|
3983
|
+
return ZSTD_compressBegin_internal(cctx,
|
3984
|
+
NULL, 0, ZSTD_dct_auto, ZSTD_dtlm_fast,
|
3985
|
+
cdict,
|
3986
|
+
&cctxParams, pledgedSrcSize,
|
3987
|
+
ZSTDb_not_buffered);
|
3570
3988
|
}
|
3571
3989
|
|
3572
3990
|
/* ZSTD_compressBegin_usingCDict() :
|
@@ -3640,32 +4058,12 @@ size_t ZSTD_CStreamOutSize(void)
|
|
3640
4058
|
return ZSTD_compressBound(ZSTD_BLOCKSIZE_MAX) + ZSTD_blockHeaderSize + 4 /* 32-bits hash */ ;
|
3641
4059
|
}
|
3642
4060
|
|
3643
|
-
static
|
3644
|
-
const void* const dict, size_t const dictSize, ZSTD_dictContentType_e const dictContentType,
|
3645
|
-
const ZSTD_CDict* const cdict,
|
3646
|
-
ZSTD_CCtx_params params, unsigned long long const pledgedSrcSize)
|
4061
|
+
static ZSTD_cParamMode_e ZSTD_getCParamMode(ZSTD_CDict const* cdict, ZSTD_CCtx_params const* params, U64 pledgedSrcSize)
|
3647
4062
|
{
|
3648
|
-
|
3649
|
-
|
3650
|
-
|
3651
|
-
|
3652
|
-
assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
|
3653
|
-
assert(!((dict) && (cdict))); /* either dict or cdict, not both */
|
3654
|
-
|
3655
|
-
FORWARD_IF_ERROR( ZSTD_compressBegin_internal(cctx,
|
3656
|
-
dict, dictSize, dictContentType, ZSTD_dtlm_fast,
|
3657
|
-
cdict,
|
3658
|
-
¶ms, pledgedSrcSize,
|
3659
|
-
ZSTDb_buffered) , "");
|
3660
|
-
|
3661
|
-
cctx->inToCompress = 0;
|
3662
|
-
cctx->inBuffPos = 0;
|
3663
|
-
cctx->inBuffTarget = cctx->blockSize
|
3664
|
-
+ (cctx->blockSize == pledgedSrcSize); /* for small input: avoid automatic flush on reaching end of block, since it would require to add a 3-bytes null block to end frame */
|
3665
|
-
cctx->outBuffContentSize = cctx->outBuffFlushedSize = 0;
|
3666
|
-
cctx->streamStage = zcss_load;
|
3667
|
-
cctx->frameEnded = 0;
|
3668
|
-
return 0; /* ready to go */
|
4063
|
+
if (cdict != NULL && ZSTD_shouldAttachDict(cdict, params, pledgedSrcSize))
|
4064
|
+
return ZSTD_cpm_attachDict;
|
4065
|
+
else
|
4066
|
+
return ZSTD_cpm_noAttachDict;
|
3669
4067
|
}
|
3670
4068
|
|
3671
4069
|
/* ZSTD_resetCStream():
|
@@ -3749,7 +4147,7 @@ size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,
|
|
3749
4147
|
FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
|
3750
4148
|
FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , "");
|
3751
4149
|
FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) , "");
|
3752
|
-
|
4150
|
+
ZSTD_CCtxParams_setZstdParams(&zcs->requestedParams, ¶ms);
|
3753
4151
|
FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) , "");
|
3754
4152
|
return 0;
|
3755
4153
|
}
|
@@ -3815,12 +4213,17 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
|
|
3815
4213
|
|
3816
4214
|
/* check expectations */
|
3817
4215
|
DEBUGLOG(5, "ZSTD_compressStream_generic, flush=%u", (unsigned)flushMode);
|
3818
|
-
|
3819
|
-
|
3820
|
-
|
3821
|
-
|
4216
|
+
if (zcs->appliedParams.inBufferMode == ZSTD_bm_buffered) {
|
4217
|
+
assert(zcs->inBuff != NULL);
|
4218
|
+
assert(zcs->inBuffSize > 0);
|
4219
|
+
}
|
4220
|
+
if (zcs->appliedParams.outBufferMode == ZSTD_bm_buffered) {
|
4221
|
+
assert(zcs->outBuff != NULL);
|
4222
|
+
assert(zcs->outBuffSize > 0);
|
4223
|
+
}
|
3822
4224
|
assert(output->pos <= output->size);
|
3823
4225
|
assert(input->pos <= input->size);
|
4226
|
+
assert((U32)flushMode <= (U32)ZSTD_e_end);
|
3824
4227
|
|
3825
4228
|
while (someMoreWork) {
|
3826
4229
|
switch(zcs->streamStage)
|
@@ -3830,7 +4233,8 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
|
|
3830
4233
|
|
3831
4234
|
case zcss_load:
|
3832
4235
|
if ( (flushMode == ZSTD_e_end)
|
3833
|
-
&& ((size_t)(oend-op) >= ZSTD_compressBound(iend-ip)
|
4236
|
+
&& ( (size_t)(oend-op) >= ZSTD_compressBound(iend-ip) /* Enough output space */
|
4237
|
+
|| zcs->appliedParams.outBufferMode == ZSTD_bm_stable) /* OR we are allowed to return dstSizeTooSmall */
|
3834
4238
|
&& (zcs->inBuffPos == 0) ) {
|
3835
4239
|
/* shortcut to compression pass directly into output buffer */
|
3836
4240
|
size_t const cSize = ZSTD_compressEnd(zcs,
|
@@ -3843,8 +4247,9 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
|
|
3843
4247
|
ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
|
3844
4248
|
someMoreWork = 0; break;
|
3845
4249
|
}
|
3846
|
-
/* complete loading into inBuffer */
|
3847
|
-
|
4250
|
+
/* complete loading into inBuffer in buffered mode */
|
4251
|
+
if (zcs->appliedParams.inBufferMode == ZSTD_bm_buffered) {
|
4252
|
+
size_t const toLoad = zcs->inBuffTarget - zcs->inBuffPos;
|
3848
4253
|
size_t const loaded = ZSTD_limitCopy(
|
3849
4254
|
zcs->inBuff + zcs->inBuffPos, toLoad,
|
3850
4255
|
ip, iend-ip);
|
@@ -3864,31 +4269,49 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
|
|
3864
4269
|
}
|
3865
4270
|
/* compress current block (note : this stage cannot be stopped in the middle) */
|
3866
4271
|
DEBUGLOG(5, "stream compression stage (flushMode==%u)", flushMode);
|
3867
|
-
{
|
4272
|
+
{ int const inputBuffered = (zcs->appliedParams.inBufferMode == ZSTD_bm_buffered);
|
4273
|
+
void* cDst;
|
3868
4274
|
size_t cSize;
|
3869
|
-
size_t const iSize = zcs->inBuffPos - zcs->inToCompress;
|
3870
4275
|
size_t oSize = oend-op;
|
3871
|
-
|
3872
|
-
|
4276
|
+
size_t const iSize = inputBuffered
|
4277
|
+
? zcs->inBuffPos - zcs->inToCompress
|
4278
|
+
: MIN((size_t)(iend - ip), zcs->blockSize);
|
4279
|
+
if (oSize >= ZSTD_compressBound(iSize) || zcs->appliedParams.outBufferMode == ZSTD_bm_stable)
|
3873
4280
|
cDst = op; /* compress into output buffer, to skip flush stage */
|
3874
4281
|
else
|
3875
4282
|
cDst = zcs->outBuff, oSize = zcs->outBuffSize;
|
3876
|
-
|
3877
|
-
|
3878
|
-
|
3879
|
-
|
3880
|
-
|
3881
|
-
|
3882
|
-
|
3883
|
-
|
3884
|
-
|
3885
|
-
|
3886
|
-
zcs->
|
3887
|
-
|
3888
|
-
|
3889
|
-
|
3890
|
-
|
3891
|
-
|
4283
|
+
if (inputBuffered) {
|
4284
|
+
unsigned const lastBlock = (flushMode == ZSTD_e_end) && (ip==iend);
|
4285
|
+
cSize = lastBlock ?
|
4286
|
+
ZSTD_compressEnd(zcs, cDst, oSize,
|
4287
|
+
zcs->inBuff + zcs->inToCompress, iSize) :
|
4288
|
+
ZSTD_compressContinue(zcs, cDst, oSize,
|
4289
|
+
zcs->inBuff + zcs->inToCompress, iSize);
|
4290
|
+
FORWARD_IF_ERROR(cSize, "%s", lastBlock ? "ZSTD_compressEnd failed" : "ZSTD_compressContinue failed");
|
4291
|
+
zcs->frameEnded = lastBlock;
|
4292
|
+
/* prepare next block */
|
4293
|
+
zcs->inBuffTarget = zcs->inBuffPos + zcs->blockSize;
|
4294
|
+
if (zcs->inBuffTarget > zcs->inBuffSize)
|
4295
|
+
zcs->inBuffPos = 0, zcs->inBuffTarget = zcs->blockSize;
|
4296
|
+
DEBUGLOG(5, "inBuffTarget:%u / inBuffSize:%u",
|
4297
|
+
(unsigned)zcs->inBuffTarget, (unsigned)zcs->inBuffSize);
|
4298
|
+
if (!lastBlock)
|
4299
|
+
assert(zcs->inBuffTarget <= zcs->inBuffSize);
|
4300
|
+
zcs->inToCompress = zcs->inBuffPos;
|
4301
|
+
} else {
|
4302
|
+
unsigned const lastBlock = (ip + iSize == iend);
|
4303
|
+
assert(flushMode == ZSTD_e_end /* Already validated */);
|
4304
|
+
cSize = lastBlock ?
|
4305
|
+
ZSTD_compressEnd(zcs, cDst, oSize, ip, iSize) :
|
4306
|
+
ZSTD_compressContinue(zcs, cDst, oSize, ip, iSize);
|
4307
|
+
/* Consume the input prior to error checking to mirror buffered mode. */
|
4308
|
+
if (iSize > 0)
|
4309
|
+
ip += iSize;
|
4310
|
+
FORWARD_IF_ERROR(cSize, "%s", lastBlock ? "ZSTD_compressEnd failed" : "ZSTD_compressContinue failed");
|
4311
|
+
zcs->frameEnded = lastBlock;
|
4312
|
+
if (lastBlock)
|
4313
|
+
assert(ip == iend);
|
4314
|
+
}
|
3892
4315
|
if (cDst == op) { /* no need to flush */
|
3893
4316
|
op += cSize;
|
3894
4317
|
if (zcs->frameEnded) {
|
@@ -3905,6 +4328,7 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
|
|
3905
4328
|
/* fall-through */
|
3906
4329
|
case zcss_flush:
|
3907
4330
|
DEBUGLOG(5, "flush stage");
|
4331
|
+
assert(zcs->appliedParams.outBufferMode == ZSTD_bm_buffered);
|
3908
4332
|
{ size_t const toFlush = zcs->outBuffContentSize - zcs->outBuffFlushedSize;
|
3909
4333
|
size_t const flushed = ZSTD_limitCopy(op, (size_t)(oend-op),
|
3910
4334
|
zcs->outBuff + zcs->outBuffFlushedSize, toFlush);
|
@@ -3959,6 +4383,123 @@ size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuf
|
|
3959
4383
|
return ZSTD_nextInputSizeHint_MTorST(zcs);
|
3960
4384
|
}
|
3961
4385
|
|
4386
|
+
/* After a compression call set the expected input/output buffer.
|
4387
|
+
* This is validated at the start of the next compression call.
|
4388
|
+
*/
|
4389
|
+
static void ZSTD_setBufferExpectations(ZSTD_CCtx* cctx, ZSTD_outBuffer const* output, ZSTD_inBuffer const* input)
|
4390
|
+
{
|
4391
|
+
if (cctx->appliedParams.inBufferMode == ZSTD_bm_stable) {
|
4392
|
+
cctx->expectedInBuffer = *input;
|
4393
|
+
}
|
4394
|
+
if (cctx->appliedParams.outBufferMode == ZSTD_bm_stable) {
|
4395
|
+
cctx->expectedOutBufferSize = output->size - output->pos;
|
4396
|
+
}
|
4397
|
+
}
|
4398
|
+
|
4399
|
+
/* Validate that the input/output buffers match the expectations set by
|
4400
|
+
* ZSTD_setBufferExpectations.
|
4401
|
+
*/
|
4402
|
+
static size_t ZSTD_checkBufferStability(ZSTD_CCtx const* cctx,
|
4403
|
+
ZSTD_outBuffer const* output,
|
4404
|
+
ZSTD_inBuffer const* input,
|
4405
|
+
ZSTD_EndDirective endOp)
|
4406
|
+
{
|
4407
|
+
if (cctx->appliedParams.inBufferMode == ZSTD_bm_stable) {
|
4408
|
+
ZSTD_inBuffer const expect = cctx->expectedInBuffer;
|
4409
|
+
if (expect.src != input->src || expect.pos != input->pos || expect.size != input->size)
|
4410
|
+
RETURN_ERROR(srcBuffer_wrong, "ZSTD_c_stableInBuffer enabled but input differs!");
|
4411
|
+
if (endOp != ZSTD_e_end)
|
4412
|
+
RETURN_ERROR(srcBuffer_wrong, "ZSTD_c_stableInBuffer can only be used with ZSTD_e_end!");
|
4413
|
+
}
|
4414
|
+
if (cctx->appliedParams.outBufferMode == ZSTD_bm_stable) {
|
4415
|
+
size_t const outBufferSize = output->size - output->pos;
|
4416
|
+
if (cctx->expectedOutBufferSize != outBufferSize)
|
4417
|
+
RETURN_ERROR(dstBuffer_wrong, "ZSTD_c_stableOutBuffer enabled but output size differs!");
|
4418
|
+
}
|
4419
|
+
return 0;
|
4420
|
+
}
|
4421
|
+
|
4422
|
+
static size_t ZSTD_CCtx_init_compressStream2(ZSTD_CCtx* cctx,
|
4423
|
+
ZSTD_EndDirective endOp,
|
4424
|
+
size_t inSize) {
|
4425
|
+
ZSTD_CCtx_params params = cctx->requestedParams;
|
4426
|
+
ZSTD_prefixDict const prefixDict = cctx->prefixDict;
|
4427
|
+
FORWARD_IF_ERROR( ZSTD_initLocalDict(cctx) , ""); /* Init the local dict if present. */
|
4428
|
+
ZSTD_memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); /* single usage */
|
4429
|
+
assert(prefixDict.dict==NULL || cctx->cdict==NULL); /* only one can be set */
|
4430
|
+
if (cctx->cdict)
|
4431
|
+
params.compressionLevel = cctx->cdict->compressionLevel; /* let cdict take priority in terms of compression level */
|
4432
|
+
DEBUGLOG(4, "ZSTD_compressStream2 : transparent init stage");
|
4433
|
+
if (endOp == ZSTD_e_end) cctx->pledgedSrcSizePlusOne = inSize + 1; /* auto-fix pledgedSrcSize */
|
4434
|
+
{
|
4435
|
+
size_t const dictSize = prefixDict.dict
|
4436
|
+
? prefixDict.dictSize
|
4437
|
+
: (cctx->cdict ? cctx->cdict->dictContentSize : 0);
|
4438
|
+
ZSTD_cParamMode_e const mode = ZSTD_getCParamMode(cctx->cdict, ¶ms, cctx->pledgedSrcSizePlusOne - 1);
|
4439
|
+
params.cParams = ZSTD_getCParamsFromCCtxParams(
|
4440
|
+
¶ms, cctx->pledgedSrcSizePlusOne-1,
|
4441
|
+
dictSize, mode);
|
4442
|
+
}
|
4443
|
+
|
4444
|
+
if (ZSTD_CParams_shouldEnableLdm(¶ms.cParams)) {
|
4445
|
+
/* Enable LDM by default for optimal parser and window size >= 128MB */
|
4446
|
+
DEBUGLOG(4, "LDM enabled by default (window size >= 128MB, strategy >= btopt)");
|
4447
|
+
params.ldmParams.enableLdm = 1;
|
4448
|
+
}
|
4449
|
+
|
4450
|
+
#ifdef ZSTD_MULTITHREAD
|
4451
|
+
if ((cctx->pledgedSrcSizePlusOne-1) <= ZSTDMT_JOBSIZE_MIN) {
|
4452
|
+
params.nbWorkers = 0; /* do not invoke multi-threading when src size is too small */
|
4453
|
+
}
|
4454
|
+
if (params.nbWorkers > 0) {
|
4455
|
+
#if ZSTD_TRACE
|
4456
|
+
cctx->traceCtx = ZSTD_trace_compress_begin(cctx);
|
4457
|
+
#endif
|
4458
|
+
/* mt context creation */
|
4459
|
+
if (cctx->mtctx == NULL) {
|
4460
|
+
DEBUGLOG(4, "ZSTD_compressStream2: creating new mtctx for nbWorkers=%u",
|
4461
|
+
params.nbWorkers);
|
4462
|
+
cctx->mtctx = ZSTDMT_createCCtx_advanced((U32)params.nbWorkers, cctx->customMem, cctx->pool);
|
4463
|
+
RETURN_ERROR_IF(cctx->mtctx == NULL, memory_allocation, "NULL pointer!");
|
4464
|
+
}
|
4465
|
+
/* mt compression */
|
4466
|
+
DEBUGLOG(4, "call ZSTDMT_initCStream_internal as nbWorkers=%u", params.nbWorkers);
|
4467
|
+
FORWARD_IF_ERROR( ZSTDMT_initCStream_internal(
|
4468
|
+
cctx->mtctx,
|
4469
|
+
prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType,
|
4470
|
+
cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) , "");
|
4471
|
+
cctx->dictID = cctx->cdict ? cctx->cdict->dictID : 0;
|
4472
|
+
cctx->dictContentSize = cctx->cdict ? cctx->cdict->dictContentSize : prefixDict.dictSize;
|
4473
|
+
cctx->consumedSrcSize = 0;
|
4474
|
+
cctx->producedCSize = 0;
|
4475
|
+
cctx->streamStage = zcss_load;
|
4476
|
+
cctx->appliedParams = params;
|
4477
|
+
} else
|
4478
|
+
#endif
|
4479
|
+
{ U64 const pledgedSrcSize = cctx->pledgedSrcSizePlusOne - 1;
|
4480
|
+
assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
|
4481
|
+
FORWARD_IF_ERROR( ZSTD_compressBegin_internal(cctx,
|
4482
|
+
prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType, ZSTD_dtlm_fast,
|
4483
|
+
cctx->cdict,
|
4484
|
+
¶ms, pledgedSrcSize,
|
4485
|
+
ZSTDb_buffered) , "");
|
4486
|
+
assert(cctx->appliedParams.nbWorkers == 0);
|
4487
|
+
cctx->inToCompress = 0;
|
4488
|
+
cctx->inBuffPos = 0;
|
4489
|
+
if (cctx->appliedParams.inBufferMode == ZSTD_bm_buffered) {
|
4490
|
+
/* for small input: avoid automatic flush on reaching end of block, since
|
4491
|
+
* it would require to add a 3-bytes null block to end frame
|
4492
|
+
*/
|
4493
|
+
cctx->inBuffTarget = cctx->blockSize + (cctx->blockSize == pledgedSrcSize);
|
4494
|
+
} else {
|
4495
|
+
cctx->inBuffTarget = 0;
|
4496
|
+
}
|
4497
|
+
cctx->outBuffContentSize = cctx->outBuffFlushedSize = 0;
|
4498
|
+
cctx->streamStage = zcss_load;
|
4499
|
+
cctx->frameEnded = 0;
|
4500
|
+
}
|
4501
|
+
return 0;
|
4502
|
+
}
|
3962
4503
|
|
3963
4504
|
size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
|
3964
4505
|
ZSTD_outBuffer* output,
|
@@ -3967,82 +4508,69 @@ size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
|
|
3967
4508
|
{
|
3968
4509
|
DEBUGLOG(5, "ZSTD_compressStream2, endOp=%u ", (unsigned)endOp);
|
3969
4510
|
/* check conditions */
|
3970
|
-
RETURN_ERROR_IF(output->pos > output->size,
|
3971
|
-
RETURN_ERROR_IF(input->pos > input->size,
|
3972
|
-
|
4511
|
+
RETURN_ERROR_IF(output->pos > output->size, dstSize_tooSmall, "invalid output buffer");
|
4512
|
+
RETURN_ERROR_IF(input->pos > input->size, srcSize_wrong, "invalid input buffer");
|
4513
|
+
RETURN_ERROR_IF((U32)endOp > (U32)ZSTD_e_end, parameter_outOfBound, "invalid endDirective");
|
4514
|
+
assert(cctx != NULL);
|
3973
4515
|
|
3974
4516
|
/* transparent initialization stage */
|
3975
4517
|
if (cctx->streamStage == zcss_init) {
|
3976
|
-
|
3977
|
-
|
3978
|
-
|
3979
|
-
memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); /* single usage */
|
3980
|
-
assert(prefixDict.dict==NULL || cctx->cdict==NULL); /* only one can be set */
|
3981
|
-
DEBUGLOG(4, "ZSTD_compressStream2 : transparent init stage");
|
3982
|
-
if (endOp == ZSTD_e_end) cctx->pledgedSrcSizePlusOne = input->size + 1; /* auto-fix pledgedSrcSize */
|
3983
|
-
params.cParams = ZSTD_getCParamsFromCCtxParams(
|
3984
|
-
&cctx->requestedParams, cctx->pledgedSrcSizePlusOne-1, 0 /*dictSize*/);
|
3985
|
-
|
3986
|
-
|
3987
|
-
#ifdef ZSTD_MULTITHREAD
|
3988
|
-
if ((cctx->pledgedSrcSizePlusOne-1) <= ZSTDMT_JOBSIZE_MIN) {
|
3989
|
-
params.nbWorkers = 0; /* do not invoke multi-threading when src size is too small */
|
3990
|
-
}
|
3991
|
-
if (params.nbWorkers > 0) {
|
3992
|
-
/* mt context creation */
|
3993
|
-
if (cctx->mtctx == NULL) {
|
3994
|
-
DEBUGLOG(4, "ZSTD_compressStream2: creating new mtctx for nbWorkers=%u",
|
3995
|
-
params.nbWorkers);
|
3996
|
-
cctx->mtctx = ZSTDMT_createCCtx_advanced((U32)params.nbWorkers, cctx->customMem);
|
3997
|
-
RETURN_ERROR_IF(cctx->mtctx == NULL, memory_allocation, "NULL pointer!");
|
3998
|
-
}
|
3999
|
-
/* mt compression */
|
4000
|
-
DEBUGLOG(4, "call ZSTDMT_initCStream_internal as nbWorkers=%u", params.nbWorkers);
|
4001
|
-
FORWARD_IF_ERROR( ZSTDMT_initCStream_internal(
|
4002
|
-
cctx->mtctx,
|
4003
|
-
prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType,
|
4004
|
-
cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) , "");
|
4005
|
-
cctx->streamStage = zcss_load;
|
4006
|
-
cctx->appliedParams.nbWorkers = params.nbWorkers;
|
4007
|
-
} else
|
4008
|
-
#endif
|
4009
|
-
{ FORWARD_IF_ERROR( ZSTD_resetCStream_internal(cctx,
|
4010
|
-
prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType,
|
4011
|
-
cctx->cdict,
|
4012
|
-
params, cctx->pledgedSrcSizePlusOne-1) , "");
|
4013
|
-
assert(cctx->streamStage == zcss_load);
|
4014
|
-
assert(cctx->appliedParams.nbWorkers == 0);
|
4015
|
-
} }
|
4518
|
+
FORWARD_IF_ERROR(ZSTD_CCtx_init_compressStream2(cctx, endOp, input->size), "CompressStream2 initialization failed");
|
4519
|
+
ZSTD_setBufferExpectations(cctx, output, input); /* Set initial buffer expectations now that we've initialized */
|
4520
|
+
}
|
4016
4521
|
/* end of transparent initialization stage */
|
4017
4522
|
|
4523
|
+
FORWARD_IF_ERROR(ZSTD_checkBufferStability(cctx, output, input, endOp), "invalid buffers");
|
4018
4524
|
/* compression stage */
|
4019
4525
|
#ifdef ZSTD_MULTITHREAD
|
4020
4526
|
if (cctx->appliedParams.nbWorkers > 0) {
|
4021
|
-
int const forceMaxProgress = (endOp == ZSTD_e_flush || endOp == ZSTD_e_end);
|
4022
4527
|
size_t flushMin;
|
4023
|
-
assert(forceMaxProgress || endOp == ZSTD_e_continue /* Protection for a new flush type */);
|
4024
4528
|
if (cctx->cParamsChanged) {
|
4025
4529
|
ZSTDMT_updateCParams_whileCompressing(cctx->mtctx, &cctx->requestedParams);
|
4026
4530
|
cctx->cParamsChanged = 0;
|
4027
4531
|
}
|
4028
|
-
|
4532
|
+
for (;;) {
|
4533
|
+
size_t const ipos = input->pos;
|
4534
|
+
size_t const opos = output->pos;
|
4029
4535
|
flushMin = ZSTDMT_compressStream_generic(cctx->mtctx, output, input, endOp);
|
4536
|
+
cctx->consumedSrcSize += (U64)(input->pos - ipos);
|
4537
|
+
cctx->producedCSize += (U64)(output->pos - opos);
|
4030
4538
|
if ( ZSTD_isError(flushMin)
|
4031
4539
|
|| (endOp == ZSTD_e_end && flushMin == 0) ) { /* compression completed */
|
4540
|
+
if (flushMin == 0)
|
4541
|
+
ZSTD_CCtx_trace(cctx, 0);
|
4032
4542
|
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);
|
4033
4543
|
}
|
4034
4544
|
FORWARD_IF_ERROR(flushMin, "ZSTDMT_compressStream_generic failed");
|
4035
|
-
|
4545
|
+
|
4546
|
+
if (endOp == ZSTD_e_continue) {
|
4547
|
+
/* We only require some progress with ZSTD_e_continue, not maximal progress.
|
4548
|
+
* We're done if we've consumed or produced any bytes, or either buffer is
|
4549
|
+
* full.
|
4550
|
+
*/
|
4551
|
+
if (input->pos != ipos || output->pos != opos || input->pos == input->size || output->pos == output->size)
|
4552
|
+
break;
|
4553
|
+
} else {
|
4554
|
+
assert(endOp == ZSTD_e_flush || endOp == ZSTD_e_end);
|
4555
|
+
/* We require maximal progress. We're done when the flush is complete or the
|
4556
|
+
* output buffer is full.
|
4557
|
+
*/
|
4558
|
+
if (flushMin == 0 || output->pos == output->size)
|
4559
|
+
break;
|
4560
|
+
}
|
4561
|
+
}
|
4036
4562
|
DEBUGLOG(5, "completed ZSTD_compressStream2 delegating to ZSTDMT_compressStream_generic");
|
4037
4563
|
/* Either we don't require maximum forward progress, we've finished the
|
4038
4564
|
* flush, or we are out of output space.
|
4039
4565
|
*/
|
4040
|
-
assert(
|
4566
|
+
assert(endOp == ZSTD_e_continue || flushMin == 0 || output->pos == output->size);
|
4567
|
+
ZSTD_setBufferExpectations(cctx, output, input);
|
4041
4568
|
return flushMin;
|
4042
4569
|
}
|
4043
4570
|
#endif
|
4044
4571
|
FORWARD_IF_ERROR( ZSTD_compressStream_generic(cctx, output, input, endOp) , "");
|
4045
4572
|
DEBUGLOG(5, "completed ZSTD_compressStream2");
|
4573
|
+
ZSTD_setBufferExpectations(cctx, output, input);
|
4046
4574
|
return cctx->outBuffContentSize - cctx->outBuffFlushedSize; /* remaining to flush */
|
4047
4575
|
}
|
4048
4576
|
|
@@ -4065,14 +4593,22 @@ size_t ZSTD_compress2(ZSTD_CCtx* cctx,
|
|
4065
4593
|
void* dst, size_t dstCapacity,
|
4066
4594
|
const void* src, size_t srcSize)
|
4067
4595
|
{
|
4596
|
+
ZSTD_bufferMode_e const originalInBufferMode = cctx->requestedParams.inBufferMode;
|
4597
|
+
ZSTD_bufferMode_e const originalOutBufferMode = cctx->requestedParams.outBufferMode;
|
4068
4598
|
DEBUGLOG(4, "ZSTD_compress2 (srcSize=%u)", (unsigned)srcSize);
|
4069
4599
|
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);
|
4600
|
+
/* Enable stable input/output buffers. */
|
4601
|
+
cctx->requestedParams.inBufferMode = ZSTD_bm_stable;
|
4602
|
+
cctx->requestedParams.outBufferMode = ZSTD_bm_stable;
|
4070
4603
|
{ size_t oPos = 0;
|
4071
4604
|
size_t iPos = 0;
|
4072
4605
|
size_t const result = ZSTD_compressStream2_simpleArgs(cctx,
|
4073
4606
|
dst, dstCapacity, &oPos,
|
4074
4607
|
src, srcSize, &iPos,
|
4075
4608
|
ZSTD_e_end);
|
4609
|
+
/* Reset to the original values. */
|
4610
|
+
cctx->requestedParams.inBufferMode = originalInBufferMode;
|
4611
|
+
cctx->requestedParams.outBufferMode = originalOutBufferMode;
|
4076
4612
|
FORWARD_IF_ERROR(result, "ZSTD_compressStream2_simpleArgs failed");
|
4077
4613
|
if (result != 0) { /* compression not completed, due to lack of output space */
|
4078
4614
|
assert(oPos == dstCapacity);
|
@@ -4083,6 +4619,409 @@ size_t ZSTD_compress2(ZSTD_CCtx* cctx,
|
|
4083
4619
|
}
|
4084
4620
|
}
|
4085
4621
|
|
4622
|
+
typedef struct {
|
4623
|
+
U32 idx; /* Index in array of ZSTD_Sequence */
|
4624
|
+
U32 posInSequence; /* Position within sequence at idx */
|
4625
|
+
size_t posInSrc; /* Number of bytes given by sequences provided so far */
|
4626
|
+
} ZSTD_sequencePosition;
|
4627
|
+
|
4628
|
+
/* Returns a ZSTD error code if sequence is not valid */
|
4629
|
+
static size_t ZSTD_validateSequence(U32 offCode, U32 matchLength,
|
4630
|
+
size_t posInSrc, U32 windowLog, size_t dictSize, U32 minMatch) {
|
4631
|
+
size_t offsetBound;
|
4632
|
+
U32 windowSize = 1 << windowLog;
|
4633
|
+
/* posInSrc represents the amount of data the the decoder would decode up to this point.
|
4634
|
+
* As long as the amount of data decoded is less than or equal to window size, offsets may be
|
4635
|
+
* larger than the total length of output decoded in order to reference the dict, even larger than
|
4636
|
+
* window size. After output surpasses windowSize, we're limited to windowSize offsets again.
|
4637
|
+
*/
|
4638
|
+
offsetBound = posInSrc > windowSize ? (size_t)windowSize : posInSrc + (size_t)dictSize;
|
4639
|
+
RETURN_ERROR_IF(offCode > offsetBound + ZSTD_REP_MOVE, corruption_detected, "Offset too large!");
|
4640
|
+
RETURN_ERROR_IF(matchLength < minMatch, corruption_detected, "Matchlength too small");
|
4641
|
+
return 0;
|
4642
|
+
}
|
4643
|
+
|
4644
|
+
/* Returns an offset code, given a sequence's raw offset, the ongoing repcode array, and whether litLength == 0 */
|
4645
|
+
static U32 ZSTD_finalizeOffCode(U32 rawOffset, const U32 rep[ZSTD_REP_NUM], U32 ll0) {
|
4646
|
+
U32 offCode = rawOffset + ZSTD_REP_MOVE;
|
4647
|
+
U32 repCode = 0;
|
4648
|
+
|
4649
|
+
if (!ll0 && rawOffset == rep[0]) {
|
4650
|
+
repCode = 1;
|
4651
|
+
} else if (rawOffset == rep[1]) {
|
4652
|
+
repCode = 2 - ll0;
|
4653
|
+
} else if (rawOffset == rep[2]) {
|
4654
|
+
repCode = 3 - ll0;
|
4655
|
+
} else if (ll0 && rawOffset == rep[0] - 1) {
|
4656
|
+
repCode = 3;
|
4657
|
+
}
|
4658
|
+
if (repCode) {
|
4659
|
+
/* ZSTD_storeSeq expects a number in the range [0, 2] to represent a repcode */
|
4660
|
+
offCode = repCode - 1;
|
4661
|
+
}
|
4662
|
+
return offCode;
|
4663
|
+
}
|
4664
|
+
|
4665
|
+
/* Returns 0 on success, and a ZSTD_error otherwise. This function scans through an array of
|
4666
|
+
* ZSTD_Sequence, storing the sequences it finds, until it reaches a block delimiter.
|
4667
|
+
*/
|
4668
|
+
static size_t ZSTD_copySequencesToSeqStoreExplicitBlockDelim(ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos,
|
4669
|
+
const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,
|
4670
|
+
const void* src, size_t blockSize) {
|
4671
|
+
U32 idx = seqPos->idx;
|
4672
|
+
BYTE const* ip = (BYTE const*)(src);
|
4673
|
+
const BYTE* const iend = ip + blockSize;
|
4674
|
+
repcodes_t updatedRepcodes;
|
4675
|
+
U32 dictSize;
|
4676
|
+
U32 litLength;
|
4677
|
+
U32 matchLength;
|
4678
|
+
U32 ll0;
|
4679
|
+
U32 offCode;
|
4680
|
+
|
4681
|
+
if (cctx->cdict) {
|
4682
|
+
dictSize = (U32)cctx->cdict->dictContentSize;
|
4683
|
+
} else if (cctx->prefixDict.dict) {
|
4684
|
+
dictSize = (U32)cctx->prefixDict.dictSize;
|
4685
|
+
} else {
|
4686
|
+
dictSize = 0;
|
4687
|
+
}
|
4688
|
+
ZSTD_memcpy(updatedRepcodes.rep, cctx->blockState.prevCBlock->rep, sizeof(repcodes_t));
|
4689
|
+
for (; (inSeqs[idx].matchLength != 0 || inSeqs[idx].offset != 0) && idx < inSeqsSize; ++idx) {
|
4690
|
+
litLength = inSeqs[idx].litLength;
|
4691
|
+
matchLength = inSeqs[idx].matchLength;
|
4692
|
+
ll0 = litLength == 0;
|
4693
|
+
offCode = ZSTD_finalizeOffCode(inSeqs[idx].offset, updatedRepcodes.rep, ll0);
|
4694
|
+
updatedRepcodes = ZSTD_updateRep(updatedRepcodes.rep, offCode, ll0);
|
4695
|
+
|
4696
|
+
DEBUGLOG(6, "Storing sequence: (of: %u, ml: %u, ll: %u)", offCode, matchLength, litLength);
|
4697
|
+
if (cctx->appliedParams.validateSequences) {
|
4698
|
+
seqPos->posInSrc += litLength + matchLength;
|
4699
|
+
FORWARD_IF_ERROR(ZSTD_validateSequence(offCode, matchLength, seqPos->posInSrc,
|
4700
|
+
cctx->appliedParams.cParams.windowLog, dictSize,
|
4701
|
+
cctx->appliedParams.cParams.minMatch),
|
4702
|
+
"Sequence validation failed");
|
4703
|
+
}
|
4704
|
+
RETURN_ERROR_IF(idx - seqPos->idx > cctx->seqStore.maxNbSeq, memory_allocation,
|
4705
|
+
"Not enough memory allocated. Try adjusting ZSTD_c_minMatch.");
|
4706
|
+
ZSTD_storeSeq(&cctx->seqStore, litLength, ip, iend, offCode, matchLength - MINMATCH);
|
4707
|
+
ip += matchLength + litLength;
|
4708
|
+
}
|
4709
|
+
ZSTD_memcpy(cctx->blockState.nextCBlock->rep, updatedRepcodes.rep, sizeof(repcodes_t));
|
4710
|
+
|
4711
|
+
if (inSeqs[idx].litLength) {
|
4712
|
+
DEBUGLOG(6, "Storing last literals of size: %u", inSeqs[idx].litLength);
|
4713
|
+
ZSTD_storeLastLiterals(&cctx->seqStore, ip, inSeqs[idx].litLength);
|
4714
|
+
ip += inSeqs[idx].litLength;
|
4715
|
+
seqPos->posInSrc += inSeqs[idx].litLength;
|
4716
|
+
}
|
4717
|
+
RETURN_ERROR_IF(ip != iend, corruption_detected, "Blocksize doesn't agree with block delimiter!");
|
4718
|
+
seqPos->idx = idx+1;
|
4719
|
+
return 0;
|
4720
|
+
}
|
4721
|
+
|
4722
|
+
/* Returns the number of bytes to move the current read position back by. Only non-zero
|
4723
|
+
* if we ended up splitting a sequence. Otherwise, it may return a ZSTD error if something
|
4724
|
+
* went wrong.
|
4725
|
+
*
|
4726
|
+
* This function will attempt to scan through blockSize bytes represented by the sequences
|
4727
|
+
* in inSeqs, storing any (partial) sequences.
|
4728
|
+
*
|
4729
|
+
* Occasionally, we may want to change the actual number of bytes we consumed from inSeqs to
|
4730
|
+
* avoid splitting a match, or to avoid splitting a match such that it would produce a match
|
4731
|
+
* smaller than MINMATCH. In this case, we return the number of bytes that we didn't read from this block.
|
4732
|
+
*/
|
4733
|
+
static size_t ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos,
|
4734
|
+
const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,
|
4735
|
+
const void* src, size_t blockSize) {
|
4736
|
+
U32 idx = seqPos->idx;
|
4737
|
+
U32 startPosInSequence = seqPos->posInSequence;
|
4738
|
+
U32 endPosInSequence = seqPos->posInSequence + (U32)blockSize;
|
4739
|
+
size_t dictSize;
|
4740
|
+
BYTE const* ip = (BYTE const*)(src);
|
4741
|
+
BYTE const* iend = ip + blockSize; /* May be adjusted if we decide to process fewer than blockSize bytes */
|
4742
|
+
repcodes_t updatedRepcodes;
|
4743
|
+
U32 bytesAdjustment = 0;
|
4744
|
+
U32 finalMatchSplit = 0;
|
4745
|
+
U32 litLength;
|
4746
|
+
U32 matchLength;
|
4747
|
+
U32 rawOffset;
|
4748
|
+
U32 offCode;
|
4749
|
+
|
4750
|
+
if (cctx->cdict) {
|
4751
|
+
dictSize = cctx->cdict->dictContentSize;
|
4752
|
+
} else if (cctx->prefixDict.dict) {
|
4753
|
+
dictSize = cctx->prefixDict.dictSize;
|
4754
|
+
} else {
|
4755
|
+
dictSize = 0;
|
4756
|
+
}
|
4757
|
+
DEBUGLOG(5, "ZSTD_copySequencesToSeqStore: idx: %u PIS: %u blockSize: %zu", idx, startPosInSequence, blockSize);
|
4758
|
+
DEBUGLOG(5, "Start seq: idx: %u (of: %u ml: %u ll: %u)", idx, inSeqs[idx].offset, inSeqs[idx].matchLength, inSeqs[idx].litLength);
|
4759
|
+
ZSTD_memcpy(updatedRepcodes.rep, cctx->blockState.prevCBlock->rep, sizeof(repcodes_t));
|
4760
|
+
while (endPosInSequence && idx < inSeqsSize && !finalMatchSplit) {
|
4761
|
+
const ZSTD_Sequence currSeq = inSeqs[idx];
|
4762
|
+
litLength = currSeq.litLength;
|
4763
|
+
matchLength = currSeq.matchLength;
|
4764
|
+
rawOffset = currSeq.offset;
|
4765
|
+
|
4766
|
+
/* Modify the sequence depending on where endPosInSequence lies */
|
4767
|
+
if (endPosInSequence >= currSeq.litLength + currSeq.matchLength) {
|
4768
|
+
if (startPosInSequence >= litLength) {
|
4769
|
+
startPosInSequence -= litLength;
|
4770
|
+
litLength = 0;
|
4771
|
+
matchLength -= startPosInSequence;
|
4772
|
+
} else {
|
4773
|
+
litLength -= startPosInSequence;
|
4774
|
+
}
|
4775
|
+
/* Move to the next sequence */
|
4776
|
+
endPosInSequence -= currSeq.litLength + currSeq.matchLength;
|
4777
|
+
startPosInSequence = 0;
|
4778
|
+
idx++;
|
4779
|
+
} else {
|
4780
|
+
/* This is the final (partial) sequence we're adding from inSeqs, and endPosInSequence
|
4781
|
+
does not reach the end of the match. So, we have to split the sequence */
|
4782
|
+
DEBUGLOG(6, "Require a split: diff: %u, idx: %u PIS: %u",
|
4783
|
+
currSeq.litLength + currSeq.matchLength - endPosInSequence, idx, endPosInSequence);
|
4784
|
+
if (endPosInSequence > litLength) {
|
4785
|
+
U32 firstHalfMatchLength;
|
4786
|
+
litLength = startPosInSequence >= litLength ? 0 : litLength - startPosInSequence;
|
4787
|
+
firstHalfMatchLength = endPosInSequence - startPosInSequence - litLength;
|
4788
|
+
if (matchLength > blockSize && firstHalfMatchLength >= cctx->appliedParams.cParams.minMatch) {
|
4789
|
+
/* Only ever split the match if it is larger than the block size */
|
4790
|
+
U32 secondHalfMatchLength = currSeq.matchLength + currSeq.litLength - endPosInSequence;
|
4791
|
+
if (secondHalfMatchLength < cctx->appliedParams.cParams.minMatch) {
|
4792
|
+
/* Move the endPosInSequence backward so that it creates match of minMatch length */
|
4793
|
+
endPosInSequence -= cctx->appliedParams.cParams.minMatch - secondHalfMatchLength;
|
4794
|
+
bytesAdjustment = cctx->appliedParams.cParams.minMatch - secondHalfMatchLength;
|
4795
|
+
firstHalfMatchLength -= bytesAdjustment;
|
4796
|
+
}
|
4797
|
+
matchLength = firstHalfMatchLength;
|
4798
|
+
/* Flag that we split the last match - after storing the sequence, exit the loop,
|
4799
|
+
but keep the value of endPosInSequence */
|
4800
|
+
finalMatchSplit = 1;
|
4801
|
+
} else {
|
4802
|
+
/* Move the position in sequence backwards so that we don't split match, and break to store
|
4803
|
+
* the last literals. We use the original currSeq.litLength as a marker for where endPosInSequence
|
4804
|
+
* should go. We prefer to do this whenever it is not necessary to split the match, or if doing so
|
4805
|
+
* would cause the first half of the match to be too small
|
4806
|
+
*/
|
4807
|
+
bytesAdjustment = endPosInSequence - currSeq.litLength;
|
4808
|
+
endPosInSequence = currSeq.litLength;
|
4809
|
+
break;
|
4810
|
+
}
|
4811
|
+
} else {
|
4812
|
+
/* This sequence ends inside the literals, break to store the last literals */
|
4813
|
+
break;
|
4814
|
+
}
|
4815
|
+
}
|
4816
|
+
/* Check if this offset can be represented with a repcode */
|
4817
|
+
{ U32 ll0 = (litLength == 0);
|
4818
|
+
offCode = ZSTD_finalizeOffCode(rawOffset, updatedRepcodes.rep, ll0);
|
4819
|
+
updatedRepcodes = ZSTD_updateRep(updatedRepcodes.rep, offCode, ll0);
|
4820
|
+
}
|
4821
|
+
|
4822
|
+
if (cctx->appliedParams.validateSequences) {
|
4823
|
+
seqPos->posInSrc += litLength + matchLength;
|
4824
|
+
FORWARD_IF_ERROR(ZSTD_validateSequence(offCode, matchLength, seqPos->posInSrc,
|
4825
|
+
cctx->appliedParams.cParams.windowLog, dictSize,
|
4826
|
+
cctx->appliedParams.cParams.minMatch),
|
4827
|
+
"Sequence validation failed");
|
4828
|
+
}
|
4829
|
+
DEBUGLOG(6, "Storing sequence: (of: %u, ml: %u, ll: %u)", offCode, matchLength, litLength);
|
4830
|
+
RETURN_ERROR_IF(idx - seqPos->idx > cctx->seqStore.maxNbSeq, memory_allocation,
|
4831
|
+
"Not enough memory allocated. Try adjusting ZSTD_c_minMatch.");
|
4832
|
+
ZSTD_storeSeq(&cctx->seqStore, litLength, ip, iend, offCode, matchLength - MINMATCH);
|
4833
|
+
ip += matchLength + litLength;
|
4834
|
+
}
|
4835
|
+
DEBUGLOG(5, "Ending seq: idx: %u (of: %u ml: %u ll: %u)", idx, inSeqs[idx].offset, inSeqs[idx].matchLength, inSeqs[idx].litLength);
|
4836
|
+
assert(idx == inSeqsSize || endPosInSequence <= inSeqs[idx].litLength + inSeqs[idx].matchLength);
|
4837
|
+
seqPos->idx = idx;
|
4838
|
+
seqPos->posInSequence = endPosInSequence;
|
4839
|
+
ZSTD_memcpy(cctx->blockState.nextCBlock->rep, updatedRepcodes.rep, sizeof(repcodes_t));
|
4840
|
+
|
4841
|
+
iend -= bytesAdjustment;
|
4842
|
+
if (ip != iend) {
|
4843
|
+
/* Store any last literals */
|
4844
|
+
U32 lastLLSize = (U32)(iend - ip);
|
4845
|
+
assert(ip <= iend);
|
4846
|
+
DEBUGLOG(6, "Storing last literals of size: %u", lastLLSize);
|
4847
|
+
ZSTD_storeLastLiterals(&cctx->seqStore, ip, lastLLSize);
|
4848
|
+
seqPos->posInSrc += lastLLSize;
|
4849
|
+
}
|
4850
|
+
|
4851
|
+
return bytesAdjustment;
|
4852
|
+
}
|
4853
|
+
|
4854
|
+
typedef size_t (*ZSTD_sequenceCopier) (ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos,
|
4855
|
+
const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,
|
4856
|
+
const void* src, size_t blockSize);
|
4857
|
+
static ZSTD_sequenceCopier ZSTD_selectSequenceCopier(ZSTD_sequenceFormat_e mode) {
|
4858
|
+
ZSTD_sequenceCopier sequenceCopier = NULL;
|
4859
|
+
assert(ZSTD_cParam_withinBounds(ZSTD_c_blockDelimiters, mode));
|
4860
|
+
if (mode == ZSTD_sf_explicitBlockDelimiters) {
|
4861
|
+
return ZSTD_copySequencesToSeqStoreExplicitBlockDelim;
|
4862
|
+
} else if (mode == ZSTD_sf_noBlockDelimiters) {
|
4863
|
+
return ZSTD_copySequencesToSeqStoreNoBlockDelim;
|
4864
|
+
}
|
4865
|
+
assert(sequenceCopier != NULL);
|
4866
|
+
return sequenceCopier;
|
4867
|
+
}
|
4868
|
+
|
4869
|
+
/* Compress, block-by-block, all of the sequences given.
|
4870
|
+
*
|
4871
|
+
* Returns the cumulative size of all compressed blocks (including their headers), otherwise a ZSTD error.
|
4872
|
+
*/
|
4873
|
+
static size_t ZSTD_compressSequences_internal(ZSTD_CCtx* cctx,
|
4874
|
+
void* dst, size_t dstCapacity,
|
4875
|
+
const ZSTD_Sequence* inSeqs, size_t inSeqsSize,
|
4876
|
+
const void* src, size_t srcSize) {
|
4877
|
+
size_t cSize = 0;
|
4878
|
+
U32 lastBlock;
|
4879
|
+
size_t blockSize;
|
4880
|
+
size_t compressedSeqsSize;
|
4881
|
+
size_t remaining = srcSize;
|
4882
|
+
ZSTD_sequencePosition seqPos = {0, 0, 0};
|
4883
|
+
|
4884
|
+
BYTE const* ip = (BYTE const*)src;
|
4885
|
+
BYTE* op = (BYTE*)dst;
|
4886
|
+
ZSTD_sequenceCopier sequenceCopier = ZSTD_selectSequenceCopier(cctx->appliedParams.blockDelimiters);
|
4887
|
+
|
4888
|
+
DEBUGLOG(4, "ZSTD_compressSequences_internal srcSize: %zu, inSeqsSize: %zu", srcSize, inSeqsSize);
|
4889
|
+
/* Special case: empty frame */
|
4890
|
+
if (remaining == 0) {
|
4891
|
+
U32 const cBlockHeader24 = 1 /* last block */ + (((U32)bt_raw)<<1);
|
4892
|
+
RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, "No room for empty frame block header");
|
4893
|
+
MEM_writeLE32(op, cBlockHeader24);
|
4894
|
+
op += ZSTD_blockHeaderSize;
|
4895
|
+
dstCapacity -= ZSTD_blockHeaderSize;
|
4896
|
+
cSize += ZSTD_blockHeaderSize;
|
4897
|
+
}
|
4898
|
+
|
4899
|
+
while (remaining) {
|
4900
|
+
size_t cBlockSize;
|
4901
|
+
size_t additionalByteAdjustment;
|
4902
|
+
lastBlock = remaining <= cctx->blockSize;
|
4903
|
+
blockSize = lastBlock ? (U32)remaining : (U32)cctx->blockSize;
|
4904
|
+
ZSTD_resetSeqStore(&cctx->seqStore);
|
4905
|
+
DEBUGLOG(4, "Working on new block. Blocksize: %zu", blockSize);
|
4906
|
+
|
4907
|
+
additionalByteAdjustment = sequenceCopier(cctx, &seqPos, inSeqs, inSeqsSize, ip, blockSize);
|
4908
|
+
FORWARD_IF_ERROR(additionalByteAdjustment, "Bad sequence copy");
|
4909
|
+
blockSize -= additionalByteAdjustment;
|
4910
|
+
|
4911
|
+
/* If blocks are too small, emit as a nocompress block */
|
4912
|
+
if (blockSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1) {
|
4913
|
+
cBlockSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock);
|
4914
|
+
FORWARD_IF_ERROR(cBlockSize, "Nocompress block failed");
|
4915
|
+
DEBUGLOG(4, "Block too small, writing out nocompress block: cSize: %zu", cBlockSize);
|
4916
|
+
cSize += cBlockSize;
|
4917
|
+
ip += blockSize;
|
4918
|
+
op += cBlockSize;
|
4919
|
+
remaining -= blockSize;
|
4920
|
+
dstCapacity -= cBlockSize;
|
4921
|
+
continue;
|
4922
|
+
}
|
4923
|
+
|
4924
|
+
compressedSeqsSize = ZSTD_entropyCompressSequences(&cctx->seqStore,
|
4925
|
+
&cctx->blockState.prevCBlock->entropy, &cctx->blockState.nextCBlock->entropy,
|
4926
|
+
&cctx->appliedParams,
|
4927
|
+
op + ZSTD_blockHeaderSize /* Leave space for block header */, dstCapacity - ZSTD_blockHeaderSize,
|
4928
|
+
blockSize,
|
4929
|
+
cctx->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */,
|
4930
|
+
cctx->bmi2);
|
4931
|
+
FORWARD_IF_ERROR(compressedSeqsSize, "Compressing sequences of block failed");
|
4932
|
+
DEBUGLOG(4, "Compressed sequences size: %zu", compressedSeqsSize);
|
4933
|
+
|
4934
|
+
if (!cctx->isFirstBlock &&
|
4935
|
+
ZSTD_maybeRLE(&cctx->seqStore) &&
|
4936
|
+
ZSTD_isRLE((BYTE const*)src, srcSize)) {
|
4937
|
+
/* We don't want to emit our first block as a RLE even if it qualifies because
|
4938
|
+
* doing so will cause the decoder (cli only) to throw a "should consume all input error."
|
4939
|
+
* This is only an issue for zstd <= v1.4.3
|
4940
|
+
*/
|
4941
|
+
compressedSeqsSize = 1;
|
4942
|
+
}
|
4943
|
+
|
4944
|
+
if (compressedSeqsSize == 0) {
|
4945
|
+
/* ZSTD_noCompressBlock writes the block header as well */
|
4946
|
+
cBlockSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock);
|
4947
|
+
FORWARD_IF_ERROR(cBlockSize, "Nocompress block failed");
|
4948
|
+
DEBUGLOG(4, "Writing out nocompress block, size: %zu", cBlockSize);
|
4949
|
+
} else if (compressedSeqsSize == 1) {
|
4950
|
+
cBlockSize = ZSTD_rleCompressBlock(op, dstCapacity, *ip, blockSize, lastBlock);
|
4951
|
+
FORWARD_IF_ERROR(cBlockSize, "RLE compress block failed");
|
4952
|
+
DEBUGLOG(4, "Writing out RLE block, size: %zu", cBlockSize);
|
4953
|
+
} else {
|
4954
|
+
U32 cBlockHeader;
|
4955
|
+
/* Error checking and repcodes update */
|
4956
|
+
ZSTD_confirmRepcodesAndEntropyTables(cctx);
|
4957
|
+
if (cctx->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid)
|
4958
|
+
cctx->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check;
|
4959
|
+
|
4960
|
+
/* Write block header into beginning of block*/
|
4961
|
+
cBlockHeader = lastBlock + (((U32)bt_compressed)<<1) + (U32)(compressedSeqsSize << 3);
|
4962
|
+
MEM_writeLE24(op, cBlockHeader);
|
4963
|
+
cBlockSize = ZSTD_blockHeaderSize + compressedSeqsSize;
|
4964
|
+
DEBUGLOG(4, "Writing out compressed block, size: %zu", cBlockSize);
|
4965
|
+
}
|
4966
|
+
|
4967
|
+
cSize += cBlockSize;
|
4968
|
+
DEBUGLOG(4, "cSize running total: %zu", cSize);
|
4969
|
+
|
4970
|
+
if (lastBlock) {
|
4971
|
+
break;
|
4972
|
+
} else {
|
4973
|
+
ip += blockSize;
|
4974
|
+
op += cBlockSize;
|
4975
|
+
remaining -= blockSize;
|
4976
|
+
dstCapacity -= cBlockSize;
|
4977
|
+
cctx->isFirstBlock = 0;
|
4978
|
+
}
|
4979
|
+
}
|
4980
|
+
|
4981
|
+
return cSize;
|
4982
|
+
}
|
4983
|
+
|
4984
|
+
size_t ZSTD_compressSequences(ZSTD_CCtx* const cctx, void* dst, size_t dstCapacity,
|
4985
|
+
const ZSTD_Sequence* inSeqs, size_t inSeqsSize,
|
4986
|
+
const void* src, size_t srcSize) {
|
4987
|
+
BYTE* op = (BYTE*)dst;
|
4988
|
+
size_t cSize = 0;
|
4989
|
+
size_t compressedBlocksSize = 0;
|
4990
|
+
size_t frameHeaderSize = 0;
|
4991
|
+
|
4992
|
+
/* Transparent initialization stage, same as compressStream2() */
|
4993
|
+
DEBUGLOG(3, "ZSTD_compressSequences()");
|
4994
|
+
assert(cctx != NULL);
|
4995
|
+
FORWARD_IF_ERROR(ZSTD_CCtx_init_compressStream2(cctx, ZSTD_e_end, srcSize), "CCtx initialization failed");
|
4996
|
+
/* Begin writing output, starting with frame header */
|
4997
|
+
frameHeaderSize = ZSTD_writeFrameHeader(op, dstCapacity, &cctx->appliedParams, srcSize, cctx->dictID);
|
4998
|
+
op += frameHeaderSize;
|
4999
|
+
dstCapacity -= frameHeaderSize;
|
5000
|
+
cSize += frameHeaderSize;
|
5001
|
+
if (cctx->appliedParams.fParams.checksumFlag && srcSize) {
|
5002
|
+
XXH64_update(&cctx->xxhState, src, srcSize);
|
5003
|
+
}
|
5004
|
+
/* cSize includes block header size and compressed sequences size */
|
5005
|
+
compressedBlocksSize = ZSTD_compressSequences_internal(cctx,
|
5006
|
+
op, dstCapacity,
|
5007
|
+
inSeqs, inSeqsSize,
|
5008
|
+
src, srcSize);
|
5009
|
+
FORWARD_IF_ERROR(compressedBlocksSize, "Compressing blocks failed!");
|
5010
|
+
cSize += compressedBlocksSize;
|
5011
|
+
dstCapacity -= compressedBlocksSize;
|
5012
|
+
|
5013
|
+
if (cctx->appliedParams.fParams.checksumFlag) {
|
5014
|
+
U32 const checksum = (U32) XXH64_digest(&cctx->xxhState);
|
5015
|
+
RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, "no room for checksum");
|
5016
|
+
DEBUGLOG(4, "Write checksum : %08X", (unsigned)checksum);
|
5017
|
+
MEM_writeLE32((char*)dst + cSize, checksum);
|
5018
|
+
cSize += 4;
|
5019
|
+
}
|
5020
|
+
|
5021
|
+
DEBUGLOG(3, "Final compressed size: %zu", cSize);
|
5022
|
+
return cSize;
|
5023
|
+
}
|
5024
|
+
|
4086
5025
|
/*====== Finalize ======*/
|
4087
5026
|
|
4088
5027
|
/*! ZSTD_flushStream() :
|
@@ -4223,25 +5162,103 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
|
|
4223
5162
|
},
|
4224
5163
|
};
|
4225
5164
|
|
5165
|
+
static ZSTD_compressionParameters ZSTD_dedicatedDictSearch_getCParams(int const compressionLevel, size_t const dictSize)
|
5166
|
+
{
|
5167
|
+
ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, 0, dictSize, ZSTD_cpm_createCDict);
|
5168
|
+
switch (cParams.strategy) {
|
5169
|
+
case ZSTD_fast:
|
5170
|
+
case ZSTD_dfast:
|
5171
|
+
break;
|
5172
|
+
case ZSTD_greedy:
|
5173
|
+
case ZSTD_lazy:
|
5174
|
+
case ZSTD_lazy2:
|
5175
|
+
cParams.hashLog += ZSTD_LAZY_DDSS_BUCKET_LOG;
|
5176
|
+
break;
|
5177
|
+
case ZSTD_btlazy2:
|
5178
|
+
case ZSTD_btopt:
|
5179
|
+
case ZSTD_btultra:
|
5180
|
+
case ZSTD_btultra2:
|
5181
|
+
break;
|
5182
|
+
}
|
5183
|
+
return cParams;
|
5184
|
+
}
|
5185
|
+
|
5186
|
+
static int ZSTD_dedicatedDictSearch_isSupported(
|
5187
|
+
ZSTD_compressionParameters const* cParams)
|
5188
|
+
{
|
5189
|
+
return (cParams->strategy >= ZSTD_greedy) && (cParams->strategy <= ZSTD_lazy2);
|
5190
|
+
}
|
5191
|
+
|
5192
|
+
/**
|
5193
|
+
* Reverses the adjustment applied to cparams when enabling dedicated dict
|
5194
|
+
* search. This is used to recover the params set to be used in the working
|
5195
|
+
* context. (Otherwise, those tables would also grow.)
|
5196
|
+
*/
|
5197
|
+
static void ZSTD_dedicatedDictSearch_revertCParams(
|
5198
|
+
ZSTD_compressionParameters* cParams) {
|
5199
|
+
switch (cParams->strategy) {
|
5200
|
+
case ZSTD_fast:
|
5201
|
+
case ZSTD_dfast:
|
5202
|
+
break;
|
5203
|
+
case ZSTD_greedy:
|
5204
|
+
case ZSTD_lazy:
|
5205
|
+
case ZSTD_lazy2:
|
5206
|
+
cParams->hashLog -= ZSTD_LAZY_DDSS_BUCKET_LOG;
|
5207
|
+
break;
|
5208
|
+
case ZSTD_btlazy2:
|
5209
|
+
case ZSTD_btopt:
|
5210
|
+
case ZSTD_btultra:
|
5211
|
+
case ZSTD_btultra2:
|
5212
|
+
break;
|
5213
|
+
}
|
5214
|
+
}
|
5215
|
+
|
5216
|
+
static U64 ZSTD_getCParamRowSize(U64 srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode)
|
5217
|
+
{
|
5218
|
+
switch (mode) {
|
5219
|
+
case ZSTD_cpm_unknown:
|
5220
|
+
case ZSTD_cpm_noAttachDict:
|
5221
|
+
case ZSTD_cpm_createCDict:
|
5222
|
+
break;
|
5223
|
+
case ZSTD_cpm_attachDict:
|
5224
|
+
dictSize = 0;
|
5225
|
+
break;
|
5226
|
+
default:
|
5227
|
+
assert(0);
|
5228
|
+
break;
|
5229
|
+
}
|
5230
|
+
{ int const unknown = srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN;
|
5231
|
+
size_t const addedSize = unknown && dictSize > 0 ? 500 : 0;
|
5232
|
+
return unknown && dictSize == 0 ? ZSTD_CONTENTSIZE_UNKNOWN : srcSizeHint+dictSize+addedSize;
|
5233
|
+
}
|
5234
|
+
}
|
5235
|
+
|
4226
5236
|
/*! ZSTD_getCParams_internal() :
|
4227
5237
|
* @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize.
|
4228
5238
|
* Note: srcSizeHint 0 means 0, use ZSTD_CONTENTSIZE_UNKNOWN for unknown.
|
4229
|
-
* Use dictSize == 0 for unknown or unused.
|
4230
|
-
|
5239
|
+
* Use dictSize == 0 for unknown or unused.
|
5240
|
+
* Note: `mode` controls how we treat the `dictSize`. See docs for `ZSTD_cParamMode_e`. */
|
5241
|
+
static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode)
|
4231
5242
|
{
|
4232
|
-
|
4233
|
-
size_t const addedSize = unknown && dictSize > 0 ? 500 : 0;
|
4234
|
-
U64 const rSize = unknown && dictSize == 0 ? ZSTD_CONTENTSIZE_UNKNOWN : srcSizeHint+dictSize+addedSize;
|
5243
|
+
U64 const rSize = ZSTD_getCParamRowSize(srcSizeHint, dictSize, mode);
|
4235
5244
|
U32 const tableID = (rSize <= 256 KB) + (rSize <= 128 KB) + (rSize <= 16 KB);
|
4236
|
-
int row
|
5245
|
+
int row;
|
4237
5246
|
DEBUGLOG(5, "ZSTD_getCParams_internal (cLevel=%i)", compressionLevel);
|
5247
|
+
|
5248
|
+
/* row */
|
4238
5249
|
if (compressionLevel == 0) row = ZSTD_CLEVEL_DEFAULT; /* 0 == default */
|
4239
|
-
if (compressionLevel < 0) row = 0; /* entry 0 is baseline for fast mode */
|
4240
|
-
if (compressionLevel > ZSTD_MAX_CLEVEL) row = ZSTD_MAX_CLEVEL;
|
5250
|
+
else if (compressionLevel < 0) row = 0; /* entry 0 is baseline for fast mode */
|
5251
|
+
else if (compressionLevel > ZSTD_MAX_CLEVEL) row = ZSTD_MAX_CLEVEL;
|
5252
|
+
else row = compressionLevel;
|
5253
|
+
|
4241
5254
|
{ ZSTD_compressionParameters cp = ZSTD_defaultCParameters[tableID][row];
|
4242
|
-
|
5255
|
+
/* acceleration factor */
|
5256
|
+
if (compressionLevel < 0) {
|
5257
|
+
int const clampedCompressionLevel = MAX(ZSTD_minCLevel(), compressionLevel);
|
5258
|
+
cp.targetLength = (unsigned)(-clampedCompressionLevel);
|
5259
|
+
}
|
4243
5260
|
/* refine parameters based on srcSize & dictSize */
|
4244
|
-
return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize);
|
5261
|
+
return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize, mode);
|
4245
5262
|
}
|
4246
5263
|
}
|
4247
5264
|
|
@@ -4251,18 +5268,18 @@ static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel,
|
|
4251
5268
|
ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize)
|
4252
5269
|
{
|
4253
5270
|
if (srcSizeHint == 0) srcSizeHint = ZSTD_CONTENTSIZE_UNKNOWN;
|
4254
|
-
return ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize);
|
5271
|
+
return ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize, ZSTD_cpm_unknown);
|
4255
5272
|
}
|
4256
5273
|
|
4257
5274
|
/*! ZSTD_getParams() :
|
4258
5275
|
* same idea as ZSTD_getCParams()
|
4259
5276
|
* @return a `ZSTD_parameters` structure (instead of `ZSTD_compressionParameters`).
|
4260
5277
|
* Fields of `ZSTD_frameParameters` are set to default values */
|
4261
|
-
static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) {
|
5278
|
+
static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode) {
|
4262
5279
|
ZSTD_parameters params;
|
4263
|
-
ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize);
|
5280
|
+
ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize, mode);
|
4264
5281
|
DEBUGLOG(5, "ZSTD_getParams (cLevel=%i)", compressionLevel);
|
4265
|
-
|
5282
|
+
ZSTD_memset(¶ms, 0, sizeof(params));
|
4266
5283
|
params.cParams = cParams;
|
4267
5284
|
params.fParams.contentSizeFlag = 1;
|
4268
5285
|
return params;
|
@@ -4274,5 +5291,5 @@ static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned lo
|
|
4274
5291
|
* Fields of `ZSTD_frameParameters` are set to default values */
|
4275
5292
|
ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) {
|
4276
5293
|
if (srcSizeHint == 0) srcSizeHint = ZSTD_CONTENTSIZE_UNKNOWN;
|
4277
|
-
return ZSTD_getParams_internal(compressionLevel, srcSizeHint, dictSize);
|
5294
|
+
return ZSTD_getParams_internal(compressionLevel, srcSizeHint, dictSize, ZSTD_cpm_unknown);
|
4278
5295
|
}
|