zstd-ruby 1.4.5.0 → 1.4.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.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
|
}
|