zstdlib 0.2.0 → 0.7.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/CHANGES.md +30 -1
- data/README.md +2 -2
- data/Rakefile +1 -1
- data/ext/zstdlib/extconf.rb +3 -3
- data/ext/zstdlib/ruby/zlib-2.7/zstdlib.c +4895 -0
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/bitstream.h +38 -39
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/compiler.h +40 -5
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/cpu.h +1 -1
- data/ext/zstdlib/zstd-1.4.5/lib/common/debug.c +24 -0
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/debug.h +11 -31
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/entropy_common.c +13 -33
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/error_private.c +2 -1
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/error_private.h +6 -2
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/fse.h +12 -32
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/fse_decompress.c +12 -35
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/huf.h +15 -33
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/mem.h +75 -2
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/pool.c +8 -4
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/pool.h +2 -2
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/threading.c +50 -4
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/threading.h +36 -4
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/xxhash.c +23 -35
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/xxhash.h +11 -31
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/zstd_common.c +1 -1
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/zstd_errors.h +2 -1
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/common/zstd_internal.h +154 -26
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/fse_compress.c +17 -40
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/hist.c +15 -35
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/hist.h +12 -32
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/huf_compress.c +92 -92
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstd_compress.c +1191 -1330
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstd_compress_internal.h +317 -55
- data/ext/zstdlib/zstd-1.4.5/lib/compress/zstd_compress_literals.c +158 -0
- data/ext/zstdlib/zstd-1.4.5/lib/compress/zstd_compress_literals.h +29 -0
- data/ext/zstdlib/zstd-1.4.5/lib/compress/zstd_compress_sequences.c +419 -0
- data/ext/zstdlib/zstd-1.4.5/lib/compress/zstd_compress_sequences.h +54 -0
- data/ext/zstdlib/zstd-1.4.5/lib/compress/zstd_compress_superblock.c +845 -0
- data/ext/zstdlib/zstd-1.4.5/lib/compress/zstd_compress_superblock.h +32 -0
- data/ext/zstdlib/zstd-1.4.5/lib/compress/zstd_cwksp.h +525 -0
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstd_double_fast.c +65 -43
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstd_double_fast.h +2 -2
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstd_fast.c +92 -66
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstd_fast.h +2 -2
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstd_lazy.c +74 -42
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstd_lazy.h +1 -1
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstd_ldm.c +32 -10
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstd_ldm.h +7 -2
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstd_opt.c +81 -114
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstd_opt.h +1 -1
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstdmt_compress.c +95 -51
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/compress/zstdmt_compress.h +3 -2
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/decompress/huf_decompress.c +76 -60
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/decompress/zstd_ddict.c +12 -8
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/decompress/zstd_ddict.h +2 -2
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/decompress/zstd_decompress.c +292 -172
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/decompress/zstd_decompress_block.c +459 -338
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/decompress/zstd_decompress_block.h +3 -3
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/decompress/zstd_decompress_internal.h +18 -4
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/lib/zstd.h +265 -88
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/zlibWrapper/gzclose.c +1 -1
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/zlibWrapper/gzcompatibility.h +1 -1
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/zlibWrapper/gzguts.h +0 -0
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/zlibWrapper/gzlib.c +9 -9
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/zlibWrapper/gzread.c +16 -8
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/zlibWrapper/gzwrite.c +8 -8
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/zlibWrapper/zstd_zlibwrapper.c +16 -12
- data/ext/zstdlib/{zstd-1.4.0 → zstd-1.4.5}/zlibWrapper/zstd_zlibwrapper.h +1 -1
- metadata +69 -62
- data/ext/zstdlib/zstd-1.4.0/lib/common/debug.c +0 -44
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright (c) 2016-
|
|
2
|
+
* Copyright (c) 2016-2020, 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
|
|
@@ -13,24 +13,34 @@
|
|
|
13
13
|
***************************************/
|
|
14
14
|
#include <limits.h> /* INT_MAX */
|
|
15
15
|
#include <string.h> /* memset */
|
|
16
|
-
#include "cpu.h"
|
|
17
|
-
#include "mem.h"
|
|
16
|
+
#include "../common/cpu.h"
|
|
17
|
+
#include "../common/mem.h"
|
|
18
18
|
#include "hist.h" /* HIST_countFast_wksp */
|
|
19
19
|
#define FSE_STATIC_LINKING_ONLY /* FSE_encodeSymbol */
|
|
20
|
-
#include "fse.h"
|
|
20
|
+
#include "../common/fse.h"
|
|
21
21
|
#define HUF_STATIC_LINKING_ONLY
|
|
22
|
-
#include "huf.h"
|
|
22
|
+
#include "../common/huf.h"
|
|
23
23
|
#include "zstd_compress_internal.h"
|
|
24
|
+
#include "zstd_compress_sequences.h"
|
|
25
|
+
#include "zstd_compress_literals.h"
|
|
24
26
|
#include "zstd_fast.h"
|
|
25
27
|
#include "zstd_double_fast.h"
|
|
26
28
|
#include "zstd_lazy.h"
|
|
27
29
|
#include "zstd_opt.h"
|
|
28
30
|
#include "zstd_ldm.h"
|
|
31
|
+
#include "zstd_compress_superblock.h"
|
|
29
32
|
|
|
30
33
|
|
|
31
34
|
/*-*************************************
|
|
32
35
|
* Helper functions
|
|
33
36
|
***************************************/
|
|
37
|
+
/* ZSTD_compressBound()
|
|
38
|
+
* Note that the result from this function is only compatible with the "normal"
|
|
39
|
+
* full-block strategy.
|
|
40
|
+
* When there are a lot of small blocks due to frequent flush in streaming mode
|
|
41
|
+
* the overhead of headers can make the compressed data to be larger than the
|
|
42
|
+
* return value of ZSTD_compressBound().
|
|
43
|
+
*/
|
|
34
44
|
size_t ZSTD_compressBound(size_t srcSize) {
|
|
35
45
|
return ZSTD_COMPRESSBOUND(srcSize);
|
|
36
46
|
}
|
|
@@ -40,15 +50,15 @@ size_t ZSTD_compressBound(size_t srcSize) {
|
|
|
40
50
|
* Context memory management
|
|
41
51
|
***************************************/
|
|
42
52
|
struct ZSTD_CDict_s {
|
|
43
|
-
void* dictBuffer;
|
|
44
53
|
const void* dictContent;
|
|
45
54
|
size_t dictContentSize;
|
|
46
|
-
|
|
47
|
-
|
|
55
|
+
U32* entropyWorkspace; /* entropy workspace of HUF_WORKSPACE_SIZE bytes */
|
|
56
|
+
ZSTD_cwksp workspace;
|
|
48
57
|
ZSTD_matchState_t matchState;
|
|
49
58
|
ZSTD_compressedBlockState_t cBlockState;
|
|
50
59
|
ZSTD_customMem customMem;
|
|
51
60
|
U32 dictID;
|
|
61
|
+
int compressionLevel; /* 0 indicates that advanced API was used to select CDict params */
|
|
52
62
|
}; /* typedef'd to ZSTD_CDict within "zstd.h" */
|
|
53
63
|
|
|
54
64
|
ZSTD_CCtx* ZSTD_createCCtx(void)
|
|
@@ -80,25 +90,26 @@ ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem)
|
|
|
80
90
|
}
|
|
81
91
|
}
|
|
82
92
|
|
|
83
|
-
ZSTD_CCtx* ZSTD_initStaticCCtx(void
|
|
93
|
+
ZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize)
|
|
84
94
|
{
|
|
85
|
-
|
|
95
|
+
ZSTD_cwksp ws;
|
|
96
|
+
ZSTD_CCtx* cctx;
|
|
86
97
|
if (workspaceSize <= sizeof(ZSTD_CCtx)) return NULL; /* minimum size */
|
|
87
98
|
if ((size_t)workspace & 7) return NULL; /* must be 8-aligned */
|
|
88
|
-
|
|
99
|
+
ZSTD_cwksp_init(&ws, workspace, workspaceSize);
|
|
100
|
+
|
|
101
|
+
cctx = (ZSTD_CCtx*)ZSTD_cwksp_reserve_object(&ws, sizeof(ZSTD_CCtx));
|
|
102
|
+
if (cctx == NULL) return NULL;
|
|
103
|
+
|
|
104
|
+
memset(cctx, 0, sizeof(ZSTD_CCtx));
|
|
105
|
+
ZSTD_cwksp_move(&cctx->workspace, &ws);
|
|
89
106
|
cctx->staticSize = workspaceSize;
|
|
90
|
-
cctx->workSpace = (void*)(cctx+1);
|
|
91
|
-
cctx->workSpaceSize = workspaceSize - sizeof(ZSTD_CCtx);
|
|
92
107
|
|
|
93
108
|
/* statically sized space. entropyWorkspace never moves (but prev/next block swap places) */
|
|
94
|
-
if (cctx->
|
|
95
|
-
|
|
96
|
-
cctx->blockState.
|
|
97
|
-
cctx->
|
|
98
|
-
{
|
|
99
|
-
void* const ptr = cctx->blockState.nextCBlock + 1;
|
|
100
|
-
cctx->entropyWorkspace = (U32*)ptr;
|
|
101
|
-
}
|
|
109
|
+
if (!ZSTD_cwksp_check_available(&cctx->workspace, HUF_WORKSPACE_SIZE + 2 * sizeof(ZSTD_compressedBlockState_t))) return NULL;
|
|
110
|
+
cctx->blockState.prevCBlock = (ZSTD_compressedBlockState_t*)ZSTD_cwksp_reserve_object(&cctx->workspace, sizeof(ZSTD_compressedBlockState_t));
|
|
111
|
+
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, HUF_WORKSPACE_SIZE);
|
|
102
113
|
cctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
|
|
103
114
|
return cctx;
|
|
104
115
|
}
|
|
@@ -126,11 +137,11 @@ static void ZSTD_freeCCtxContent(ZSTD_CCtx* cctx)
|
|
|
126
137
|
{
|
|
127
138
|
assert(cctx != NULL);
|
|
128
139
|
assert(cctx->staticSize == 0);
|
|
129
|
-
ZSTD_free(cctx->workSpace, cctx->customMem); cctx->workSpace = NULL;
|
|
130
140
|
ZSTD_clearAllDicts(cctx);
|
|
131
141
|
#ifdef ZSTD_MULTITHREAD
|
|
132
142
|
ZSTDMT_freeCCtx(cctx->mtctx); cctx->mtctx = NULL;
|
|
133
143
|
#endif
|
|
144
|
+
ZSTD_cwksp_free(&cctx->workspace, cctx->customMem);
|
|
134
145
|
}
|
|
135
146
|
|
|
136
147
|
size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
|
|
@@ -138,8 +149,13 @@ size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
|
|
|
138
149
|
if (cctx==NULL) return 0; /* support free on NULL */
|
|
139
150
|
RETURN_ERROR_IF(cctx->staticSize, memory_allocation,
|
|
140
151
|
"not compatible with static CCtx");
|
|
141
|
-
|
|
142
|
-
|
|
152
|
+
{
|
|
153
|
+
int cctxInWorkspace = ZSTD_cwksp_owns_buffer(&cctx->workspace, cctx);
|
|
154
|
+
ZSTD_freeCCtxContent(cctx);
|
|
155
|
+
if (!cctxInWorkspace) {
|
|
156
|
+
ZSTD_free(cctx, cctx->customMem);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
143
159
|
return 0;
|
|
144
160
|
}
|
|
145
161
|
|
|
@@ -158,7 +174,9 @@ static size_t ZSTD_sizeof_mtctx(const ZSTD_CCtx* cctx)
|
|
|
158
174
|
size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx)
|
|
159
175
|
{
|
|
160
176
|
if (cctx==NULL) return 0; /* support sizeof on NULL */
|
|
161
|
-
|
|
177
|
+
/* cctx may be in the workspace */
|
|
178
|
+
return (cctx->workspace.workspace == cctx ? 0 : sizeof(*cctx))
|
|
179
|
+
+ ZSTD_cwksp_sizeof(&cctx->workspace)
|
|
162
180
|
+ ZSTD_sizeof_localDict(cctx->localDict)
|
|
163
181
|
+ ZSTD_sizeof_mtctx(cctx);
|
|
164
182
|
}
|
|
@@ -215,7 +233,7 @@ size_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params)
|
|
|
215
233
|
}
|
|
216
234
|
|
|
217
235
|
size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel) {
|
|
218
|
-
RETURN_ERROR_IF(!cctxParams, GENERIC);
|
|
236
|
+
RETURN_ERROR_IF(!cctxParams, GENERIC, "NULL pointer!");
|
|
219
237
|
memset(cctxParams, 0, sizeof(*cctxParams));
|
|
220
238
|
cctxParams->compressionLevel = compressionLevel;
|
|
221
239
|
cctxParams->fParams.contentSizeFlag = 1;
|
|
@@ -224,26 +242,26 @@ size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel)
|
|
|
224
242
|
|
|
225
243
|
size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params)
|
|
226
244
|
{
|
|
227
|
-
RETURN_ERROR_IF(!cctxParams, GENERIC);
|
|
228
|
-
FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) );
|
|
245
|
+
RETURN_ERROR_IF(!cctxParams, GENERIC, "NULL pointer!");
|
|
246
|
+
FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) , "");
|
|
229
247
|
memset(cctxParams, 0, sizeof(*cctxParams));
|
|
248
|
+
assert(!ZSTD_checkCParams(params.cParams));
|
|
230
249
|
cctxParams->cParams = params.cParams;
|
|
231
250
|
cctxParams->fParams = params.fParams;
|
|
232
251
|
cctxParams->compressionLevel = ZSTD_CLEVEL_DEFAULT; /* should not matter, as all cParams are presumed properly defined */
|
|
233
|
-
assert(!ZSTD_checkCParams(params.cParams));
|
|
234
252
|
return 0;
|
|
235
253
|
}
|
|
236
254
|
|
|
237
255
|
/* ZSTD_assignParamsToCCtxParams() :
|
|
238
256
|
* params is presumed valid at this stage */
|
|
239
257
|
static ZSTD_CCtx_params ZSTD_assignParamsToCCtxParams(
|
|
240
|
-
ZSTD_CCtx_params cctxParams, ZSTD_parameters params)
|
|
258
|
+
const ZSTD_CCtx_params* cctxParams, const ZSTD_parameters* params)
|
|
241
259
|
{
|
|
242
|
-
ZSTD_CCtx_params ret = cctxParams;
|
|
243
|
-
|
|
244
|
-
ret.
|
|
260
|
+
ZSTD_CCtx_params ret = *cctxParams;
|
|
261
|
+
assert(!ZSTD_checkCParams(params->cParams));
|
|
262
|
+
ret.cParams = params->cParams;
|
|
263
|
+
ret.fParams = params->fParams;
|
|
245
264
|
ret.compressionLevel = ZSTD_CLEVEL_DEFAULT; /* should not matter, as all cParams are presumed properly defined */
|
|
246
|
-
assert(!ZSTD_checkCParams(params.cParams));
|
|
247
265
|
return ret;
|
|
248
266
|
}
|
|
249
267
|
|
|
@@ -327,8 +345,13 @@ ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param)
|
|
|
327
345
|
return bounds;
|
|
328
346
|
|
|
329
347
|
case ZSTD_c_overlapLog:
|
|
348
|
+
#ifdef ZSTD_MULTITHREAD
|
|
330
349
|
bounds.lowerBound = ZSTD_OVERLAPLOG_MIN;
|
|
331
350
|
bounds.upperBound = ZSTD_OVERLAPLOG_MAX;
|
|
351
|
+
#else
|
|
352
|
+
bounds.lowerBound = 0;
|
|
353
|
+
bounds.upperBound = 0;
|
|
354
|
+
#endif
|
|
332
355
|
return bounds;
|
|
333
356
|
|
|
334
357
|
case ZSTD_c_enableLongDistanceMatching:
|
|
@@ -376,7 +399,7 @@ ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param)
|
|
|
376
399
|
case ZSTD_c_forceAttachDict:
|
|
377
400
|
ZSTD_STATIC_ASSERT(ZSTD_dictDefaultAttach < ZSTD_dictForceCopy);
|
|
378
401
|
bounds.lowerBound = ZSTD_dictDefaultAttach;
|
|
379
|
-
bounds.upperBound =
|
|
402
|
+
bounds.upperBound = ZSTD_dictForceLoad; /* note : how to ensure at compile time that this is the highest value enum ? */
|
|
380
403
|
return bounds;
|
|
381
404
|
|
|
382
405
|
case ZSTD_c_literalCompressionMode:
|
|
@@ -385,25 +408,22 @@ ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param)
|
|
|
385
408
|
bounds.upperBound = ZSTD_lcm_uncompressed;
|
|
386
409
|
return bounds;
|
|
387
410
|
|
|
411
|
+
case ZSTD_c_targetCBlockSize:
|
|
412
|
+
bounds.lowerBound = ZSTD_TARGETCBLOCKSIZE_MIN;
|
|
413
|
+
bounds.upperBound = ZSTD_TARGETCBLOCKSIZE_MAX;
|
|
414
|
+
return bounds;
|
|
415
|
+
|
|
416
|
+
case ZSTD_c_srcSizeHint:
|
|
417
|
+
bounds.lowerBound = ZSTD_SRCSIZEHINT_MIN;
|
|
418
|
+
bounds.upperBound = ZSTD_SRCSIZEHINT_MAX;
|
|
419
|
+
return bounds;
|
|
420
|
+
|
|
388
421
|
default:
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
}
|
|
422
|
+
bounds.error = ERROR(parameter_unsupported);
|
|
423
|
+
return bounds;
|
|
392
424
|
}
|
|
393
425
|
}
|
|
394
426
|
|
|
395
|
-
/* ZSTD_cParam_withinBounds:
|
|
396
|
-
* @return 1 if value is within cParam bounds,
|
|
397
|
-
* 0 otherwise */
|
|
398
|
-
static int ZSTD_cParam_withinBounds(ZSTD_cParameter cParam, int value)
|
|
399
|
-
{
|
|
400
|
-
ZSTD_bounds const bounds = ZSTD_cParam_getBounds(cParam);
|
|
401
|
-
if (ZSTD_isError(bounds.error)) return 0;
|
|
402
|
-
if (value < bounds.lowerBound) return 0;
|
|
403
|
-
if (value > bounds.upperBound) return 0;
|
|
404
|
-
return 1;
|
|
405
|
-
}
|
|
406
|
-
|
|
407
427
|
/* ZSTD_cParam_clampBounds:
|
|
408
428
|
* Clamps the value into the bounded range.
|
|
409
429
|
*/
|
|
@@ -418,7 +438,7 @@ static size_t ZSTD_cParam_clampBounds(ZSTD_cParameter cParam, int* value)
|
|
|
418
438
|
|
|
419
439
|
#define BOUNDCHECK(cParam, val) { \
|
|
420
440
|
RETURN_ERROR_IF(!ZSTD_cParam_withinBounds(cParam,val), \
|
|
421
|
-
parameter_outOfBound); \
|
|
441
|
+
parameter_outOfBound, "Param out of bounds"); \
|
|
422
442
|
}
|
|
423
443
|
|
|
424
444
|
|
|
@@ -452,6 +472,8 @@ static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param)
|
|
|
452
472
|
case ZSTD_c_ldmHashRateLog:
|
|
453
473
|
case ZSTD_c_forceAttachDict:
|
|
454
474
|
case ZSTD_c_literalCompressionMode:
|
|
475
|
+
case ZSTD_c_targetCBlockSize:
|
|
476
|
+
case ZSTD_c_srcSizeHint:
|
|
455
477
|
default:
|
|
456
478
|
return 0;
|
|
457
479
|
}
|
|
@@ -464,7 +486,7 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value)
|
|
|
464
486
|
if (ZSTD_isUpdateAuthorized(param)) {
|
|
465
487
|
cctx->cParamsChanged = 1;
|
|
466
488
|
} else {
|
|
467
|
-
RETURN_ERROR(stage_wrong);
|
|
489
|
+
RETURN_ERROR(stage_wrong, "can only set params in ctx init stage");
|
|
468
490
|
} }
|
|
469
491
|
|
|
470
492
|
switch(param)
|
|
@@ -497,9 +519,11 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value)
|
|
|
497
519
|
case ZSTD_c_ldmHashLog:
|
|
498
520
|
case ZSTD_c_ldmMinMatch:
|
|
499
521
|
case ZSTD_c_ldmBucketSizeLog:
|
|
522
|
+
case ZSTD_c_targetCBlockSize:
|
|
523
|
+
case ZSTD_c_srcSizeHint:
|
|
500
524
|
break;
|
|
501
525
|
|
|
502
|
-
default: RETURN_ERROR(parameter_unsupported);
|
|
526
|
+
default: RETURN_ERROR(parameter_unsupported, "unknown parameter");
|
|
503
527
|
}
|
|
504
528
|
return ZSTD_CCtxParams_setParameter(&cctx->requestedParams, param, value);
|
|
505
529
|
}
|
|
@@ -516,37 +540,37 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
|
|
|
516
540
|
return (size_t)CCtxParams->format;
|
|
517
541
|
|
|
518
542
|
case ZSTD_c_compressionLevel : {
|
|
519
|
-
FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value));
|
|
543
|
+
FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value), "");
|
|
520
544
|
if (value) { /* 0 : does not change current level */
|
|
521
545
|
CCtxParams->compressionLevel = value;
|
|
522
546
|
}
|
|
523
|
-
if (CCtxParams->compressionLevel >= 0) return CCtxParams->compressionLevel;
|
|
547
|
+
if (CCtxParams->compressionLevel >= 0) return (size_t)CCtxParams->compressionLevel;
|
|
524
548
|
return 0; /* return type (size_t) cannot represent negative values */
|
|
525
549
|
}
|
|
526
550
|
|
|
527
551
|
case ZSTD_c_windowLog :
|
|
528
552
|
if (value!=0) /* 0 => use default */
|
|
529
553
|
BOUNDCHECK(ZSTD_c_windowLog, value);
|
|
530
|
-
CCtxParams->cParams.windowLog = value;
|
|
554
|
+
CCtxParams->cParams.windowLog = (U32)value;
|
|
531
555
|
return CCtxParams->cParams.windowLog;
|
|
532
556
|
|
|
533
557
|
case ZSTD_c_hashLog :
|
|
534
558
|
if (value!=0) /* 0 => use default */
|
|
535
559
|
BOUNDCHECK(ZSTD_c_hashLog, value);
|
|
536
|
-
CCtxParams->cParams.hashLog = value;
|
|
560
|
+
CCtxParams->cParams.hashLog = (U32)value;
|
|
537
561
|
return CCtxParams->cParams.hashLog;
|
|
538
562
|
|
|
539
563
|
case ZSTD_c_chainLog :
|
|
540
564
|
if (value!=0) /* 0 => use default */
|
|
541
565
|
BOUNDCHECK(ZSTD_c_chainLog, value);
|
|
542
|
-
CCtxParams->cParams.chainLog = value;
|
|
566
|
+
CCtxParams->cParams.chainLog = (U32)value;
|
|
543
567
|
return CCtxParams->cParams.chainLog;
|
|
544
568
|
|
|
545
569
|
case ZSTD_c_searchLog :
|
|
546
570
|
if (value!=0) /* 0 => use default */
|
|
547
571
|
BOUNDCHECK(ZSTD_c_searchLog, value);
|
|
548
|
-
CCtxParams->cParams.searchLog = value;
|
|
549
|
-
return value;
|
|
572
|
+
CCtxParams->cParams.searchLog = (U32)value;
|
|
573
|
+
return (size_t)value;
|
|
550
574
|
|
|
551
575
|
case ZSTD_c_minMatch :
|
|
552
576
|
if (value!=0) /* 0 => use default */
|
|
@@ -604,7 +628,7 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
|
|
|
604
628
|
RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading");
|
|
605
629
|
return 0;
|
|
606
630
|
#else
|
|
607
|
-
FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value));
|
|
631
|
+
FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value), "");
|
|
608
632
|
CCtxParams->nbWorkers = value;
|
|
609
633
|
return CCtxParams->nbWorkers;
|
|
610
634
|
#endif
|
|
@@ -617,7 +641,7 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
|
|
|
617
641
|
/* Adjust to the minimum non-default value. */
|
|
618
642
|
if (value != 0 && value < ZSTDMT_JOBSIZE_MIN)
|
|
619
643
|
value = ZSTDMT_JOBSIZE_MIN;
|
|
620
|
-
FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value));
|
|
644
|
+
FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value), "");
|
|
621
645
|
assert(value >= 0);
|
|
622
646
|
CCtxParams->jobSize = value;
|
|
623
647
|
return CCtxParams->jobSize;
|
|
@@ -628,7 +652,7 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
|
|
|
628
652
|
RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading");
|
|
629
653
|
return 0;
|
|
630
654
|
#else
|
|
631
|
-
FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(ZSTD_c_overlapLog, &value));
|
|
655
|
+
FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(ZSTD_c_overlapLog, &value), "");
|
|
632
656
|
CCtxParams->overlapLog = value;
|
|
633
657
|
return CCtxParams->overlapLog;
|
|
634
658
|
#endif
|
|
@@ -638,7 +662,7 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
|
|
|
638
662
|
RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading");
|
|
639
663
|
return 0;
|
|
640
664
|
#else
|
|
641
|
-
FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(ZSTD_c_overlapLog, &value));
|
|
665
|
+
FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(ZSTD_c_overlapLog, &value), "");
|
|
642
666
|
CCtxParams->rsyncable = value;
|
|
643
667
|
return CCtxParams->rsyncable;
|
|
644
668
|
#endif
|
|
@@ -667,10 +691,22 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
|
|
|
667
691
|
|
|
668
692
|
case ZSTD_c_ldmHashRateLog :
|
|
669
693
|
RETURN_ERROR_IF(value > ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN,
|
|
670
|
-
parameter_outOfBound);
|
|
694
|
+
parameter_outOfBound, "Param out of bounds!");
|
|
671
695
|
CCtxParams->ldmParams.hashRateLog = value;
|
|
672
696
|
return CCtxParams->ldmParams.hashRateLog;
|
|
673
697
|
|
|
698
|
+
case ZSTD_c_targetCBlockSize :
|
|
699
|
+
if (value!=0) /* 0 ==> default */
|
|
700
|
+
BOUNDCHECK(ZSTD_c_targetCBlockSize, value);
|
|
701
|
+
CCtxParams->targetCBlockSize = value;
|
|
702
|
+
return CCtxParams->targetCBlockSize;
|
|
703
|
+
|
|
704
|
+
case ZSTD_c_srcSizeHint :
|
|
705
|
+
if (value!=0) /* 0 ==> default */
|
|
706
|
+
BOUNDCHECK(ZSTD_c_srcSizeHint, value);
|
|
707
|
+
CCtxParams->srcSizeHint = value;
|
|
708
|
+
return CCtxParams->srcSizeHint;
|
|
709
|
+
|
|
674
710
|
default: RETURN_ERROR(parameter_unsupported, "unknown parameter");
|
|
675
711
|
}
|
|
676
712
|
}
|
|
@@ -692,13 +728,13 @@ size_t ZSTD_CCtxParams_getParameter(
|
|
|
692
728
|
*value = CCtxParams->compressionLevel;
|
|
693
729
|
break;
|
|
694
730
|
case ZSTD_c_windowLog :
|
|
695
|
-
*value = CCtxParams->cParams.windowLog;
|
|
731
|
+
*value = (int)CCtxParams->cParams.windowLog;
|
|
696
732
|
break;
|
|
697
733
|
case ZSTD_c_hashLog :
|
|
698
|
-
*value = CCtxParams->cParams.hashLog;
|
|
734
|
+
*value = (int)CCtxParams->cParams.hashLog;
|
|
699
735
|
break;
|
|
700
736
|
case ZSTD_c_chainLog :
|
|
701
|
-
*value = CCtxParams->cParams.chainLog;
|
|
737
|
+
*value = (int)CCtxParams->cParams.chainLog;
|
|
702
738
|
break;
|
|
703
739
|
case ZSTD_c_searchLog :
|
|
704
740
|
*value = CCtxParams->cParams.searchLog;
|
|
@@ -773,6 +809,12 @@ size_t ZSTD_CCtxParams_getParameter(
|
|
|
773
809
|
case ZSTD_c_ldmHashRateLog :
|
|
774
810
|
*value = CCtxParams->ldmParams.hashRateLog;
|
|
775
811
|
break;
|
|
812
|
+
case ZSTD_c_targetCBlockSize :
|
|
813
|
+
*value = (int)CCtxParams->targetCBlockSize;
|
|
814
|
+
break;
|
|
815
|
+
case ZSTD_c_srcSizeHint :
|
|
816
|
+
*value = (int)CCtxParams->srcSizeHint;
|
|
817
|
+
break;
|
|
776
818
|
default: RETURN_ERROR(parameter_unsupported, "unknown parameter");
|
|
777
819
|
}
|
|
778
820
|
return 0;
|
|
@@ -789,8 +831,11 @@ size_t ZSTD_CCtx_setParametersUsingCCtxParams(
|
|
|
789
831
|
ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params)
|
|
790
832
|
{
|
|
791
833
|
DEBUGLOG(4, "ZSTD_CCtx_setParametersUsingCCtxParams");
|
|
792
|
-
RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong
|
|
793
|
-
|
|
834
|
+
RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
|
|
835
|
+
"The context is in the wrong stage!");
|
|
836
|
+
RETURN_ERROR_IF(cctx->cdict, stage_wrong,
|
|
837
|
+
"Can't override parameters with cdict attached (some must "
|
|
838
|
+
"be inherited from the cdict).");
|
|
794
839
|
|
|
795
840
|
cctx->requestedParams = *params;
|
|
796
841
|
return 0;
|
|
@@ -799,7 +844,8 @@ size_t ZSTD_CCtx_setParametersUsingCCtxParams(
|
|
|
799
844
|
ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize)
|
|
800
845
|
{
|
|
801
846
|
DEBUGLOG(4, "ZSTD_CCtx_setPledgedSrcSize to %u bytes", (U32)pledgedSrcSize);
|
|
802
|
-
RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong
|
|
847
|
+
RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
|
|
848
|
+
"Can't set pledgedSrcSize when not in init stage.");
|
|
803
849
|
cctx->pledgedSrcSizePlusOne = pledgedSrcSize+1;
|
|
804
850
|
return 0;
|
|
805
851
|
}
|
|
@@ -813,7 +859,7 @@ static size_t ZSTD_initLocalDict(ZSTD_CCtx* cctx)
|
|
|
813
859
|
{
|
|
814
860
|
ZSTD_localDict* const dl = &cctx->localDict;
|
|
815
861
|
ZSTD_compressionParameters const cParams = ZSTD_getCParamsFromCCtxParams(
|
|
816
|
-
&cctx->requestedParams,
|
|
862
|
+
&cctx->requestedParams, ZSTD_CONTENTSIZE_UNKNOWN, dl->dictSize);
|
|
817
863
|
if (dl->dict == NULL) {
|
|
818
864
|
/* No local dictionary. */
|
|
819
865
|
assert(dl->dictBuffer == NULL);
|
|
@@ -837,7 +883,7 @@ static size_t ZSTD_initLocalDict(ZSTD_CCtx* cctx)
|
|
|
837
883
|
dl->dictContentType,
|
|
838
884
|
cParams,
|
|
839
885
|
cctx->customMem);
|
|
840
|
-
RETURN_ERROR_IF(!dl->cdict, memory_allocation);
|
|
886
|
+
RETURN_ERROR_IF(!dl->cdict, memory_allocation, "ZSTD_createCDict_advanced failed");
|
|
841
887
|
cctx->cdict = dl->cdict;
|
|
842
888
|
return 0;
|
|
843
889
|
}
|
|
@@ -846,7 +892,8 @@ size_t ZSTD_CCtx_loadDictionary_advanced(
|
|
|
846
892
|
ZSTD_CCtx* cctx, const void* dict, size_t dictSize,
|
|
847
893
|
ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType)
|
|
848
894
|
{
|
|
849
|
-
RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong
|
|
895
|
+
RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
|
|
896
|
+
"Can't load a dictionary when ctx is not in init stage.");
|
|
850
897
|
RETURN_ERROR_IF(cctx->staticSize, memory_allocation,
|
|
851
898
|
"no malloc for static CCtx");
|
|
852
899
|
DEBUGLOG(4, "ZSTD_CCtx_loadDictionary_advanced (size: %u)", (U32)dictSize);
|
|
@@ -857,7 +904,7 @@ size_t ZSTD_CCtx_loadDictionary_advanced(
|
|
|
857
904
|
cctx->localDict.dict = dict;
|
|
858
905
|
} else {
|
|
859
906
|
void* dictBuffer = ZSTD_malloc(dictSize, cctx->customMem);
|
|
860
|
-
RETURN_ERROR_IF(!dictBuffer, memory_allocation);
|
|
907
|
+
RETURN_ERROR_IF(!dictBuffer, memory_allocation, "NULL pointer!");
|
|
861
908
|
memcpy(dictBuffer, dict, dictSize);
|
|
862
909
|
cctx->localDict.dictBuffer = dictBuffer;
|
|
863
910
|
cctx->localDict.dict = dictBuffer;
|
|
@@ -883,7 +930,8 @@ ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, s
|
|
|
883
930
|
|
|
884
931
|
size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict)
|
|
885
932
|
{
|
|
886
|
-
RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong
|
|
933
|
+
RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
|
|
934
|
+
"Can't ref a dict when ctx not in init stage.");
|
|
887
935
|
/* Free the existing local cdict (if any) to save memory. */
|
|
888
936
|
ZSTD_clearAllDicts(cctx);
|
|
889
937
|
cctx->cdict = cdict;
|
|
@@ -898,11 +946,14 @@ size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSiz
|
|
|
898
946
|
size_t ZSTD_CCtx_refPrefix_advanced(
|
|
899
947
|
ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType)
|
|
900
948
|
{
|
|
901
|
-
RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong
|
|
949
|
+
RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
|
|
950
|
+
"Can't ref a prefix when ctx not in init stage.");
|
|
902
951
|
ZSTD_clearAllDicts(cctx);
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
952
|
+
if (prefix != NULL && prefixSize > 0) {
|
|
953
|
+
cctx->prefixDict.dict = prefix;
|
|
954
|
+
cctx->prefixDict.dictSize = prefixSize;
|
|
955
|
+
cctx->prefixDict.dictContentType = dictContentType;
|
|
956
|
+
}
|
|
906
957
|
return 0;
|
|
907
958
|
}
|
|
908
959
|
|
|
@@ -917,7 +968,8 @@ size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset)
|
|
|
917
968
|
}
|
|
918
969
|
if ( (reset == ZSTD_reset_parameters)
|
|
919
970
|
|| (reset == ZSTD_reset_session_and_parameters) ) {
|
|
920
|
-
RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong
|
|
971
|
+
RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
|
|
972
|
+
"Can't reset parameters only when not in init stage.");
|
|
921
973
|
ZSTD_clearAllDicts(cctx);
|
|
922
974
|
return ZSTD_CCtxParams_reset(&cctx->requestedParams);
|
|
923
975
|
}
|
|
@@ -930,12 +982,12 @@ size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset)
|
|
|
930
982
|
@return : 0, or an error code if one value is beyond authorized range */
|
|
931
983
|
size_t ZSTD_checkCParams(ZSTD_compressionParameters cParams)
|
|
932
984
|
{
|
|
933
|
-
BOUNDCHECK(ZSTD_c_windowLog, cParams.windowLog);
|
|
934
|
-
BOUNDCHECK(ZSTD_c_chainLog, cParams.chainLog);
|
|
935
|
-
BOUNDCHECK(ZSTD_c_hashLog, cParams.hashLog);
|
|
936
|
-
BOUNDCHECK(ZSTD_c_searchLog, cParams.searchLog);
|
|
937
|
-
BOUNDCHECK(ZSTD_c_minMatch, cParams.minMatch);
|
|
938
|
-
BOUNDCHECK(ZSTD_c_targetLength,cParams.targetLength);
|
|
985
|
+
BOUNDCHECK(ZSTD_c_windowLog, (int)cParams.windowLog);
|
|
986
|
+
BOUNDCHECK(ZSTD_c_chainLog, (int)cParams.chainLog);
|
|
987
|
+
BOUNDCHECK(ZSTD_c_hashLog, (int)cParams.hashLog);
|
|
988
|
+
BOUNDCHECK(ZSTD_c_searchLog, (int)cParams.searchLog);
|
|
989
|
+
BOUNDCHECK(ZSTD_c_minMatch, (int)cParams.minMatch);
|
|
990
|
+
BOUNDCHECK(ZSTD_c_targetLength,(int)cParams.targetLength);
|
|
939
991
|
BOUNDCHECK(ZSTD_c_strategy, cParams.strategy);
|
|
940
992
|
return 0;
|
|
941
993
|
}
|
|
@@ -951,7 +1003,7 @@ ZSTD_clampCParams(ZSTD_compressionParameters cParams)
|
|
|
951
1003
|
if ((int)val<bounds.lowerBound) val=(type)bounds.lowerBound; \
|
|
952
1004
|
else if ((int)val>bounds.upperBound) val=(type)bounds.upperBound; \
|
|
953
1005
|
}
|
|
954
|
-
# define CLAMP(cParam, val) CLAMP_TYPE(cParam, val,
|
|
1006
|
+
# define CLAMP(cParam, val) CLAMP_TYPE(cParam, val, unsigned)
|
|
955
1007
|
CLAMP(ZSTD_c_windowLog, cParams.windowLog);
|
|
956
1008
|
CLAMP(ZSTD_c_chainLog, cParams.chainLog);
|
|
957
1009
|
CLAMP(ZSTD_c_hashLog, cParams.hashLog);
|
|
@@ -964,7 +1016,7 @@ ZSTD_clampCParams(ZSTD_compressionParameters cParams)
|
|
|
964
1016
|
|
|
965
1017
|
/** ZSTD_cycleLog() :
|
|
966
1018
|
* condition for correct operation : hashLog > 1 */
|
|
967
|
-
|
|
1019
|
+
U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat)
|
|
968
1020
|
{
|
|
969
1021
|
U32 const btScale = ((U32)strat >= (U32)ZSTD_btlazy2);
|
|
970
1022
|
return hashLog - btScale;
|
|
@@ -974,7 +1026,7 @@ static U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat)
|
|
|
974
1026
|
* optimize `cPar` for a specified input (`srcSize` and `dictSize`).
|
|
975
1027
|
* mostly downsize to reduce memory consumption and initialization latency.
|
|
976
1028
|
* `srcSize` can be ZSTD_CONTENTSIZE_UNKNOWN when not known.
|
|
977
|
-
* note :
|
|
1029
|
+
* note : `srcSize==0` means 0!
|
|
978
1030
|
* condition : cPar is presumed validated (can be checked using ZSTD_checkCParams()). */
|
|
979
1031
|
static ZSTD_compressionParameters
|
|
980
1032
|
ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar,
|
|
@@ -985,10 +1037,8 @@ ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar,
|
|
|
985
1037
|
static const U64 maxWindowResize = 1ULL << (ZSTD_WINDOWLOG_MAX-1);
|
|
986
1038
|
assert(ZSTD_checkCParams(cPar)==0);
|
|
987
1039
|
|
|
988
|
-
if (dictSize &&
|
|
989
|
-
srcSize = minSrcSize;
|
|
990
|
-
else if (srcSize == 0)
|
|
991
|
-
srcSize = ZSTD_CONTENTSIZE_UNKNOWN; /* 0 == unknown : presumed large */
|
|
1040
|
+
if (dictSize && srcSize == ZSTD_CONTENTSIZE_UNKNOWN)
|
|
1041
|
+
srcSize = minSrcSize;
|
|
992
1042
|
|
|
993
1043
|
/* resize windowLog if input is small enough, to use less memory */
|
|
994
1044
|
if ( (srcSize < maxWindowResize)
|
|
@@ -1017,13 +1067,21 @@ ZSTD_adjustCParams(ZSTD_compressionParameters cPar,
|
|
|
1017
1067
|
size_t dictSize)
|
|
1018
1068
|
{
|
|
1019
1069
|
cPar = ZSTD_clampCParams(cPar); /* resulting cPar is necessarily valid (all parameters within range) */
|
|
1070
|
+
if (srcSize == 0) srcSize = ZSTD_CONTENTSIZE_UNKNOWN;
|
|
1020
1071
|
return ZSTD_adjustCParams_internal(cPar, srcSize, dictSize);
|
|
1021
1072
|
}
|
|
1022
1073
|
|
|
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);
|
|
1076
|
+
|
|
1023
1077
|
ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
|
|
1024
1078
|
const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize)
|
|
1025
1079
|
{
|
|
1026
|
-
ZSTD_compressionParameters cParams
|
|
1080
|
+
ZSTD_compressionParameters cParams;
|
|
1081
|
+
if (srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN && CCtxParams->srcSizeHint > 0) {
|
|
1082
|
+
srcSizeHint = CCtxParams->srcSizeHint;
|
|
1083
|
+
}
|
|
1084
|
+
cParams = ZSTD_getCParams_internal(CCtxParams->compressionLevel, srcSizeHint, dictSize);
|
|
1027
1085
|
if (CCtxParams->ldmParams.enableLdm) cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG;
|
|
1028
1086
|
if (CCtxParams->cParams.windowLog) cParams.windowLog = CCtxParams->cParams.windowLog;
|
|
1029
1087
|
if (CCtxParams->cParams.hashLog) cParams.hashLog = CCtxParams->cParams.hashLog;
|
|
@@ -1033,6 +1091,7 @@ ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
|
|
|
1033
1091
|
if (CCtxParams->cParams.targetLength) cParams.targetLength = CCtxParams->cParams.targetLength;
|
|
1034
1092
|
if (CCtxParams->cParams.strategy) cParams.strategy = CCtxParams->cParams.strategy;
|
|
1035
1093
|
assert(!ZSTD_checkCParams(cParams));
|
|
1094
|
+
/* srcSizeHint == 0 means 0 */
|
|
1036
1095
|
return ZSTD_adjustCParams_internal(cParams, srcSizeHint, dictSize);
|
|
1037
1096
|
}
|
|
1038
1097
|
|
|
@@ -1043,10 +1102,19 @@ ZSTD_sizeof_matchState(const ZSTD_compressionParameters* const cParams,
|
|
|
1043
1102
|
size_t const chainSize = (cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cParams->chainLog);
|
|
1044
1103
|
size_t const hSize = ((size_t)1) << cParams->hashLog;
|
|
1045
1104
|
U32 const hashLog3 = (forCCtx && cParams->minMatch==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0;
|
|
1046
|
-
size_t const h3Size = ((size_t)1) << hashLog3;
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1105
|
+
size_t const h3Size = hashLog3 ? ((size_t)1) << hashLog3 : 0;
|
|
1106
|
+
/* We don't use ZSTD_cwksp_alloc_size() here because the tables aren't
|
|
1107
|
+
* surrounded by redzones in ASAN. */
|
|
1108
|
+
size_t const tableSpace = chainSize * sizeof(U32)
|
|
1109
|
+
+ hSize * sizeof(U32)
|
|
1110
|
+
+ h3Size * sizeof(U32);
|
|
1111
|
+
size_t const optPotentialSpace =
|
|
1112
|
+
ZSTD_cwksp_alloc_size((MaxML+1) * sizeof(U32))
|
|
1113
|
+
+ ZSTD_cwksp_alloc_size((MaxLL+1) * sizeof(U32))
|
|
1114
|
+
+ ZSTD_cwksp_alloc_size((MaxOff+1) * sizeof(U32))
|
|
1115
|
+
+ ZSTD_cwksp_alloc_size((1<<Litbits) * sizeof(U32))
|
|
1116
|
+
+ ZSTD_cwksp_alloc_size((ZSTD_OPT_NUM+1) * sizeof(ZSTD_match_t))
|
|
1117
|
+
+ ZSTD_cwksp_alloc_size((ZSTD_OPT_NUM+1) * sizeof(ZSTD_optimal_t));
|
|
1050
1118
|
size_t const optSpace = (forCCtx && (cParams->strategy >= ZSTD_btopt))
|
|
1051
1119
|
? optPotentialSpace
|
|
1052
1120
|
: 0;
|
|
@@ -1059,24 +1127,40 @@ size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params)
|
|
|
1059
1127
|
{
|
|
1060
1128
|
RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only.");
|
|
1061
1129
|
{ ZSTD_compressionParameters const cParams =
|
|
1062
|
-
ZSTD_getCParamsFromCCtxParams(params,
|
|
1130
|
+
ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0);
|
|
1063
1131
|
size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog);
|
|
1064
1132
|
U32 const divider = (cParams.minMatch==3) ? 3 : 4;
|
|
1065
1133
|
size_t const maxNbSeq = blockSize / divider;
|
|
1066
|
-
size_t const tokenSpace = WILDCOPY_OVERLENGTH + blockSize
|
|
1067
|
-
|
|
1068
|
-
|
|
1134
|
+
size_t const tokenSpace = ZSTD_cwksp_alloc_size(WILDCOPY_OVERLENGTH + blockSize)
|
|
1135
|
+
+ ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(seqDef))
|
|
1136
|
+
+ 3 * ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(BYTE));
|
|
1137
|
+
size_t const entropySpace = ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE);
|
|
1138
|
+
size_t const blockStateSpace = 2 * ZSTD_cwksp_alloc_size(sizeof(ZSTD_compressedBlockState_t));
|
|
1069
1139
|
size_t const matchStateSize = ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 1);
|
|
1070
1140
|
|
|
1071
1141
|
size_t const ldmSpace = ZSTD_ldm_getTableSize(params->ldmParams);
|
|
1072
|
-
size_t const ldmSeqSpace = ZSTD_ldm_getMaxNbSeq(params->ldmParams, blockSize) * sizeof(rawSeq);
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1142
|
+
size_t const ldmSeqSpace = ZSTD_cwksp_alloc_size(ZSTD_ldm_getMaxNbSeq(params->ldmParams, blockSize) * sizeof(rawSeq));
|
|
1143
|
+
|
|
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
|
+
|
|
1150
|
+
size_t const cctxSpace = ZSTD_cwksp_alloc_size(sizeof(ZSTD_CCtx));
|
|
1151
|
+
|
|
1152
|
+
size_t const neededSpace =
|
|
1153
|
+
cctxSpace +
|
|
1154
|
+
entropySpace +
|
|
1155
|
+
blockStateSpace +
|
|
1156
|
+
ldmSpace +
|
|
1157
|
+
ldmSeqSpace +
|
|
1158
|
+
matchStateSize +
|
|
1159
|
+
tokenSpace +
|
|
1160
|
+
bufferSpace;
|
|
1161
|
+
|
|
1162
|
+
DEBUGLOG(5, "estimate workspace : %u", (U32)neededSpace);
|
|
1163
|
+
return neededSpace;
|
|
1080
1164
|
}
|
|
1081
1165
|
}
|
|
1082
1166
|
|
|
@@ -1088,7 +1172,7 @@ size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams)
|
|
|
1088
1172
|
|
|
1089
1173
|
static size_t ZSTD_estimateCCtxSize_internal(int compressionLevel)
|
|
1090
1174
|
{
|
|
1091
|
-
ZSTD_compressionParameters const cParams =
|
|
1175
|
+
ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0);
|
|
1092
1176
|
return ZSTD_estimateCCtxSize_usingCParams(cParams);
|
|
1093
1177
|
}
|
|
1094
1178
|
|
|
@@ -1107,12 +1191,13 @@ size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params)
|
|
|
1107
1191
|
{
|
|
1108
1192
|
RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only.");
|
|
1109
1193
|
{ ZSTD_compressionParameters const cParams =
|
|
1110
|
-
ZSTD_getCParamsFromCCtxParams(params,
|
|
1194
|
+
ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0);
|
|
1111
1195
|
size_t const CCtxSize = ZSTD_estimateCCtxSize_usingCCtxParams(params);
|
|
1112
1196
|
size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog);
|
|
1113
1197
|
size_t const inBuffSize = ((size_t)1 << cParams.windowLog) + blockSize;
|
|
1114
1198
|
size_t const outBuffSize = ZSTD_compressBound(blockSize) + 1;
|
|
1115
|
-
size_t const streamingSize = inBuffSize
|
|
1199
|
+
size_t const streamingSize = ZSTD_cwksp_alloc_size(inBuffSize)
|
|
1200
|
+
+ ZSTD_cwksp_alloc_size(outBuffSize);
|
|
1116
1201
|
|
|
1117
1202
|
return CCtxSize + streamingSize;
|
|
1118
1203
|
}
|
|
@@ -1126,7 +1211,7 @@ size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams)
|
|
|
1126
1211
|
|
|
1127
1212
|
static size_t ZSTD_estimateCStreamSize_internal(int compressionLevel)
|
|
1128
1213
|
{
|
|
1129
|
-
ZSTD_compressionParameters const cParams =
|
|
1214
|
+
ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0);
|
|
1130
1215
|
return ZSTD_estimateCStreamSize_usingCParams(cParams);
|
|
1131
1216
|
}
|
|
1132
1217
|
|
|
@@ -1180,17 +1265,6 @@ size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx)
|
|
|
1180
1265
|
return 0; /* over-simplification; could also check if context is currently running in streaming mode, and in which case, report how many bytes are left to be flushed within output buffer */
|
|
1181
1266
|
}
|
|
1182
1267
|
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
static U32 ZSTD_equivalentCParams(ZSTD_compressionParameters cParams1,
|
|
1186
|
-
ZSTD_compressionParameters cParams2)
|
|
1187
|
-
{
|
|
1188
|
-
return (cParams1.hashLog == cParams2.hashLog)
|
|
1189
|
-
& (cParams1.chainLog == cParams2.chainLog)
|
|
1190
|
-
& (cParams1.strategy == cParams2.strategy) /* opt parser space */
|
|
1191
|
-
& ((cParams1.minMatch==3) == (cParams2.minMatch==3)); /* hashlog3 space */
|
|
1192
|
-
}
|
|
1193
|
-
|
|
1194
1268
|
static void ZSTD_assertEqualCParams(ZSTD_compressionParameters cParams1,
|
|
1195
1269
|
ZSTD_compressionParameters cParams2)
|
|
1196
1270
|
{
|
|
@@ -1205,72 +1279,7 @@ static void ZSTD_assertEqualCParams(ZSTD_compressionParameters cParams1,
|
|
|
1205
1279
|
assert(cParams1.strategy == cParams2.strategy);
|
|
1206
1280
|
}
|
|
1207
1281
|
|
|
1208
|
-
|
|
1209
|
-
* all the parameters are equivalent. */
|
|
1210
|
-
static U32 ZSTD_equivalentLdmParams(ldmParams_t ldmParams1,
|
|
1211
|
-
ldmParams_t ldmParams2)
|
|
1212
|
-
{
|
|
1213
|
-
return (!ldmParams1.enableLdm && !ldmParams2.enableLdm) ||
|
|
1214
|
-
(ldmParams1.enableLdm == ldmParams2.enableLdm &&
|
|
1215
|
-
ldmParams1.hashLog == ldmParams2.hashLog &&
|
|
1216
|
-
ldmParams1.bucketSizeLog == ldmParams2.bucketSizeLog &&
|
|
1217
|
-
ldmParams1.minMatchLength == ldmParams2.minMatchLength &&
|
|
1218
|
-
ldmParams1.hashRateLog == ldmParams2.hashRateLog);
|
|
1219
|
-
}
|
|
1220
|
-
|
|
1221
|
-
typedef enum { ZSTDb_not_buffered, ZSTDb_buffered } ZSTD_buffered_policy_e;
|
|
1222
|
-
|
|
1223
|
-
/* ZSTD_sufficientBuff() :
|
|
1224
|
-
* check internal buffers exist for streaming if buffPol == ZSTDb_buffered .
|
|
1225
|
-
* Note : they are assumed to be correctly sized if ZSTD_equivalentCParams()==1 */
|
|
1226
|
-
static U32 ZSTD_sufficientBuff(size_t bufferSize1, size_t maxNbSeq1,
|
|
1227
|
-
size_t maxNbLit1,
|
|
1228
|
-
ZSTD_buffered_policy_e buffPol2,
|
|
1229
|
-
ZSTD_compressionParameters cParams2,
|
|
1230
|
-
U64 pledgedSrcSize)
|
|
1231
|
-
{
|
|
1232
|
-
size_t const windowSize2 = MAX(1, (size_t)MIN(((U64)1 << cParams2.windowLog), pledgedSrcSize));
|
|
1233
|
-
size_t const blockSize2 = MIN(ZSTD_BLOCKSIZE_MAX, windowSize2);
|
|
1234
|
-
size_t const maxNbSeq2 = blockSize2 / ((cParams2.minMatch == 3) ? 3 : 4);
|
|
1235
|
-
size_t const maxNbLit2 = blockSize2;
|
|
1236
|
-
size_t const neededBufferSize2 = (buffPol2==ZSTDb_buffered) ? windowSize2 + blockSize2 : 0;
|
|
1237
|
-
DEBUGLOG(4, "ZSTD_sufficientBuff: is neededBufferSize2=%u <= bufferSize1=%u",
|
|
1238
|
-
(U32)neededBufferSize2, (U32)bufferSize1);
|
|
1239
|
-
DEBUGLOG(4, "ZSTD_sufficientBuff: is maxNbSeq2=%u <= maxNbSeq1=%u",
|
|
1240
|
-
(U32)maxNbSeq2, (U32)maxNbSeq1);
|
|
1241
|
-
DEBUGLOG(4, "ZSTD_sufficientBuff: is maxNbLit2=%u <= maxNbLit1=%u",
|
|
1242
|
-
(U32)maxNbLit2, (U32)maxNbLit1);
|
|
1243
|
-
return (maxNbLit2 <= maxNbLit1)
|
|
1244
|
-
& (maxNbSeq2 <= maxNbSeq1)
|
|
1245
|
-
& (neededBufferSize2 <= bufferSize1);
|
|
1246
|
-
}
|
|
1247
|
-
|
|
1248
|
-
/** Equivalence for resetCCtx purposes */
|
|
1249
|
-
static U32 ZSTD_equivalentParams(ZSTD_CCtx_params params1,
|
|
1250
|
-
ZSTD_CCtx_params params2,
|
|
1251
|
-
size_t buffSize1,
|
|
1252
|
-
size_t maxNbSeq1, size_t maxNbLit1,
|
|
1253
|
-
ZSTD_buffered_policy_e buffPol2,
|
|
1254
|
-
U64 pledgedSrcSize)
|
|
1255
|
-
{
|
|
1256
|
-
DEBUGLOG(4, "ZSTD_equivalentParams: pledgedSrcSize=%u", (U32)pledgedSrcSize);
|
|
1257
|
-
if (!ZSTD_equivalentCParams(params1.cParams, params2.cParams)) {
|
|
1258
|
-
DEBUGLOG(4, "ZSTD_equivalentCParams() == 0");
|
|
1259
|
-
return 0;
|
|
1260
|
-
}
|
|
1261
|
-
if (!ZSTD_equivalentLdmParams(params1.ldmParams, params2.ldmParams)) {
|
|
1262
|
-
DEBUGLOG(4, "ZSTD_equivalentLdmParams() == 0");
|
|
1263
|
-
return 0;
|
|
1264
|
-
}
|
|
1265
|
-
if (!ZSTD_sufficientBuff(buffSize1, maxNbSeq1, maxNbLit1, buffPol2,
|
|
1266
|
-
params2.cParams, pledgedSrcSize)) {
|
|
1267
|
-
DEBUGLOG(4, "ZSTD_sufficientBuff() == 0");
|
|
1268
|
-
return 0;
|
|
1269
|
-
}
|
|
1270
|
-
return 1;
|
|
1271
|
-
}
|
|
1272
|
-
|
|
1273
|
-
static void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs)
|
|
1282
|
+
void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs)
|
|
1274
1283
|
{
|
|
1275
1284
|
int i;
|
|
1276
1285
|
for (i = 0; i < ZSTD_REP_NUM; ++i)
|
|
@@ -1282,132 +1291,143 @@ static void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs)
|
|
|
1282
1291
|
}
|
|
1283
1292
|
|
|
1284
1293
|
/*! ZSTD_invalidateMatchState()
|
|
1285
|
-
*
|
|
1286
|
-
*
|
|
1294
|
+
* Invalidate all the matches in the match finder tables.
|
|
1295
|
+
* Requires nextSrc and base to be set (can be NULL).
|
|
1287
1296
|
*/
|
|
1288
1297
|
static void ZSTD_invalidateMatchState(ZSTD_matchState_t* ms)
|
|
1289
1298
|
{
|
|
1290
1299
|
ZSTD_window_clear(&ms->window);
|
|
1291
1300
|
|
|
1292
1301
|
ms->nextToUpdate = ms->window.dictLimit;
|
|
1293
|
-
ms->nextToUpdate3 = ms->window.dictLimit;
|
|
1294
1302
|
ms->loadedDictEnd = 0;
|
|
1295
1303
|
ms->opt.litLengthSum = 0; /* force reset of btopt stats */
|
|
1296
1304
|
ms->dictMatchState = NULL;
|
|
1297
1305
|
}
|
|
1298
1306
|
|
|
1299
|
-
|
|
1300
|
-
*
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
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;
|
|
1306
1316
|
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
cctx->dictID = 0;
|
|
1319
|
-
if (params.ldmParams.enableLdm)
|
|
1320
|
-
ZSTD_window_clear(&cctx->ldmState.window);
|
|
1321
|
-
ZSTD_referenceExternalSequences(cctx, NULL, 0);
|
|
1322
|
-
ZSTD_invalidateMatchState(&cctx->blockState.matchState);
|
|
1323
|
-
ZSTD_reset_compressedBlockState(cctx->blockState.prevCBlock);
|
|
1324
|
-
XXH64_reset(&cctx->xxhState, 0);
|
|
1325
|
-
return 0;
|
|
1326
|
-
}
|
|
1317
|
+
/**
|
|
1318
|
+
* Controls, for this matchState reset, whether the tables need to be cleared /
|
|
1319
|
+
* prepared for the coming compression (ZSTDcrp_makeClean), or whether the
|
|
1320
|
+
* tables can be left unclean (ZSTDcrp_leaveDirty), because we know that a
|
|
1321
|
+
* subsequent operation will overwrite the table space anyways (e.g., copying
|
|
1322
|
+
* the matchState contents in from a CDict).
|
|
1323
|
+
*/
|
|
1324
|
+
typedef enum {
|
|
1325
|
+
ZSTDcrp_makeClean,
|
|
1326
|
+
ZSTDcrp_leaveDirty
|
|
1327
|
+
} ZSTD_compResetPolicy_e;
|
|
1327
1328
|
|
|
1328
|
-
|
|
1329
|
+
/**
|
|
1330
|
+
* Controls, for this matchState reset, whether indexing can continue where it
|
|
1331
|
+
* left off (ZSTDirp_continue), or whether it needs to be restarted from zero
|
|
1332
|
+
* (ZSTDirp_reset).
|
|
1333
|
+
*/
|
|
1334
|
+
typedef enum {
|
|
1335
|
+
ZSTDirp_continue,
|
|
1336
|
+
ZSTDirp_reset
|
|
1337
|
+
} ZSTD_indexResetPolicy_e;
|
|
1338
|
+
|
|
1339
|
+
typedef enum {
|
|
1340
|
+
ZSTD_resetTarget_CDict,
|
|
1341
|
+
ZSTD_resetTarget_CCtx
|
|
1342
|
+
} ZSTD_resetTarget_e;
|
|
1329
1343
|
|
|
1330
|
-
static
|
|
1344
|
+
static size_t
|
|
1331
1345
|
ZSTD_reset_matchState(ZSTD_matchState_t* ms,
|
|
1332
|
-
|
|
1346
|
+
ZSTD_cwksp* ws,
|
|
1333
1347
|
const ZSTD_compressionParameters* cParams,
|
|
1334
|
-
|
|
1348
|
+
const ZSTD_compResetPolicy_e crp,
|
|
1349
|
+
const ZSTD_indexResetPolicy_e forceResetIndex,
|
|
1350
|
+
const ZSTD_resetTarget_e forWho)
|
|
1335
1351
|
{
|
|
1336
1352
|
size_t const chainSize = (cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cParams->chainLog);
|
|
1337
1353
|
size_t const hSize = ((size_t)1) << cParams->hashLog;
|
|
1338
|
-
U32 const hashLog3 = (
|
|
1339
|
-
size_t const h3Size = ((size_t)1) << hashLog3;
|
|
1340
|
-
size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
|
|
1354
|
+
U32 const hashLog3 = ((forWho == ZSTD_resetTarget_CCtx) && cParams->minMatch==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0;
|
|
1355
|
+
size_t const h3Size = hashLog3 ? ((size_t)1) << hashLog3 : 0;
|
|
1341
1356
|
|
|
1342
|
-
|
|
1357
|
+
DEBUGLOG(4, "reset indices : %u", forceResetIndex == ZSTDirp_reset);
|
|
1358
|
+
if (forceResetIndex == ZSTDirp_reset) {
|
|
1359
|
+
ZSTD_window_init(&ms->window);
|
|
1360
|
+
ZSTD_cwksp_mark_tables_dirty(ws);
|
|
1361
|
+
}
|
|
1343
1362
|
|
|
1344
1363
|
ms->hashLog3 = hashLog3;
|
|
1345
|
-
|
|
1346
|
-
ms->window.dictLimit = 1; /* start from 1, so that 1st position is valid */
|
|
1347
|
-
ms->window.lowLimit = 1; /* it ensures first and later CCtx usages compress the same */
|
|
1348
|
-
ms->window.nextSrc = ms->window.base + 1; /* see issue #1241 */
|
|
1364
|
+
|
|
1349
1365
|
ZSTD_invalidateMatchState(ms);
|
|
1350
1366
|
|
|
1367
|
+
assert(!ZSTD_cwksp_reserve_failed(ws)); /* check that allocation hasn't already failed */
|
|
1368
|
+
|
|
1369
|
+
ZSTD_cwksp_clear_tables(ws);
|
|
1370
|
+
|
|
1371
|
+
DEBUGLOG(5, "reserving table space");
|
|
1372
|
+
/* table Space */
|
|
1373
|
+
ms->hashTable = (U32*)ZSTD_cwksp_reserve_table(ws, hSize * sizeof(U32));
|
|
1374
|
+
ms->chainTable = (U32*)ZSTD_cwksp_reserve_table(ws, chainSize * sizeof(U32));
|
|
1375
|
+
ms->hashTable3 = (U32*)ZSTD_cwksp_reserve_table(ws, h3Size * sizeof(U32));
|
|
1376
|
+
RETURN_ERROR_IF(ZSTD_cwksp_reserve_failed(ws), memory_allocation,
|
|
1377
|
+
"failed a workspace allocation in ZSTD_reset_matchState");
|
|
1378
|
+
|
|
1379
|
+
DEBUGLOG(4, "reset table : %u", crp!=ZSTDcrp_leaveDirty);
|
|
1380
|
+
if (crp!=ZSTDcrp_leaveDirty) {
|
|
1381
|
+
/* reset tables only */
|
|
1382
|
+
ZSTD_cwksp_clean_tables(ws);
|
|
1383
|
+
}
|
|
1384
|
+
|
|
1351
1385
|
/* opt parser space */
|
|
1352
|
-
if (
|
|
1386
|
+
if ((forWho == ZSTD_resetTarget_CCtx) && (cParams->strategy >= ZSTD_btopt)) {
|
|
1353
1387
|
DEBUGLOG(4, "reserving optimal parser space");
|
|
1354
|
-
ms->opt.litFreq = (unsigned*)
|
|
1355
|
-
ms->opt.litLengthFreq =
|
|
1356
|
-
ms->opt.matchLengthFreq =
|
|
1357
|
-
ms->opt.offCodeFreq =
|
|
1358
|
-
|
|
1359
|
-
ms->opt.
|
|
1360
|
-
ptr = ms->opt.matchTable + ZSTD_OPT_NUM+1;
|
|
1361
|
-
ms->opt.priceTable = (ZSTD_optimal_t*)ptr;
|
|
1362
|
-
ptr = ms->opt.priceTable + ZSTD_OPT_NUM+1;
|
|
1388
|
+
ms->opt.litFreq = (unsigned*)ZSTD_cwksp_reserve_aligned(ws, (1<<Litbits) * sizeof(unsigned));
|
|
1389
|
+
ms->opt.litLengthFreq = (unsigned*)ZSTD_cwksp_reserve_aligned(ws, (MaxLL+1) * sizeof(unsigned));
|
|
1390
|
+
ms->opt.matchLengthFreq = (unsigned*)ZSTD_cwksp_reserve_aligned(ws, (MaxML+1) * sizeof(unsigned));
|
|
1391
|
+
ms->opt.offCodeFreq = (unsigned*)ZSTD_cwksp_reserve_aligned(ws, (MaxOff+1) * sizeof(unsigned));
|
|
1392
|
+
ms->opt.matchTable = (ZSTD_match_t*)ZSTD_cwksp_reserve_aligned(ws, (ZSTD_OPT_NUM+1) * sizeof(ZSTD_match_t));
|
|
1393
|
+
ms->opt.priceTable = (ZSTD_optimal_t*)ZSTD_cwksp_reserve_aligned(ws, (ZSTD_OPT_NUM+1) * sizeof(ZSTD_optimal_t));
|
|
1363
1394
|
}
|
|
1364
1395
|
|
|
1365
|
-
/* table Space */
|
|
1366
|
-
DEBUGLOG(4, "reset table : %u", crp!=ZSTDcrp_noMemset);
|
|
1367
|
-
assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */
|
|
1368
|
-
if (crp!=ZSTDcrp_noMemset) memset(ptr, 0, tableSpace); /* reset tables only */
|
|
1369
|
-
ms->hashTable = (U32*)(ptr);
|
|
1370
|
-
ms->chainTable = ms->hashTable + hSize;
|
|
1371
|
-
ms->hashTable3 = ms->chainTable + chainSize;
|
|
1372
|
-
ptr = ms->hashTable3 + h3Size;
|
|
1373
|
-
|
|
1374
1396
|
ms->cParams = *cParams;
|
|
1375
1397
|
|
|
1376
|
-
|
|
1377
|
-
|
|
1398
|
+
RETURN_ERROR_IF(ZSTD_cwksp_reserve_failed(ws), memory_allocation,
|
|
1399
|
+
"failed a workspace allocation in ZSTD_reset_matchState");
|
|
1400
|
+
|
|
1401
|
+
return 0;
|
|
1378
1402
|
}
|
|
1379
1403
|
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1404
|
+
/* ZSTD_indexTooCloseToMax() :
|
|
1405
|
+
* minor optimization : prefer memset() rather than reduceIndex()
|
|
1406
|
+
* which is measurably slow in some circumstances (reported for Visual Studio).
|
|
1407
|
+
* Works when re-using a context for a lot of smallish inputs :
|
|
1408
|
+
* if all inputs are smaller than ZSTD_INDEXOVERFLOW_MARGIN,
|
|
1409
|
+
* memset() will be triggered before reduceIndex().
|
|
1410
|
+
*/
|
|
1411
|
+
#define ZSTD_INDEXOVERFLOW_MARGIN (16 MB)
|
|
1412
|
+
static int ZSTD_indexTooCloseToMax(ZSTD_window_t w)
|
|
1413
|
+
{
|
|
1414
|
+
return (size_t)(w.nextSrc - w.base) > (ZSTD_CURRENT_MAX - ZSTD_INDEXOVERFLOW_MARGIN);
|
|
1415
|
+
}
|
|
1386
1416
|
|
|
1387
1417
|
/*! ZSTD_resetCCtx_internal() :
|
|
1388
1418
|
note : `params` are assumed fully validated at this stage */
|
|
1389
1419
|
static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
|
|
1390
1420
|
ZSTD_CCtx_params params,
|
|
1391
|
-
U64 pledgedSrcSize,
|
|
1421
|
+
U64 const pledgedSrcSize,
|
|
1392
1422
|
ZSTD_compResetPolicy_e const crp,
|
|
1393
1423
|
ZSTD_buffered_policy_e const zbuff)
|
|
1394
1424
|
{
|
|
1425
|
+
ZSTD_cwksp* const ws = &zc->workspace;
|
|
1395
1426
|
DEBUGLOG(4, "ZSTD_resetCCtx_internal: pledgedSrcSize=%u, wlog=%u",
|
|
1396
1427
|
(U32)pledgedSrcSize, params.cParams.windowLog);
|
|
1397
1428
|
assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
|
|
1398
1429
|
|
|
1399
|
-
|
|
1400
|
-
if (ZSTD_equivalentParams(zc->appliedParams, params,
|
|
1401
|
-
zc->inBuffSize,
|
|
1402
|
-
zc->seqStore.maxNbSeq, zc->seqStore.maxNbLit,
|
|
1403
|
-
zbuff, pledgedSrcSize)) {
|
|
1404
|
-
DEBUGLOG(4, "ZSTD_equivalentParams()==1 -> continue mode (wLog1=%u, blockSize1=%zu)",
|
|
1405
|
-
zc->appliedParams.cParams.windowLog, zc->blockSize);
|
|
1406
|
-
zc->workSpaceOversizedDuration += (zc->workSpaceOversizedDuration > 0); /* if it was too large, it still is */
|
|
1407
|
-
if (zc->workSpaceOversizedDuration <= ZSTD_WORKSPACETOOLARGE_MAXDURATION)
|
|
1408
|
-
return ZSTD_continueCCtx(zc, params, pledgedSrcSize);
|
|
1409
|
-
} }
|
|
1410
|
-
DEBUGLOG(4, "ZSTD_equivalentParams()==0 -> reset CCtx");
|
|
1430
|
+
zc->isFirstBlock = 1;
|
|
1411
1431
|
|
|
1412
1432
|
if (params.ldmParams.enableLdm) {
|
|
1413
1433
|
/* Adjust long distance matching parameters */
|
|
@@ -1421,58 +1441,74 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
|
|
|
1421
1441
|
size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, windowSize);
|
|
1422
1442
|
U32 const divider = (params.cParams.minMatch==3) ? 3 : 4;
|
|
1423
1443
|
size_t const maxNbSeq = blockSize / divider;
|
|
1424
|
-
size_t const tokenSpace = WILDCOPY_OVERLENGTH + blockSize
|
|
1444
|
+
size_t const tokenSpace = ZSTD_cwksp_alloc_size(WILDCOPY_OVERLENGTH + blockSize)
|
|
1445
|
+
+ ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(seqDef))
|
|
1446
|
+
+ 3 * ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(BYTE));
|
|
1425
1447
|
size_t const buffOutSize = (zbuff==ZSTDb_buffered) ? ZSTD_compressBound(blockSize)+1 : 0;
|
|
1426
1448
|
size_t const buffInSize = (zbuff==ZSTDb_buffered) ? windowSize + blockSize : 0;
|
|
1427
1449
|
size_t const matchStateSize = ZSTD_sizeof_matchState(¶ms.cParams, /* forCCtx */ 1);
|
|
1428
1450
|
size_t const maxNbLdmSeq = ZSTD_ldm_getMaxNbSeq(params.ldmParams, blockSize);
|
|
1429
|
-
void* ptr; /* used to partition workSpace */
|
|
1430
1451
|
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1452
|
+
ZSTD_indexResetPolicy_e needsIndexReset = zc->initialized ? ZSTDirp_continue : ZSTDirp_reset;
|
|
1453
|
+
|
|
1454
|
+
if (ZSTD_indexTooCloseToMax(zc->blockState.matchState.window)) {
|
|
1455
|
+
needsIndexReset = ZSTDirp_reset;
|
|
1456
|
+
}
|
|
1457
|
+
|
|
1458
|
+
if (!zc->staticSize) ZSTD_cwksp_bump_oversized_duration(ws, 0);
|
|
1459
|
+
|
|
1460
|
+
/* Check if workspace is large enough, alloc a new one if needed */
|
|
1461
|
+
{ size_t const cctxSpace = zc->staticSize ? ZSTD_cwksp_alloc_size(sizeof(ZSTD_CCtx)) : 0;
|
|
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);
|
|
1435
1465
|
size_t const ldmSpace = ZSTD_ldm_getTableSize(params.ldmParams);
|
|
1436
|
-
size_t const ldmSeqSpace = maxNbLdmSeq * sizeof(rawSeq);
|
|
1466
|
+
size_t const ldmSeqSpace = ZSTD_cwksp_alloc_size(maxNbLdmSeq * sizeof(rawSeq));
|
|
1437
1467
|
|
|
1438
|
-
size_t const neededSpace =
|
|
1439
|
-
|
|
1440
|
-
|
|
1468
|
+
size_t const neededSpace =
|
|
1469
|
+
cctxSpace +
|
|
1470
|
+
entropySpace +
|
|
1471
|
+
blockStateSpace +
|
|
1472
|
+
ldmSpace +
|
|
1473
|
+
ldmSeqSpace +
|
|
1474
|
+
matchStateSize +
|
|
1475
|
+
tokenSpace +
|
|
1476
|
+
bufferSpace;
|
|
1441
1477
|
|
|
1442
|
-
int const
|
|
1443
|
-
int const
|
|
1444
|
-
int const workSpaceWasteful = workSpaceTooLarge && (zc->workSpaceOversizedDuration > ZSTD_WORKSPACETOOLARGE_MAXDURATION);
|
|
1445
|
-
zc->workSpaceOversizedDuration = workSpaceTooLarge ? zc->workSpaceOversizedDuration+1 : 0;
|
|
1478
|
+
int const workspaceTooSmall = ZSTD_cwksp_sizeof(ws) < neededSpace;
|
|
1479
|
+
int const workspaceWasteful = ZSTD_cwksp_check_wasteful(ws, neededSpace);
|
|
1446
1480
|
|
|
1447
1481
|
DEBUGLOG(4, "Need %zuKB workspace, including %zuKB for match state, and %zuKB for buffers",
|
|
1448
1482
|
neededSpace>>10, matchStateSize>>10, bufferSpace>>10);
|
|
1449
1483
|
DEBUGLOG(4, "windowSize: %zu - blockSize: %zu", windowSize, blockSize);
|
|
1450
1484
|
|
|
1451
|
-
if (
|
|
1452
|
-
DEBUGLOG(4, "
|
|
1453
|
-
|
|
1485
|
+
if (workspaceTooSmall || workspaceWasteful) {
|
|
1486
|
+
DEBUGLOG(4, "Resize workspaceSize from %zuKB to %zuKB",
|
|
1487
|
+
ZSTD_cwksp_sizeof(ws) >> 10,
|
|
1454
1488
|
neededSpace >> 10);
|
|
1455
1489
|
|
|
1456
1490
|
RETURN_ERROR_IF(zc->staticSize, memory_allocation, "static cctx : no resize");
|
|
1457
1491
|
|
|
1458
|
-
|
|
1459
|
-
ZSTD_free(zc->workSpace, zc->customMem);
|
|
1460
|
-
zc->workSpace = ZSTD_malloc(neededSpace, zc->customMem);
|
|
1461
|
-
RETURN_ERROR_IF(zc->workSpace == NULL, memory_allocation);
|
|
1462
|
-
zc->workSpaceSize = neededSpace;
|
|
1463
|
-
zc->workSpaceOversizedDuration = 0;
|
|
1492
|
+
needsIndexReset = ZSTDirp_reset;
|
|
1464
1493
|
|
|
1494
|
+
ZSTD_cwksp_free(ws, zc->customMem);
|
|
1495
|
+
FORWARD_IF_ERROR(ZSTD_cwksp_create(ws, neededSpace, zc->customMem), "");
|
|
1496
|
+
|
|
1497
|
+
DEBUGLOG(5, "reserving object space");
|
|
1465
1498
|
/* Statically sized space.
|
|
1466
1499
|
* entropyWorkspace never moves,
|
|
1467
1500
|
* though prev/next block swap places */
|
|
1468
|
-
assert((
|
|
1469
|
-
|
|
1470
|
-
zc->blockState.prevCBlock
|
|
1471
|
-
zc->blockState.nextCBlock =
|
|
1472
|
-
|
|
1473
|
-
zc->entropyWorkspace = (U32*)
|
|
1501
|
+
assert(ZSTD_cwksp_check_available(ws, 2 * sizeof(ZSTD_compressedBlockState_t)));
|
|
1502
|
+
zc->blockState.prevCBlock = (ZSTD_compressedBlockState_t*) ZSTD_cwksp_reserve_object(ws, sizeof(ZSTD_compressedBlockState_t));
|
|
1503
|
+
RETURN_ERROR_IF(zc->blockState.prevCBlock == NULL, memory_allocation, "couldn't allocate prevCBlock");
|
|
1504
|
+
zc->blockState.nextCBlock = (ZSTD_compressedBlockState_t*) ZSTD_cwksp_reserve_object(ws, sizeof(ZSTD_compressedBlockState_t));
|
|
1505
|
+
RETURN_ERROR_IF(zc->blockState.nextCBlock == NULL, memory_allocation, "couldn't allocate nextCBlock");
|
|
1506
|
+
zc->entropyWorkspace = (U32*) ZSTD_cwksp_reserve_object(ws, HUF_WORKSPACE_SIZE);
|
|
1507
|
+
RETURN_ERROR_IF(zc->blockState.nextCBlock == NULL, memory_allocation, "couldn't allocate entropyWorkspace");
|
|
1474
1508
|
} }
|
|
1475
1509
|
|
|
1510
|
+
ZSTD_cwksp_clear(ws);
|
|
1511
|
+
|
|
1476
1512
|
/* init params */
|
|
1477
1513
|
zc->appliedParams = params;
|
|
1478
1514
|
zc->blockState.matchState.cParams = params.cParams;
|
|
@@ -1491,57 +1527,60 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
|
|
|
1491
1527
|
|
|
1492
1528
|
ZSTD_reset_compressedBlockState(zc->blockState.prevCBlock);
|
|
1493
1529
|
|
|
1494
|
-
ptr = zc->entropyWorkspace + HUF_WORKSPACE_SIZE_U32;
|
|
1495
|
-
|
|
1496
|
-
/* ldm hash table */
|
|
1497
|
-
/* initialize bucketOffsets table later for pointer alignment */
|
|
1498
|
-
if (params.ldmParams.enableLdm) {
|
|
1499
|
-
size_t const ldmHSize = ((size_t)1) << params.ldmParams.hashLog;
|
|
1500
|
-
memset(ptr, 0, ldmHSize * sizeof(ldmEntry_t));
|
|
1501
|
-
assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */
|
|
1502
|
-
zc->ldmState.hashTable = (ldmEntry_t*)ptr;
|
|
1503
|
-
ptr = zc->ldmState.hashTable + ldmHSize;
|
|
1504
|
-
zc->ldmSequences = (rawSeq*)ptr;
|
|
1505
|
-
ptr = zc->ldmSequences + maxNbLdmSeq;
|
|
1506
|
-
zc->maxNbLdmSequences = maxNbLdmSeq;
|
|
1507
|
-
|
|
1508
|
-
memset(&zc->ldmState.window, 0, sizeof(zc->ldmState.window));
|
|
1509
|
-
}
|
|
1510
|
-
assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */
|
|
1511
|
-
|
|
1512
|
-
ptr = ZSTD_reset_matchState(&zc->blockState.matchState, ptr, ¶ms.cParams, crp, /* forCCtx */ 1);
|
|
1513
|
-
|
|
1514
|
-
/* sequences storage */
|
|
1515
|
-
zc->seqStore.maxNbSeq = maxNbSeq;
|
|
1516
|
-
zc->seqStore.sequencesStart = (seqDef*)ptr;
|
|
1517
|
-
ptr = zc->seqStore.sequencesStart + maxNbSeq;
|
|
1518
|
-
zc->seqStore.llCode = (BYTE*) ptr;
|
|
1519
|
-
zc->seqStore.mlCode = zc->seqStore.llCode + maxNbSeq;
|
|
1520
|
-
zc->seqStore.ofCode = zc->seqStore.mlCode + maxNbSeq;
|
|
1521
|
-
zc->seqStore.litStart = zc->seqStore.ofCode + maxNbSeq;
|
|
1522
1530
|
/* ZSTD_wildcopy() is used to copy into the literals buffer,
|
|
1523
1531
|
* so we have to oversize the buffer by WILDCOPY_OVERLENGTH bytes.
|
|
1524
1532
|
*/
|
|
1533
|
+
zc->seqStore.litStart = ZSTD_cwksp_reserve_buffer(ws, blockSize + WILDCOPY_OVERLENGTH);
|
|
1525
1534
|
zc->seqStore.maxNbLit = blockSize;
|
|
1526
|
-
|
|
1535
|
+
|
|
1536
|
+
/* buffers */
|
|
1537
|
+
zc->inBuffSize = buffInSize;
|
|
1538
|
+
zc->inBuff = (char*)ZSTD_cwksp_reserve_buffer(ws, buffInSize);
|
|
1539
|
+
zc->outBuffSize = buffOutSize;
|
|
1540
|
+
zc->outBuff = (char*)ZSTD_cwksp_reserve_buffer(ws, buffOutSize);
|
|
1527
1541
|
|
|
1528
1542
|
/* ldm bucketOffsets table */
|
|
1529
1543
|
if (params.ldmParams.enableLdm) {
|
|
1544
|
+
/* TODO: avoid memset? */
|
|
1530
1545
|
size_t const ldmBucketSize =
|
|
1531
1546
|
((size_t)1) << (params.ldmParams.hashLog -
|
|
1532
1547
|
params.ldmParams.bucketSizeLog);
|
|
1533
|
-
|
|
1534
|
-
zc->ldmState.bucketOffsets
|
|
1535
|
-
ptr = zc->ldmState.bucketOffsets + ldmBucketSize;
|
|
1536
|
-
ZSTD_window_clear(&zc->ldmState.window);
|
|
1548
|
+
zc->ldmState.bucketOffsets = ZSTD_cwksp_reserve_buffer(ws, ldmBucketSize);
|
|
1549
|
+
memset(zc->ldmState.bucketOffsets, 0, ldmBucketSize);
|
|
1537
1550
|
}
|
|
1551
|
+
|
|
1552
|
+
/* sequences storage */
|
|
1538
1553
|
ZSTD_referenceExternalSequences(zc, NULL, 0);
|
|
1554
|
+
zc->seqStore.maxNbSeq = maxNbSeq;
|
|
1555
|
+
zc->seqStore.llCode = ZSTD_cwksp_reserve_buffer(ws, maxNbSeq * sizeof(BYTE));
|
|
1556
|
+
zc->seqStore.mlCode = ZSTD_cwksp_reserve_buffer(ws, maxNbSeq * sizeof(BYTE));
|
|
1557
|
+
zc->seqStore.ofCode = ZSTD_cwksp_reserve_buffer(ws, maxNbSeq * sizeof(BYTE));
|
|
1558
|
+
zc->seqStore.sequencesStart = (seqDef*)ZSTD_cwksp_reserve_aligned(ws, maxNbSeq * sizeof(seqDef));
|
|
1559
|
+
|
|
1560
|
+
FORWARD_IF_ERROR(ZSTD_reset_matchState(
|
|
1561
|
+
&zc->blockState.matchState,
|
|
1562
|
+
ws,
|
|
1563
|
+
¶ms.cParams,
|
|
1564
|
+
crp,
|
|
1565
|
+
needsIndexReset,
|
|
1566
|
+
ZSTD_resetTarget_CCtx), "");
|
|
1539
1567
|
|
|
1540
|
-
/*
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1568
|
+
/* ldm hash table */
|
|
1569
|
+
if (params.ldmParams.enableLdm) {
|
|
1570
|
+
/* TODO: avoid memset? */
|
|
1571
|
+
size_t const ldmHSize = ((size_t)1) << params.ldmParams.hashLog;
|
|
1572
|
+
zc->ldmState.hashTable = (ldmEntry_t*)ZSTD_cwksp_reserve_aligned(ws, ldmHSize * sizeof(ldmEntry_t));
|
|
1573
|
+
memset(zc->ldmState.hashTable, 0, ldmHSize * sizeof(ldmEntry_t));
|
|
1574
|
+
zc->ldmSequences = (rawSeq*)ZSTD_cwksp_reserve_aligned(ws, maxNbLdmSeq * sizeof(rawSeq));
|
|
1575
|
+
zc->maxNbLdmSequences = maxNbLdmSeq;
|
|
1576
|
+
|
|
1577
|
+
ZSTD_window_init(&zc->ldmState.window);
|
|
1578
|
+
ZSTD_window_clear(&zc->ldmState.window);
|
|
1579
|
+
zc->ldmState.loadedDictEnd = 0;
|
|
1580
|
+
}
|
|
1581
|
+
|
|
1582
|
+
DEBUGLOG(3, "wksp: finished allocating, %zd bytes remain available", ZSTD_cwksp_available_space(ws));
|
|
1583
|
+
zc->initialized = 1;
|
|
1545
1584
|
|
|
1546
1585
|
return 0;
|
|
1547
1586
|
}
|
|
@@ -1575,40 +1614,39 @@ static const size_t attachDictSizeCutoffs[ZSTD_STRATEGY_MAX+1] = {
|
|
|
1575
1614
|
};
|
|
1576
1615
|
|
|
1577
1616
|
static int ZSTD_shouldAttachDict(const ZSTD_CDict* cdict,
|
|
1578
|
-
ZSTD_CCtx_params params,
|
|
1617
|
+
const ZSTD_CCtx_params* params,
|
|
1579
1618
|
U64 pledgedSrcSize)
|
|
1580
1619
|
{
|
|
1581
1620
|
size_t cutoff = attachDictSizeCutoffs[cdict->matchState.cParams.strategy];
|
|
1582
1621
|
return ( pledgedSrcSize <= cutoff
|
|
1583
1622
|
|| pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN
|
|
1584
|
-
|| params
|
|
1585
|
-
&& params
|
|
1586
|
-
&& !params
|
|
1623
|
+
|| params->attachDictPref == ZSTD_dictForceAttach )
|
|
1624
|
+
&& params->attachDictPref != ZSTD_dictForceCopy
|
|
1625
|
+
&& !params->forceWindow; /* dictMatchState isn't correctly
|
|
1587
1626
|
* handled in _enforceMaxDist */
|
|
1588
1627
|
}
|
|
1589
1628
|
|
|
1590
|
-
static size_t
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1629
|
+
static size_t
|
|
1630
|
+
ZSTD_resetCCtx_byAttachingCDict(ZSTD_CCtx* cctx,
|
|
1631
|
+
const ZSTD_CDict* cdict,
|
|
1632
|
+
ZSTD_CCtx_params params,
|
|
1633
|
+
U64 pledgedSrcSize,
|
|
1634
|
+
ZSTD_buffered_policy_e zbuff)
|
|
1596
1635
|
{
|
|
1597
|
-
{
|
|
1598
|
-
const ZSTD_compressionParameters *cdict_cParams = &cdict->matchState.cParams;
|
|
1636
|
+
{ const ZSTD_compressionParameters* const cdict_cParams = &cdict->matchState.cParams;
|
|
1599
1637
|
unsigned const windowLog = params.cParams.windowLog;
|
|
1600
1638
|
assert(windowLog != 0);
|
|
1601
1639
|
/* Resize working context table params for input only, since the dict
|
|
1602
1640
|
* has its own tables. */
|
|
1641
|
+
/* pledgeSrcSize == 0 means 0! */
|
|
1603
1642
|
params.cParams = ZSTD_adjustCParams_internal(*cdict_cParams, pledgedSrcSize, 0);
|
|
1604
1643
|
params.cParams.windowLog = windowLog;
|
|
1605
|
-
ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
|
|
1606
|
-
|
|
1644
|
+
FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
|
|
1645
|
+
ZSTDcrp_makeClean, zbuff), "");
|
|
1607
1646
|
assert(cctx->appliedParams.cParams.strategy == cdict_cParams->strategy);
|
|
1608
1647
|
}
|
|
1609
1648
|
|
|
1610
|
-
{
|
|
1611
|
-
const U32 cdictEnd = (U32)( cdict->matchState.window.nextSrc
|
|
1649
|
+
{ const U32 cdictEnd = (U32)( cdict->matchState.window.nextSrc
|
|
1612
1650
|
- cdict->matchState.window.base);
|
|
1613
1651
|
const U32 cdictLen = cdictEnd - cdict->matchState.window.dictLimit;
|
|
1614
1652
|
if (cdictLen == 0) {
|
|
@@ -1625,9 +1663,9 @@ static size_t ZSTD_resetCCtx_byAttachingCDict(
|
|
|
1625
1663
|
cctx->blockState.matchState.window.base + cdictEnd;
|
|
1626
1664
|
ZSTD_window_clear(&cctx->blockState.matchState.window);
|
|
1627
1665
|
}
|
|
1666
|
+
/* loadedDictEnd is expressed within the referential of the active context */
|
|
1628
1667
|
cctx->blockState.matchState.loadedDictEnd = cctx->blockState.matchState.window.dictLimit;
|
|
1629
|
-
|
|
1630
|
-
}
|
|
1668
|
+
} }
|
|
1631
1669
|
|
|
1632
1670
|
cctx->dictID = cdict->dictID;
|
|
1633
1671
|
|
|
@@ -1652,36 +1690,41 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx,
|
|
|
1652
1690
|
/* Copy only compression parameters related to tables. */
|
|
1653
1691
|
params.cParams = *cdict_cParams;
|
|
1654
1692
|
params.cParams.windowLog = windowLog;
|
|
1655
|
-
ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
|
|
1656
|
-
|
|
1693
|
+
FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
|
|
1694
|
+
ZSTDcrp_leaveDirty, zbuff), "");
|
|
1657
1695
|
assert(cctx->appliedParams.cParams.strategy == cdict_cParams->strategy);
|
|
1658
1696
|
assert(cctx->appliedParams.cParams.hashLog == cdict_cParams->hashLog);
|
|
1659
1697
|
assert(cctx->appliedParams.cParams.chainLog == cdict_cParams->chainLog);
|
|
1660
1698
|
}
|
|
1661
1699
|
|
|
1700
|
+
ZSTD_cwksp_mark_tables_dirty(&cctx->workspace);
|
|
1701
|
+
|
|
1662
1702
|
/* copy tables */
|
|
1663
1703
|
{ size_t const chainSize = (cdict_cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cdict_cParams->chainLog);
|
|
1664
1704
|
size_t const hSize = (size_t)1 << cdict_cParams->hashLog;
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1705
|
+
|
|
1706
|
+
memcpy(cctx->blockState.matchState.hashTable,
|
|
1707
|
+
cdict->matchState.hashTable,
|
|
1708
|
+
hSize * sizeof(U32));
|
|
1709
|
+
memcpy(cctx->blockState.matchState.chainTable,
|
|
1710
|
+
cdict->matchState.chainTable,
|
|
1711
|
+
chainSize * sizeof(U32));
|
|
1671
1712
|
}
|
|
1672
1713
|
|
|
1673
1714
|
/* Zero the hashTable3, since the cdict never fills it */
|
|
1674
|
-
{
|
|
1715
|
+
{ int const h3log = cctx->blockState.matchState.hashLog3;
|
|
1716
|
+
size_t const h3Size = h3log ? ((size_t)1 << h3log) : 0;
|
|
1675
1717
|
assert(cdict->matchState.hashLog3 == 0);
|
|
1676
1718
|
memset(cctx->blockState.matchState.hashTable3, 0, h3Size * sizeof(U32));
|
|
1677
1719
|
}
|
|
1678
1720
|
|
|
1721
|
+
ZSTD_cwksp_mark_tables_clean(&cctx->workspace);
|
|
1722
|
+
|
|
1679
1723
|
/* copy dictionary offsets */
|
|
1680
1724
|
{ ZSTD_matchState_t const* srcMatchState = &cdict->matchState;
|
|
1681
1725
|
ZSTD_matchState_t* dstMatchState = &cctx->blockState.matchState;
|
|
1682
1726
|
dstMatchState->window = srcMatchState->window;
|
|
1683
1727
|
dstMatchState->nextToUpdate = srcMatchState->nextToUpdate;
|
|
1684
|
-
dstMatchState->nextToUpdate3= srcMatchState->nextToUpdate3;
|
|
1685
1728
|
dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd;
|
|
1686
1729
|
}
|
|
1687
1730
|
|
|
@@ -1698,7 +1741,7 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx,
|
|
|
1698
1741
|
* in-place. We decide here which strategy to use. */
|
|
1699
1742
|
static size_t ZSTD_resetCCtx_usingCDict(ZSTD_CCtx* cctx,
|
|
1700
1743
|
const ZSTD_CDict* cdict,
|
|
1701
|
-
ZSTD_CCtx_params params,
|
|
1744
|
+
const ZSTD_CCtx_params* params,
|
|
1702
1745
|
U64 pledgedSrcSize,
|
|
1703
1746
|
ZSTD_buffered_policy_e zbuff)
|
|
1704
1747
|
{
|
|
@@ -1708,10 +1751,10 @@ static size_t ZSTD_resetCCtx_usingCDict(ZSTD_CCtx* cctx,
|
|
|
1708
1751
|
|
|
1709
1752
|
if (ZSTD_shouldAttachDict(cdict, params, pledgedSrcSize)) {
|
|
1710
1753
|
return ZSTD_resetCCtx_byAttachingCDict(
|
|
1711
|
-
cctx, cdict, params, pledgedSrcSize, zbuff);
|
|
1754
|
+
cctx, cdict, *params, pledgedSrcSize, zbuff);
|
|
1712
1755
|
} else {
|
|
1713
1756
|
return ZSTD_resetCCtx_byCopyingCDict(
|
|
1714
|
-
cctx, cdict, params, pledgedSrcSize, zbuff);
|
|
1757
|
+
cctx, cdict, *params, pledgedSrcSize, zbuff);
|
|
1715
1758
|
}
|
|
1716
1759
|
}
|
|
1717
1760
|
|
|
@@ -1729,7 +1772,8 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
|
|
|
1729
1772
|
ZSTD_buffered_policy_e zbuff)
|
|
1730
1773
|
{
|
|
1731
1774
|
DEBUGLOG(5, "ZSTD_copyCCtx_internal");
|
|
1732
|
-
RETURN_ERROR_IF(srcCCtx->stage!=ZSTDcs_init, stage_wrong
|
|
1775
|
+
RETURN_ERROR_IF(srcCCtx->stage!=ZSTDcs_init, stage_wrong,
|
|
1776
|
+
"Can't copy a ctx that's not in init stage.");
|
|
1733
1777
|
|
|
1734
1778
|
memcpy(&dstCCtx->customMem, &srcCCtx->customMem, sizeof(ZSTD_customMem));
|
|
1735
1779
|
{ ZSTD_CCtx_params params = dstCCtx->requestedParams;
|
|
@@ -1737,7 +1781,7 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
|
|
|
1737
1781
|
params.cParams = srcCCtx->appliedParams.cParams;
|
|
1738
1782
|
params.fParams = fParams;
|
|
1739
1783
|
ZSTD_resetCCtx_internal(dstCCtx, params, pledgedSrcSize,
|
|
1740
|
-
|
|
1784
|
+
ZSTDcrp_leaveDirty, zbuff);
|
|
1741
1785
|
assert(dstCCtx->appliedParams.cParams.windowLog == srcCCtx->appliedParams.cParams.windowLog);
|
|
1742
1786
|
assert(dstCCtx->appliedParams.cParams.strategy == srcCCtx->appliedParams.cParams.strategy);
|
|
1743
1787
|
assert(dstCCtx->appliedParams.cParams.hashLog == srcCCtx->appliedParams.cParams.hashLog);
|
|
@@ -1745,23 +1789,33 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
|
|
|
1745
1789
|
assert(dstCCtx->blockState.matchState.hashLog3 == srcCCtx->blockState.matchState.hashLog3);
|
|
1746
1790
|
}
|
|
1747
1791
|
|
|
1792
|
+
ZSTD_cwksp_mark_tables_dirty(&dstCCtx->workspace);
|
|
1793
|
+
|
|
1748
1794
|
/* copy tables */
|
|
1749
1795
|
{ size_t const chainSize = (srcCCtx->appliedParams.cParams.strategy == ZSTD_fast) ? 0 : ((size_t)1 << srcCCtx->appliedParams.cParams.chainLog);
|
|
1750
1796
|
size_t const hSize = (size_t)1 << srcCCtx->appliedParams.cParams.hashLog;
|
|
1751
|
-
|
|
1752
|
-
size_t const
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1797
|
+
int const h3log = srcCCtx->blockState.matchState.hashLog3;
|
|
1798
|
+
size_t const h3Size = h3log ? ((size_t)1 << h3log) : 0;
|
|
1799
|
+
|
|
1800
|
+
memcpy(dstCCtx->blockState.matchState.hashTable,
|
|
1801
|
+
srcCCtx->blockState.matchState.hashTable,
|
|
1802
|
+
hSize * sizeof(U32));
|
|
1803
|
+
memcpy(dstCCtx->blockState.matchState.chainTable,
|
|
1804
|
+
srcCCtx->blockState.matchState.chainTable,
|
|
1805
|
+
chainSize * sizeof(U32));
|
|
1806
|
+
memcpy(dstCCtx->blockState.matchState.hashTable3,
|
|
1807
|
+
srcCCtx->blockState.matchState.hashTable3,
|
|
1808
|
+
h3Size * sizeof(U32));
|
|
1756
1809
|
}
|
|
1757
1810
|
|
|
1811
|
+
ZSTD_cwksp_mark_tables_clean(&dstCCtx->workspace);
|
|
1812
|
+
|
|
1758
1813
|
/* copy dictionary offsets */
|
|
1759
1814
|
{
|
|
1760
1815
|
const ZSTD_matchState_t* srcMatchState = &srcCCtx->blockState.matchState;
|
|
1761
1816
|
ZSTD_matchState_t* dstMatchState = &dstCCtx->blockState.matchState;
|
|
1762
1817
|
dstMatchState->window = srcMatchState->window;
|
|
1763
1818
|
dstMatchState->nextToUpdate = srcMatchState->nextToUpdate;
|
|
1764
|
-
dstMatchState->nextToUpdate3= srcMatchState->nextToUpdate3;
|
|
1765
1819
|
dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd;
|
|
1766
1820
|
}
|
|
1767
1821
|
dstCCtx->dictID = srcCCtx->dictID;
|
|
@@ -1806,6 +1860,20 @@ ZSTD_reduceTable_internal (U32* const table, U32 const size, U32 const reducerVa
|
|
|
1806
1860
|
int rowNb;
|
|
1807
1861
|
assert((size & (ZSTD_ROWSIZE-1)) == 0); /* multiple of ZSTD_ROWSIZE */
|
|
1808
1862
|
assert(size < (1U<<31)); /* can be casted to int */
|
|
1863
|
+
|
|
1864
|
+
#if defined (MEMORY_SANITIZER) && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE)
|
|
1865
|
+
/* To validate that the table re-use logic is sound, and that we don't
|
|
1866
|
+
* access table space that we haven't cleaned, we re-"poison" the table
|
|
1867
|
+
* space every time we mark it dirty.
|
|
1868
|
+
*
|
|
1869
|
+
* This function however is intended to operate on those dirty tables and
|
|
1870
|
+
* re-clean them. So when this function is used correctly, we can unpoison
|
|
1871
|
+
* the memory it operated on. This introduces a blind spot though, since
|
|
1872
|
+
* if we now try to operate on __actually__ poisoned memory, we will not
|
|
1873
|
+
* detect that. */
|
|
1874
|
+
__msan_unpoison(table, size * sizeof(U32));
|
|
1875
|
+
#endif
|
|
1876
|
+
|
|
1809
1877
|
for (rowNb=0 ; rowNb < nbRows ; rowNb++) {
|
|
1810
1878
|
int column;
|
|
1811
1879
|
for (column=0; column<ZSTD_ROWSIZE; column++) {
|
|
@@ -1831,16 +1899,15 @@ static void ZSTD_reduceTable_btlazy2(U32* const table, U32 const size, U32 const
|
|
|
1831
1899
|
|
|
1832
1900
|
/*! ZSTD_reduceIndex() :
|
|
1833
1901
|
* rescale all indexes to avoid future overflow (indexes are U32) */
|
|
1834
|
-
static void ZSTD_reduceIndex (
|
|
1902
|
+
static void ZSTD_reduceIndex (ZSTD_matchState_t* ms, ZSTD_CCtx_params const* params, const U32 reducerValue)
|
|
1835
1903
|
{
|
|
1836
|
-
|
|
1837
|
-
{ U32 const hSize = (U32)1 << zc->appliedParams.cParams.hashLog;
|
|
1904
|
+
{ U32 const hSize = (U32)1 << params->cParams.hashLog;
|
|
1838
1905
|
ZSTD_reduceTable(ms->hashTable, hSize, reducerValue);
|
|
1839
1906
|
}
|
|
1840
1907
|
|
|
1841
|
-
if (
|
|
1842
|
-
U32 const chainSize = (U32)1 <<
|
|
1843
|
-
if (
|
|
1908
|
+
if (params->cParams.strategy != ZSTD_fast) {
|
|
1909
|
+
U32 const chainSize = (U32)1 << params->cParams.chainLog;
|
|
1910
|
+
if (params->cParams.strategy == ZSTD_btlazy2)
|
|
1844
1911
|
ZSTD_reduceTable_btlazy2(ms->chainTable, chainSize, reducerValue);
|
|
1845
1912
|
else
|
|
1846
1913
|
ZSTD_reduceTable(ms->chainTable, chainSize, reducerValue);
|
|
@@ -1859,165 +1926,6 @@ static void ZSTD_reduceIndex (ZSTD_CCtx* zc, const U32 reducerValue)
|
|
|
1859
1926
|
|
|
1860
1927
|
/* See doc/zstd_compression_format.md for detailed format description */
|
|
1861
1928
|
|
|
1862
|
-
static size_t ZSTD_noCompressBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize, U32 lastBlock)
|
|
1863
|
-
{
|
|
1864
|
-
U32 const cBlockHeader24 = lastBlock + (((U32)bt_raw)<<1) + (U32)(srcSize << 3);
|
|
1865
|
-
RETURN_ERROR_IF(srcSize + ZSTD_blockHeaderSize > dstCapacity,
|
|
1866
|
-
dstSize_tooSmall);
|
|
1867
|
-
MEM_writeLE24(dst, cBlockHeader24);
|
|
1868
|
-
memcpy((BYTE*)dst + ZSTD_blockHeaderSize, src, srcSize);
|
|
1869
|
-
return ZSTD_blockHeaderSize + srcSize;
|
|
1870
|
-
}
|
|
1871
|
-
|
|
1872
|
-
static size_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void* src, size_t srcSize)
|
|
1873
|
-
{
|
|
1874
|
-
BYTE* const ostart = (BYTE* const)dst;
|
|
1875
|
-
U32 const flSize = 1 + (srcSize>31) + (srcSize>4095);
|
|
1876
|
-
|
|
1877
|
-
RETURN_ERROR_IF(srcSize + flSize > dstCapacity, dstSize_tooSmall);
|
|
1878
|
-
|
|
1879
|
-
switch(flSize)
|
|
1880
|
-
{
|
|
1881
|
-
case 1: /* 2 - 1 - 5 */
|
|
1882
|
-
ostart[0] = (BYTE)((U32)set_basic + (srcSize<<3));
|
|
1883
|
-
break;
|
|
1884
|
-
case 2: /* 2 - 2 - 12 */
|
|
1885
|
-
MEM_writeLE16(ostart, (U16)((U32)set_basic + (1<<2) + (srcSize<<4)));
|
|
1886
|
-
break;
|
|
1887
|
-
case 3: /* 2 - 2 - 20 */
|
|
1888
|
-
MEM_writeLE32(ostart, (U32)((U32)set_basic + (3<<2) + (srcSize<<4)));
|
|
1889
|
-
break;
|
|
1890
|
-
default: /* not necessary : flSize is {1,2,3} */
|
|
1891
|
-
assert(0);
|
|
1892
|
-
}
|
|
1893
|
-
|
|
1894
|
-
memcpy(ostart + flSize, src, srcSize);
|
|
1895
|
-
return srcSize + flSize;
|
|
1896
|
-
}
|
|
1897
|
-
|
|
1898
|
-
static size_t ZSTD_compressRleLiteralsBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize)
|
|
1899
|
-
{
|
|
1900
|
-
BYTE* const ostart = (BYTE* const)dst;
|
|
1901
|
-
U32 const flSize = 1 + (srcSize>31) + (srcSize>4095);
|
|
1902
|
-
|
|
1903
|
-
(void)dstCapacity; /* dstCapacity already guaranteed to be >=4, hence large enough */
|
|
1904
|
-
|
|
1905
|
-
switch(flSize)
|
|
1906
|
-
{
|
|
1907
|
-
case 1: /* 2 - 1 - 5 */
|
|
1908
|
-
ostart[0] = (BYTE)((U32)set_rle + (srcSize<<3));
|
|
1909
|
-
break;
|
|
1910
|
-
case 2: /* 2 - 2 - 12 */
|
|
1911
|
-
MEM_writeLE16(ostart, (U16)((U32)set_rle + (1<<2) + (srcSize<<4)));
|
|
1912
|
-
break;
|
|
1913
|
-
case 3: /* 2 - 2 - 20 */
|
|
1914
|
-
MEM_writeLE32(ostart, (U32)((U32)set_rle + (3<<2) + (srcSize<<4)));
|
|
1915
|
-
break;
|
|
1916
|
-
default: /* not necessary : flSize is {1,2,3} */
|
|
1917
|
-
assert(0);
|
|
1918
|
-
}
|
|
1919
|
-
|
|
1920
|
-
ostart[flSize] = *(const BYTE*)src;
|
|
1921
|
-
return flSize+1;
|
|
1922
|
-
}
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
/* ZSTD_minGain() :
|
|
1926
|
-
* minimum compression required
|
|
1927
|
-
* to generate a compress block or a compressed literals section.
|
|
1928
|
-
* note : use same formula for both situations */
|
|
1929
|
-
static size_t ZSTD_minGain(size_t srcSize, ZSTD_strategy strat)
|
|
1930
|
-
{
|
|
1931
|
-
U32 const minlog = (strat>=ZSTD_btultra) ? (U32)(strat) - 1 : 6;
|
|
1932
|
-
ZSTD_STATIC_ASSERT(ZSTD_btultra == 8);
|
|
1933
|
-
assert(ZSTD_cParam_withinBounds(ZSTD_c_strategy, strat));
|
|
1934
|
-
return (srcSize >> minlog) + 2;
|
|
1935
|
-
}
|
|
1936
|
-
|
|
1937
|
-
static size_t ZSTD_compressLiterals (ZSTD_hufCTables_t const* prevHuf,
|
|
1938
|
-
ZSTD_hufCTables_t* nextHuf,
|
|
1939
|
-
ZSTD_strategy strategy, int disableLiteralCompression,
|
|
1940
|
-
void* dst, size_t dstCapacity,
|
|
1941
|
-
const void* src, size_t srcSize,
|
|
1942
|
-
void* workspace, size_t wkspSize,
|
|
1943
|
-
const int bmi2)
|
|
1944
|
-
{
|
|
1945
|
-
size_t const minGain = ZSTD_minGain(srcSize, strategy);
|
|
1946
|
-
size_t const lhSize = 3 + (srcSize >= 1 KB) + (srcSize >= 16 KB);
|
|
1947
|
-
BYTE* const ostart = (BYTE*)dst;
|
|
1948
|
-
U32 singleStream = srcSize < 256;
|
|
1949
|
-
symbolEncodingType_e hType = set_compressed;
|
|
1950
|
-
size_t cLitSize;
|
|
1951
|
-
|
|
1952
|
-
DEBUGLOG(5,"ZSTD_compressLiterals (disableLiteralCompression=%i)",
|
|
1953
|
-
disableLiteralCompression);
|
|
1954
|
-
|
|
1955
|
-
/* Prepare nextEntropy assuming reusing the existing table */
|
|
1956
|
-
memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
|
|
1957
|
-
|
|
1958
|
-
if (disableLiteralCompression)
|
|
1959
|
-
return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
|
|
1960
|
-
|
|
1961
|
-
/* small ? don't even attempt compression (speed opt) */
|
|
1962
|
-
# define COMPRESS_LITERALS_SIZE_MIN 63
|
|
1963
|
-
{ size_t const minLitSize = (prevHuf->repeatMode == HUF_repeat_valid) ? 6 : COMPRESS_LITERALS_SIZE_MIN;
|
|
1964
|
-
if (srcSize <= minLitSize) return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
|
|
1965
|
-
}
|
|
1966
|
-
|
|
1967
|
-
RETURN_ERROR_IF(dstCapacity < lhSize+1, dstSize_tooSmall, "not enough space for compression");
|
|
1968
|
-
{ HUF_repeat repeat = prevHuf->repeatMode;
|
|
1969
|
-
int const preferRepeat = strategy < ZSTD_lazy ? srcSize <= 1024 : 0;
|
|
1970
|
-
if (repeat == HUF_repeat_valid && lhSize == 3) singleStream = 1;
|
|
1971
|
-
cLitSize = singleStream ? HUF_compress1X_repeat(ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 11,
|
|
1972
|
-
workspace, wkspSize, (HUF_CElt*)nextHuf->CTable, &repeat, preferRepeat, bmi2)
|
|
1973
|
-
: HUF_compress4X_repeat(ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 11,
|
|
1974
|
-
workspace, wkspSize, (HUF_CElt*)nextHuf->CTable, &repeat, preferRepeat, bmi2);
|
|
1975
|
-
if (repeat != HUF_repeat_none) {
|
|
1976
|
-
/* reused the existing table */
|
|
1977
|
-
hType = set_repeat;
|
|
1978
|
-
}
|
|
1979
|
-
}
|
|
1980
|
-
|
|
1981
|
-
if ((cLitSize==0) | (cLitSize >= srcSize - minGain) | ERR_isError(cLitSize)) {
|
|
1982
|
-
memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
|
|
1983
|
-
return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
|
|
1984
|
-
}
|
|
1985
|
-
if (cLitSize==1) {
|
|
1986
|
-
memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
|
|
1987
|
-
return ZSTD_compressRleLiteralsBlock(dst, dstCapacity, src, srcSize);
|
|
1988
|
-
}
|
|
1989
|
-
|
|
1990
|
-
if (hType == set_compressed) {
|
|
1991
|
-
/* using a newly constructed table */
|
|
1992
|
-
nextHuf->repeatMode = HUF_repeat_check;
|
|
1993
|
-
}
|
|
1994
|
-
|
|
1995
|
-
/* Build header */
|
|
1996
|
-
switch(lhSize)
|
|
1997
|
-
{
|
|
1998
|
-
case 3: /* 2 - 2 - 10 - 10 */
|
|
1999
|
-
{ U32 const lhc = hType + ((!singleStream) << 2) + ((U32)srcSize<<4) + ((U32)cLitSize<<14);
|
|
2000
|
-
MEM_writeLE24(ostart, lhc);
|
|
2001
|
-
break;
|
|
2002
|
-
}
|
|
2003
|
-
case 4: /* 2 - 2 - 14 - 14 */
|
|
2004
|
-
{ U32 const lhc = hType + (2 << 2) + ((U32)srcSize<<4) + ((U32)cLitSize<<18);
|
|
2005
|
-
MEM_writeLE32(ostart, lhc);
|
|
2006
|
-
break;
|
|
2007
|
-
}
|
|
2008
|
-
case 5: /* 2 - 2 - 18 - 18 */
|
|
2009
|
-
{ U32 const lhc = hType + (3 << 2) + ((U32)srcSize<<4) + ((U32)cLitSize<<22);
|
|
2010
|
-
MEM_writeLE32(ostart, lhc);
|
|
2011
|
-
ostart[4] = (BYTE)(cLitSize >> 10);
|
|
2012
|
-
break;
|
|
2013
|
-
}
|
|
2014
|
-
default: /* not possible : lhSize is {3,4,5} */
|
|
2015
|
-
assert(0);
|
|
2016
|
-
}
|
|
2017
|
-
return lhSize+cLitSize;
|
|
2018
|
-
}
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
1929
|
void ZSTD_seqToCodes(const seqStore_t* seqStorePtr)
|
|
2022
1930
|
{
|
|
2023
1931
|
const seqDef* const sequences = seqStorePtr->sequencesStart;
|
|
@@ -2040,431 +1948,14 @@ void ZSTD_seqToCodes(const seqStore_t* seqStorePtr)
|
|
|
2040
1948
|
mlCodeTable[seqStorePtr->longLengthPos] = MaxML;
|
|
2041
1949
|
}
|
|
2042
1950
|
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
*
|
|
2046
|
-
*
|
|
2047
|
-
|
|
2048
|
-
*/
|
|
2049
|
-
static unsigned const kInverseProbabilityLog256[256] = {
|
|
2050
|
-
0, 2048, 1792, 1642, 1536, 1453, 1386, 1329, 1280, 1236, 1197, 1162,
|
|
2051
|
-
1130, 1100, 1073, 1047, 1024, 1001, 980, 960, 941, 923, 906, 889,
|
|
2052
|
-
874, 859, 844, 830, 817, 804, 791, 779, 768, 756, 745, 734,
|
|
2053
|
-
724, 714, 704, 694, 685, 676, 667, 658, 650, 642, 633, 626,
|
|
2054
|
-
618, 610, 603, 595, 588, 581, 574, 567, 561, 554, 548, 542,
|
|
2055
|
-
535, 529, 523, 517, 512, 506, 500, 495, 489, 484, 478, 473,
|
|
2056
|
-
468, 463, 458, 453, 448, 443, 438, 434, 429, 424, 420, 415,
|
|
2057
|
-
411, 407, 402, 398, 394, 390, 386, 382, 377, 373, 370, 366,
|
|
2058
|
-
362, 358, 354, 350, 347, 343, 339, 336, 332, 329, 325, 322,
|
|
2059
|
-
318, 315, 311, 308, 305, 302, 298, 295, 292, 289, 286, 282,
|
|
2060
|
-
279, 276, 273, 270, 267, 264, 261, 258, 256, 253, 250, 247,
|
|
2061
|
-
244, 241, 239, 236, 233, 230, 228, 225, 222, 220, 217, 215,
|
|
2062
|
-
212, 209, 207, 204, 202, 199, 197, 194, 192, 190, 187, 185,
|
|
2063
|
-
182, 180, 178, 175, 173, 171, 168, 166, 164, 162, 159, 157,
|
|
2064
|
-
155, 153, 151, 149, 146, 144, 142, 140, 138, 136, 134, 132,
|
|
2065
|
-
130, 128, 126, 123, 121, 119, 117, 115, 114, 112, 110, 108,
|
|
2066
|
-
106, 104, 102, 100, 98, 96, 94, 93, 91, 89, 87, 85,
|
|
2067
|
-
83, 82, 80, 78, 76, 74, 73, 71, 69, 67, 66, 64,
|
|
2068
|
-
62, 61, 59, 57, 55, 54, 52, 50, 49, 47, 46, 44,
|
|
2069
|
-
42, 41, 39, 37, 36, 34, 33, 31, 30, 28, 26, 25,
|
|
2070
|
-
23, 22, 20, 19, 17, 16, 14, 13, 11, 10, 8, 7,
|
|
2071
|
-
5, 4, 2, 1,
|
|
2072
|
-
};
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
/**
|
|
2076
|
-
* Returns the cost in bits of encoding the distribution described by count
|
|
2077
|
-
* using the entropy bound.
|
|
2078
|
-
*/
|
|
2079
|
-
static size_t ZSTD_entropyCost(unsigned const* count, unsigned const max, size_t const total)
|
|
2080
|
-
{
|
|
2081
|
-
unsigned cost = 0;
|
|
2082
|
-
unsigned s;
|
|
2083
|
-
for (s = 0; s <= max; ++s) {
|
|
2084
|
-
unsigned norm = (unsigned)((256 * count[s]) / total);
|
|
2085
|
-
if (count[s] != 0 && norm == 0)
|
|
2086
|
-
norm = 1;
|
|
2087
|
-
assert(count[s] < total);
|
|
2088
|
-
cost += count[s] * kInverseProbabilityLog256[norm];
|
|
2089
|
-
}
|
|
2090
|
-
return cost >> 8;
|
|
2091
|
-
}
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
/**
|
|
2095
|
-
* Returns the cost in bits of encoding the distribution in count using the
|
|
2096
|
-
* table described by norm. The max symbol support by norm is assumed >= max.
|
|
2097
|
-
* norm must be valid for every symbol with non-zero probability in count.
|
|
2098
|
-
*/
|
|
2099
|
-
static size_t ZSTD_crossEntropyCost(short const* norm, unsigned accuracyLog,
|
|
2100
|
-
unsigned const* count, unsigned const max)
|
|
2101
|
-
{
|
|
2102
|
-
unsigned const shift = 8 - accuracyLog;
|
|
2103
|
-
size_t cost = 0;
|
|
2104
|
-
unsigned s;
|
|
2105
|
-
assert(accuracyLog <= 8);
|
|
2106
|
-
for (s = 0; s <= max; ++s) {
|
|
2107
|
-
unsigned const normAcc = norm[s] != -1 ? norm[s] : 1;
|
|
2108
|
-
unsigned const norm256 = normAcc << shift;
|
|
2109
|
-
assert(norm256 > 0);
|
|
2110
|
-
assert(norm256 < 256);
|
|
2111
|
-
cost += count[s] * kInverseProbabilityLog256[norm256];
|
|
2112
|
-
}
|
|
2113
|
-
return cost >> 8;
|
|
2114
|
-
}
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
static unsigned ZSTD_getFSEMaxSymbolValue(FSE_CTable const* ctable) {
|
|
2118
|
-
void const* ptr = ctable;
|
|
2119
|
-
U16 const* u16ptr = (U16 const*)ptr;
|
|
2120
|
-
U32 const maxSymbolValue = MEM_read16(u16ptr + 1);
|
|
2121
|
-
return maxSymbolValue;
|
|
2122
|
-
}
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
/**
|
|
2126
|
-
* Returns the cost in bits of encoding the distribution in count using ctable.
|
|
2127
|
-
* Returns an error if ctable cannot represent all the symbols in count.
|
|
2128
|
-
*/
|
|
2129
|
-
static size_t ZSTD_fseBitCost(
|
|
2130
|
-
FSE_CTable const* ctable,
|
|
2131
|
-
unsigned const* count,
|
|
2132
|
-
unsigned const max)
|
|
2133
|
-
{
|
|
2134
|
-
unsigned const kAccuracyLog = 8;
|
|
2135
|
-
size_t cost = 0;
|
|
2136
|
-
unsigned s;
|
|
2137
|
-
FSE_CState_t cstate;
|
|
2138
|
-
FSE_initCState(&cstate, ctable);
|
|
2139
|
-
RETURN_ERROR_IF(ZSTD_getFSEMaxSymbolValue(ctable) < max, GENERIC,
|
|
2140
|
-
"Repeat FSE_CTable has maxSymbolValue %u < %u",
|
|
2141
|
-
ZSTD_getFSEMaxSymbolValue(ctable), max);
|
|
2142
|
-
for (s = 0; s <= max; ++s) {
|
|
2143
|
-
unsigned const tableLog = cstate.stateLog;
|
|
2144
|
-
unsigned const badCost = (tableLog + 1) << kAccuracyLog;
|
|
2145
|
-
unsigned const bitCost = FSE_bitCost(cstate.symbolTT, tableLog, s, kAccuracyLog);
|
|
2146
|
-
if (count[s] == 0)
|
|
2147
|
-
continue;
|
|
2148
|
-
RETURN_ERROR_IF(bitCost >= badCost, GENERIC,
|
|
2149
|
-
"Repeat FSE_CTable has Prob[%u] == 0", s);
|
|
2150
|
-
cost += count[s] * bitCost;
|
|
2151
|
-
}
|
|
2152
|
-
return cost >> kAccuracyLog;
|
|
2153
|
-
}
|
|
2154
|
-
|
|
2155
|
-
/**
|
|
2156
|
-
* Returns the cost in bytes of encoding the normalized count header.
|
|
2157
|
-
* Returns an error if any of the helper functions return an error.
|
|
2158
|
-
*/
|
|
2159
|
-
static size_t ZSTD_NCountCost(unsigned const* count, unsigned const max,
|
|
2160
|
-
size_t const nbSeq, unsigned const FSELog)
|
|
2161
|
-
{
|
|
2162
|
-
BYTE wksp[FSE_NCOUNTBOUND];
|
|
2163
|
-
S16 norm[MaxSeq + 1];
|
|
2164
|
-
const U32 tableLog = FSE_optimalTableLog(FSELog, nbSeq, max);
|
|
2165
|
-
FORWARD_IF_ERROR(FSE_normalizeCount(norm, tableLog, count, nbSeq, max));
|
|
2166
|
-
return FSE_writeNCount(wksp, sizeof(wksp), norm, max, tableLog);
|
|
2167
|
-
}
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
typedef enum {
|
|
2171
|
-
ZSTD_defaultDisallowed = 0,
|
|
2172
|
-
ZSTD_defaultAllowed = 1
|
|
2173
|
-
} ZSTD_defaultPolicy_e;
|
|
2174
|
-
|
|
2175
|
-
MEM_STATIC symbolEncodingType_e
|
|
2176
|
-
ZSTD_selectEncodingType(
|
|
2177
|
-
FSE_repeat* repeatMode, unsigned const* count, unsigned const max,
|
|
2178
|
-
size_t const mostFrequent, size_t nbSeq, unsigned const FSELog,
|
|
2179
|
-
FSE_CTable const* prevCTable,
|
|
2180
|
-
short const* defaultNorm, U32 defaultNormLog,
|
|
2181
|
-
ZSTD_defaultPolicy_e const isDefaultAllowed,
|
|
2182
|
-
ZSTD_strategy const strategy)
|
|
2183
|
-
{
|
|
2184
|
-
ZSTD_STATIC_ASSERT(ZSTD_defaultDisallowed == 0 && ZSTD_defaultAllowed != 0);
|
|
2185
|
-
if (mostFrequent == nbSeq) {
|
|
2186
|
-
*repeatMode = FSE_repeat_none;
|
|
2187
|
-
if (isDefaultAllowed && nbSeq <= 2) {
|
|
2188
|
-
/* Prefer set_basic over set_rle when there are 2 or less symbols,
|
|
2189
|
-
* since RLE uses 1 byte, but set_basic uses 5-6 bits per symbol.
|
|
2190
|
-
* If basic encoding isn't possible, always choose RLE.
|
|
2191
|
-
*/
|
|
2192
|
-
DEBUGLOG(5, "Selected set_basic");
|
|
2193
|
-
return set_basic;
|
|
2194
|
-
}
|
|
2195
|
-
DEBUGLOG(5, "Selected set_rle");
|
|
2196
|
-
return set_rle;
|
|
2197
|
-
}
|
|
2198
|
-
if (strategy < ZSTD_lazy) {
|
|
2199
|
-
if (isDefaultAllowed) {
|
|
2200
|
-
size_t const staticFse_nbSeq_max = 1000;
|
|
2201
|
-
size_t const mult = 10 - strategy;
|
|
2202
|
-
size_t const baseLog = 3;
|
|
2203
|
-
size_t const dynamicFse_nbSeq_min = (((size_t)1 << defaultNormLog) * mult) >> baseLog; /* 28-36 for offset, 56-72 for lengths */
|
|
2204
|
-
assert(defaultNormLog >= 5 && defaultNormLog <= 6); /* xx_DEFAULTNORMLOG */
|
|
2205
|
-
assert(mult <= 9 && mult >= 7);
|
|
2206
|
-
if ( (*repeatMode == FSE_repeat_valid)
|
|
2207
|
-
&& (nbSeq < staticFse_nbSeq_max) ) {
|
|
2208
|
-
DEBUGLOG(5, "Selected set_repeat");
|
|
2209
|
-
return set_repeat;
|
|
2210
|
-
}
|
|
2211
|
-
if ( (nbSeq < dynamicFse_nbSeq_min)
|
|
2212
|
-
|| (mostFrequent < (nbSeq >> (defaultNormLog-1))) ) {
|
|
2213
|
-
DEBUGLOG(5, "Selected set_basic");
|
|
2214
|
-
/* The format allows default tables to be repeated, but it isn't useful.
|
|
2215
|
-
* When using simple heuristics to select encoding type, we don't want
|
|
2216
|
-
* to confuse these tables with dictionaries. When running more careful
|
|
2217
|
-
* analysis, we don't need to waste time checking both repeating tables
|
|
2218
|
-
* and default tables.
|
|
2219
|
-
*/
|
|
2220
|
-
*repeatMode = FSE_repeat_none;
|
|
2221
|
-
return set_basic;
|
|
2222
|
-
}
|
|
2223
|
-
}
|
|
2224
|
-
} else {
|
|
2225
|
-
size_t const basicCost = isDefaultAllowed ? ZSTD_crossEntropyCost(defaultNorm, defaultNormLog, count, max) : ERROR(GENERIC);
|
|
2226
|
-
size_t const repeatCost = *repeatMode != FSE_repeat_none ? ZSTD_fseBitCost(prevCTable, count, max) : ERROR(GENERIC);
|
|
2227
|
-
size_t const NCountCost = ZSTD_NCountCost(count, max, nbSeq, FSELog);
|
|
2228
|
-
size_t const compressedCost = (NCountCost << 3) + ZSTD_entropyCost(count, max, nbSeq);
|
|
2229
|
-
|
|
2230
|
-
if (isDefaultAllowed) {
|
|
2231
|
-
assert(!ZSTD_isError(basicCost));
|
|
2232
|
-
assert(!(*repeatMode == FSE_repeat_valid && ZSTD_isError(repeatCost)));
|
|
2233
|
-
}
|
|
2234
|
-
assert(!ZSTD_isError(NCountCost));
|
|
2235
|
-
assert(compressedCost < ERROR(maxCode));
|
|
2236
|
-
DEBUGLOG(5, "Estimated bit costs: basic=%u\trepeat=%u\tcompressed=%u",
|
|
2237
|
-
(unsigned)basicCost, (unsigned)repeatCost, (unsigned)compressedCost);
|
|
2238
|
-
if (basicCost <= repeatCost && basicCost <= compressedCost) {
|
|
2239
|
-
DEBUGLOG(5, "Selected set_basic");
|
|
2240
|
-
assert(isDefaultAllowed);
|
|
2241
|
-
*repeatMode = FSE_repeat_none;
|
|
2242
|
-
return set_basic;
|
|
2243
|
-
}
|
|
2244
|
-
if (repeatCost <= compressedCost) {
|
|
2245
|
-
DEBUGLOG(5, "Selected set_repeat");
|
|
2246
|
-
assert(!ZSTD_isError(repeatCost));
|
|
2247
|
-
return set_repeat;
|
|
2248
|
-
}
|
|
2249
|
-
assert(compressedCost < basicCost && compressedCost < repeatCost);
|
|
2250
|
-
}
|
|
2251
|
-
DEBUGLOG(5, "Selected set_compressed");
|
|
2252
|
-
*repeatMode = FSE_repeat_check;
|
|
2253
|
-
return set_compressed;
|
|
2254
|
-
}
|
|
2255
|
-
|
|
2256
|
-
MEM_STATIC size_t
|
|
2257
|
-
ZSTD_buildCTable(void* dst, size_t dstCapacity,
|
|
2258
|
-
FSE_CTable* nextCTable, U32 FSELog, symbolEncodingType_e type,
|
|
2259
|
-
unsigned* count, U32 max,
|
|
2260
|
-
const BYTE* codeTable, size_t nbSeq,
|
|
2261
|
-
const S16* defaultNorm, U32 defaultNormLog, U32 defaultMax,
|
|
2262
|
-
const FSE_CTable* prevCTable, size_t prevCTableSize,
|
|
2263
|
-
void* workspace, size_t workspaceSize)
|
|
2264
|
-
{
|
|
2265
|
-
BYTE* op = (BYTE*)dst;
|
|
2266
|
-
const BYTE* const oend = op + dstCapacity;
|
|
2267
|
-
DEBUGLOG(6, "ZSTD_buildCTable (dstCapacity=%u)", (unsigned)dstCapacity);
|
|
2268
|
-
|
|
2269
|
-
switch (type) {
|
|
2270
|
-
case set_rle:
|
|
2271
|
-
FORWARD_IF_ERROR(FSE_buildCTable_rle(nextCTable, (BYTE)max));
|
|
2272
|
-
RETURN_ERROR_IF(dstCapacity==0, dstSize_tooSmall);
|
|
2273
|
-
*op = codeTable[0];
|
|
2274
|
-
return 1;
|
|
2275
|
-
case set_repeat:
|
|
2276
|
-
memcpy(nextCTable, prevCTable, prevCTableSize);
|
|
2277
|
-
return 0;
|
|
2278
|
-
case set_basic:
|
|
2279
|
-
FORWARD_IF_ERROR(FSE_buildCTable_wksp(nextCTable, defaultNorm, defaultMax, defaultNormLog, workspace, workspaceSize)); /* note : could be pre-calculated */
|
|
2280
|
-
return 0;
|
|
2281
|
-
case set_compressed: {
|
|
2282
|
-
S16 norm[MaxSeq + 1];
|
|
2283
|
-
size_t nbSeq_1 = nbSeq;
|
|
2284
|
-
const U32 tableLog = FSE_optimalTableLog(FSELog, nbSeq, max);
|
|
2285
|
-
if (count[codeTable[nbSeq-1]] > 1) {
|
|
2286
|
-
count[codeTable[nbSeq-1]]--;
|
|
2287
|
-
nbSeq_1--;
|
|
2288
|
-
}
|
|
2289
|
-
assert(nbSeq_1 > 1);
|
|
2290
|
-
FORWARD_IF_ERROR(FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max));
|
|
2291
|
-
{ size_t const NCountSize = FSE_writeNCount(op, oend - op, norm, max, tableLog); /* overflow protected */
|
|
2292
|
-
FORWARD_IF_ERROR(NCountSize);
|
|
2293
|
-
FORWARD_IF_ERROR(FSE_buildCTable_wksp(nextCTable, norm, max, tableLog, workspace, workspaceSize));
|
|
2294
|
-
return NCountSize;
|
|
2295
|
-
}
|
|
2296
|
-
}
|
|
2297
|
-
default: assert(0); RETURN_ERROR(GENERIC);
|
|
2298
|
-
}
|
|
2299
|
-
}
|
|
2300
|
-
|
|
2301
|
-
FORCE_INLINE_TEMPLATE size_t
|
|
2302
|
-
ZSTD_encodeSequences_body(
|
|
2303
|
-
void* dst, size_t dstCapacity,
|
|
2304
|
-
FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,
|
|
2305
|
-
FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,
|
|
2306
|
-
FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,
|
|
2307
|
-
seqDef const* sequences, size_t nbSeq, int longOffsets)
|
|
2308
|
-
{
|
|
2309
|
-
BIT_CStream_t blockStream;
|
|
2310
|
-
FSE_CState_t stateMatchLength;
|
|
2311
|
-
FSE_CState_t stateOffsetBits;
|
|
2312
|
-
FSE_CState_t stateLitLength;
|
|
2313
|
-
|
|
2314
|
-
RETURN_ERROR_IF(
|
|
2315
|
-
ERR_isError(BIT_initCStream(&blockStream, dst, dstCapacity)),
|
|
2316
|
-
dstSize_tooSmall, "not enough space remaining");
|
|
2317
|
-
DEBUGLOG(6, "available space for bitstream : %i (dstCapacity=%u)",
|
|
2318
|
-
(int)(blockStream.endPtr - blockStream.startPtr),
|
|
2319
|
-
(unsigned)dstCapacity);
|
|
2320
|
-
|
|
2321
|
-
/* first symbols */
|
|
2322
|
-
FSE_initCState2(&stateMatchLength, CTable_MatchLength, mlCodeTable[nbSeq-1]);
|
|
2323
|
-
FSE_initCState2(&stateOffsetBits, CTable_OffsetBits, ofCodeTable[nbSeq-1]);
|
|
2324
|
-
FSE_initCState2(&stateLitLength, CTable_LitLength, llCodeTable[nbSeq-1]);
|
|
2325
|
-
BIT_addBits(&blockStream, sequences[nbSeq-1].litLength, LL_bits[llCodeTable[nbSeq-1]]);
|
|
2326
|
-
if (MEM_32bits()) BIT_flushBits(&blockStream);
|
|
2327
|
-
BIT_addBits(&blockStream, sequences[nbSeq-1].matchLength, ML_bits[mlCodeTable[nbSeq-1]]);
|
|
2328
|
-
if (MEM_32bits()) BIT_flushBits(&blockStream);
|
|
2329
|
-
if (longOffsets) {
|
|
2330
|
-
U32 const ofBits = ofCodeTable[nbSeq-1];
|
|
2331
|
-
int const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN-1);
|
|
2332
|
-
if (extraBits) {
|
|
2333
|
-
BIT_addBits(&blockStream, sequences[nbSeq-1].offset, extraBits);
|
|
2334
|
-
BIT_flushBits(&blockStream);
|
|
2335
|
-
}
|
|
2336
|
-
BIT_addBits(&blockStream, sequences[nbSeq-1].offset >> extraBits,
|
|
2337
|
-
ofBits - extraBits);
|
|
2338
|
-
} else {
|
|
2339
|
-
BIT_addBits(&blockStream, sequences[nbSeq-1].offset, ofCodeTable[nbSeq-1]);
|
|
2340
|
-
}
|
|
2341
|
-
BIT_flushBits(&blockStream);
|
|
2342
|
-
|
|
2343
|
-
{ size_t n;
|
|
2344
|
-
for (n=nbSeq-2 ; n<nbSeq ; n--) { /* intentional underflow */
|
|
2345
|
-
BYTE const llCode = llCodeTable[n];
|
|
2346
|
-
BYTE const ofCode = ofCodeTable[n];
|
|
2347
|
-
BYTE const mlCode = mlCodeTable[n];
|
|
2348
|
-
U32 const llBits = LL_bits[llCode];
|
|
2349
|
-
U32 const ofBits = ofCode;
|
|
2350
|
-
U32 const mlBits = ML_bits[mlCode];
|
|
2351
|
-
DEBUGLOG(6, "encoding: litlen:%2u - matchlen:%2u - offCode:%7u",
|
|
2352
|
-
(unsigned)sequences[n].litLength,
|
|
2353
|
-
(unsigned)sequences[n].matchLength + MINMATCH,
|
|
2354
|
-
(unsigned)sequences[n].offset);
|
|
2355
|
-
/* 32b*/ /* 64b*/
|
|
2356
|
-
/* (7)*/ /* (7)*/
|
|
2357
|
-
FSE_encodeSymbol(&blockStream, &stateOffsetBits, ofCode); /* 15 */ /* 15 */
|
|
2358
|
-
FSE_encodeSymbol(&blockStream, &stateMatchLength, mlCode); /* 24 */ /* 24 */
|
|
2359
|
-
if (MEM_32bits()) BIT_flushBits(&blockStream); /* (7)*/
|
|
2360
|
-
FSE_encodeSymbol(&blockStream, &stateLitLength, llCode); /* 16 */ /* 33 */
|
|
2361
|
-
if (MEM_32bits() || (ofBits+mlBits+llBits >= 64-7-(LLFSELog+MLFSELog+OffFSELog)))
|
|
2362
|
-
BIT_flushBits(&blockStream); /* (7)*/
|
|
2363
|
-
BIT_addBits(&blockStream, sequences[n].litLength, llBits);
|
|
2364
|
-
if (MEM_32bits() && ((llBits+mlBits)>24)) BIT_flushBits(&blockStream);
|
|
2365
|
-
BIT_addBits(&blockStream, sequences[n].matchLength, mlBits);
|
|
2366
|
-
if (MEM_32bits() || (ofBits+mlBits+llBits > 56)) BIT_flushBits(&blockStream);
|
|
2367
|
-
if (longOffsets) {
|
|
2368
|
-
int const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN-1);
|
|
2369
|
-
if (extraBits) {
|
|
2370
|
-
BIT_addBits(&blockStream, sequences[n].offset, extraBits);
|
|
2371
|
-
BIT_flushBits(&blockStream); /* (7)*/
|
|
2372
|
-
}
|
|
2373
|
-
BIT_addBits(&blockStream, sequences[n].offset >> extraBits,
|
|
2374
|
-
ofBits - extraBits); /* 31 */
|
|
2375
|
-
} else {
|
|
2376
|
-
BIT_addBits(&blockStream, sequences[n].offset, ofBits); /* 31 */
|
|
2377
|
-
}
|
|
2378
|
-
BIT_flushBits(&blockStream); /* (7)*/
|
|
2379
|
-
DEBUGLOG(7, "remaining space : %i", (int)(blockStream.endPtr - blockStream.ptr));
|
|
2380
|
-
} }
|
|
2381
|
-
|
|
2382
|
-
DEBUGLOG(6, "ZSTD_encodeSequences: flushing ML state with %u bits", stateMatchLength.stateLog);
|
|
2383
|
-
FSE_flushCState(&blockStream, &stateMatchLength);
|
|
2384
|
-
DEBUGLOG(6, "ZSTD_encodeSequences: flushing Off state with %u bits", stateOffsetBits.stateLog);
|
|
2385
|
-
FSE_flushCState(&blockStream, &stateOffsetBits);
|
|
2386
|
-
DEBUGLOG(6, "ZSTD_encodeSequences: flushing LL state with %u bits", stateLitLength.stateLog);
|
|
2387
|
-
FSE_flushCState(&blockStream, &stateLitLength);
|
|
2388
|
-
|
|
2389
|
-
{ size_t const streamSize = BIT_closeCStream(&blockStream);
|
|
2390
|
-
RETURN_ERROR_IF(streamSize==0, dstSize_tooSmall, "not enough space");
|
|
2391
|
-
return streamSize;
|
|
2392
|
-
}
|
|
2393
|
-
}
|
|
2394
|
-
|
|
2395
|
-
static size_t
|
|
2396
|
-
ZSTD_encodeSequences_default(
|
|
2397
|
-
void* dst, size_t dstCapacity,
|
|
2398
|
-
FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,
|
|
2399
|
-
FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,
|
|
2400
|
-
FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,
|
|
2401
|
-
seqDef const* sequences, size_t nbSeq, int longOffsets)
|
|
2402
|
-
{
|
|
2403
|
-
return ZSTD_encodeSequences_body(dst, dstCapacity,
|
|
2404
|
-
CTable_MatchLength, mlCodeTable,
|
|
2405
|
-
CTable_OffsetBits, ofCodeTable,
|
|
2406
|
-
CTable_LitLength, llCodeTable,
|
|
2407
|
-
sequences, nbSeq, longOffsets);
|
|
2408
|
-
}
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
#if DYNAMIC_BMI2
|
|
2412
|
-
|
|
2413
|
-
static TARGET_ATTRIBUTE("bmi2") size_t
|
|
2414
|
-
ZSTD_encodeSequences_bmi2(
|
|
2415
|
-
void* dst, size_t dstCapacity,
|
|
2416
|
-
FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,
|
|
2417
|
-
FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,
|
|
2418
|
-
FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,
|
|
2419
|
-
seqDef const* sequences, size_t nbSeq, int longOffsets)
|
|
1951
|
+
/* ZSTD_useTargetCBlockSize():
|
|
1952
|
+
* Returns if target compressed block size param is being used.
|
|
1953
|
+
* If used, compression will do best effort to make a compressed block size to be around targetCBlockSize.
|
|
1954
|
+
* Returns 1 if true, 0 otherwise. */
|
|
1955
|
+
static int ZSTD_useTargetCBlockSize(const ZSTD_CCtx_params* cctxParams)
|
|
2420
1956
|
{
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
CTable_OffsetBits, ofCodeTable,
|
|
2424
|
-
CTable_LitLength, llCodeTable,
|
|
2425
|
-
sequences, nbSeq, longOffsets);
|
|
2426
|
-
}
|
|
2427
|
-
|
|
2428
|
-
#endif
|
|
2429
|
-
|
|
2430
|
-
static size_t ZSTD_encodeSequences(
|
|
2431
|
-
void* dst, size_t dstCapacity,
|
|
2432
|
-
FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,
|
|
2433
|
-
FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,
|
|
2434
|
-
FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,
|
|
2435
|
-
seqDef const* sequences, size_t nbSeq, int longOffsets, int bmi2)
|
|
2436
|
-
{
|
|
2437
|
-
DEBUGLOG(5, "ZSTD_encodeSequences: dstCapacity = %u", (unsigned)dstCapacity);
|
|
2438
|
-
#if DYNAMIC_BMI2
|
|
2439
|
-
if (bmi2) {
|
|
2440
|
-
return ZSTD_encodeSequences_bmi2(dst, dstCapacity,
|
|
2441
|
-
CTable_MatchLength, mlCodeTable,
|
|
2442
|
-
CTable_OffsetBits, ofCodeTable,
|
|
2443
|
-
CTable_LitLength, llCodeTable,
|
|
2444
|
-
sequences, nbSeq, longOffsets);
|
|
2445
|
-
}
|
|
2446
|
-
#endif
|
|
2447
|
-
(void)bmi2;
|
|
2448
|
-
return ZSTD_encodeSequences_default(dst, dstCapacity,
|
|
2449
|
-
CTable_MatchLength, mlCodeTable,
|
|
2450
|
-
CTable_OffsetBits, ofCodeTable,
|
|
2451
|
-
CTable_LitLength, llCodeTable,
|
|
2452
|
-
sequences, nbSeq, longOffsets);
|
|
2453
|
-
}
|
|
2454
|
-
|
|
2455
|
-
static int ZSTD_disableLiteralsCompression(const ZSTD_CCtx_params* cctxParams)
|
|
2456
|
-
{
|
|
2457
|
-
switch (cctxParams->literalCompressionMode) {
|
|
2458
|
-
case ZSTD_lcm_huffman:
|
|
2459
|
-
return 0;
|
|
2460
|
-
case ZSTD_lcm_uncompressed:
|
|
2461
|
-
return 1;
|
|
2462
|
-
default:
|
|
2463
|
-
assert(0 /* impossible: pre-validated */);
|
|
2464
|
-
/* fall-through */
|
|
2465
|
-
case ZSTD_lcm_auto:
|
|
2466
|
-
return (cctxParams->cParams.strategy == ZSTD_fast) && (cctxParams->cParams.targetLength > 0);
|
|
2467
|
-
}
|
|
1957
|
+
DEBUGLOG(5, "ZSTD_useTargetCBlockSize (targetCBlockSize=%zu)", cctxParams->targetCBlockSize);
|
|
1958
|
+
return (cctxParams->targetCBlockSize != 0);
|
|
2468
1959
|
}
|
|
2469
1960
|
|
|
2470
1961
|
/* ZSTD_compressSequences_internal():
|
|
@@ -2475,7 +1966,7 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
|
|
|
2475
1966
|
ZSTD_entropyCTables_t* nextEntropy,
|
|
2476
1967
|
const ZSTD_CCtx_params* cctxParams,
|
|
2477
1968
|
void* dst, size_t dstCapacity,
|
|
2478
|
-
void*
|
|
1969
|
+
void* entropyWorkspace, size_t entropyWkspSize,
|
|
2479
1970
|
const int bmi2)
|
|
2480
1971
|
{
|
|
2481
1972
|
const int longOffsets = cctxParams->cParams.windowLog > STREAM_ACCUMULATOR_MIN;
|
|
@@ -2492,52 +1983,59 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
|
|
|
2492
1983
|
BYTE* const ostart = (BYTE*)dst;
|
|
2493
1984
|
BYTE* const oend = ostart + dstCapacity;
|
|
2494
1985
|
BYTE* op = ostart;
|
|
2495
|
-
size_t const nbSeq = seqStorePtr->sequences - seqStorePtr->sequencesStart;
|
|
1986
|
+
size_t const nbSeq = (size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
|
|
2496
1987
|
BYTE* seqHead;
|
|
2497
1988
|
BYTE* lastNCount = NULL;
|
|
2498
1989
|
|
|
1990
|
+
DEBUGLOG(5, "ZSTD_compressSequences_internal (nbSeq=%zu)", nbSeq);
|
|
2499
1991
|
ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<<MAX(MLFSELog,LLFSELog)));
|
|
2500
|
-
DEBUGLOG(5, "ZSTD_compressSequences_internal");
|
|
2501
1992
|
|
|
2502
1993
|
/* Compress literals */
|
|
2503
1994
|
{ const BYTE* const literals = seqStorePtr->litStart;
|
|
2504
|
-
size_t const litSize = seqStorePtr->lit - literals;
|
|
1995
|
+
size_t const litSize = (size_t)(seqStorePtr->lit - literals);
|
|
2505
1996
|
size_t const cSize = ZSTD_compressLiterals(
|
|
2506
1997
|
&prevEntropy->huf, &nextEntropy->huf,
|
|
2507
1998
|
cctxParams->cParams.strategy,
|
|
2508
1999
|
ZSTD_disableLiteralsCompression(cctxParams),
|
|
2509
2000
|
op, dstCapacity,
|
|
2510
2001
|
literals, litSize,
|
|
2511
|
-
|
|
2002
|
+
entropyWorkspace, entropyWkspSize,
|
|
2512
2003
|
bmi2);
|
|
2513
|
-
FORWARD_IF_ERROR(cSize);
|
|
2004
|
+
FORWARD_IF_ERROR(cSize, "ZSTD_compressLiterals failed");
|
|
2514
2005
|
assert(cSize <= dstCapacity);
|
|
2515
2006
|
op += cSize;
|
|
2516
2007
|
}
|
|
2517
2008
|
|
|
2518
2009
|
/* Sequences Header */
|
|
2519
2010
|
RETURN_ERROR_IF((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead*/,
|
|
2520
|
-
dstSize_tooSmall);
|
|
2521
|
-
if (nbSeq <
|
|
2011
|
+
dstSize_tooSmall, "Can't fit seq hdr in output buf!");
|
|
2012
|
+
if (nbSeq < 128) {
|
|
2522
2013
|
*op++ = (BYTE)nbSeq;
|
|
2523
|
-
else if (nbSeq < LONGNBSEQ)
|
|
2524
|
-
op[0] = (BYTE)((nbSeq>>8) + 0x80)
|
|
2525
|
-
|
|
2526
|
-
op
|
|
2014
|
+
} else if (nbSeq < LONGNBSEQ) {
|
|
2015
|
+
op[0] = (BYTE)((nbSeq>>8) + 0x80);
|
|
2016
|
+
op[1] = (BYTE)nbSeq;
|
|
2017
|
+
op+=2;
|
|
2018
|
+
} else {
|
|
2019
|
+
op[0]=0xFF;
|
|
2020
|
+
MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ));
|
|
2021
|
+
op+=3;
|
|
2022
|
+
}
|
|
2023
|
+
assert(op <= oend);
|
|
2527
2024
|
if (nbSeq==0) {
|
|
2528
2025
|
/* Copy the old tables over as if we repeated them */
|
|
2529
2026
|
memcpy(&nextEntropy->fse, &prevEntropy->fse, sizeof(prevEntropy->fse));
|
|
2530
|
-
return op - ostart;
|
|
2027
|
+
return (size_t)(op - ostart);
|
|
2531
2028
|
}
|
|
2532
2029
|
|
|
2533
2030
|
/* seqHead : flags for FSE encoding type */
|
|
2534
2031
|
seqHead = op++;
|
|
2032
|
+
assert(op <= oend);
|
|
2535
2033
|
|
|
2536
2034
|
/* convert length/distances into codes */
|
|
2537
2035
|
ZSTD_seqToCodes(seqStorePtr);
|
|
2538
2036
|
/* build CTable for Literal Lengths */
|
|
2539
2037
|
{ unsigned max = MaxLL;
|
|
2540
|
-
size_t const mostFrequent = HIST_countFast_wksp(count, &max, llCodeTable, nbSeq,
|
|
2038
|
+
size_t const mostFrequent = HIST_countFast_wksp(count, &max, llCodeTable, nbSeq, entropyWorkspace, entropyWkspSize); /* can't fail */
|
|
2541
2039
|
DEBUGLOG(5, "Building LL table");
|
|
2542
2040
|
nextEntropy->fse.litlength_repeatMode = prevEntropy->fse.litlength_repeatMode;
|
|
2543
2041
|
LLtype = ZSTD_selectEncodingType(&nextEntropy->fse.litlength_repeatMode,
|
|
@@ -2547,18 +2045,24 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
|
|
|
2547
2045
|
ZSTD_defaultAllowed, strategy);
|
|
2548
2046
|
assert(set_basic < set_compressed && set_rle < set_compressed);
|
|
2549
2047
|
assert(!(LLtype < set_compressed && nextEntropy->fse.litlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */
|
|
2550
|
-
{ size_t const countSize = ZSTD_buildCTable(
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2048
|
+
{ size_t const countSize = ZSTD_buildCTable(
|
|
2049
|
+
op, (size_t)(oend - op),
|
|
2050
|
+
CTable_LitLength, LLFSELog, (symbolEncodingType_e)LLtype,
|
|
2051
|
+
count, max, llCodeTable, nbSeq,
|
|
2052
|
+
LL_defaultNorm, LL_defaultNormLog, MaxLL,
|
|
2053
|
+
prevEntropy->fse.litlengthCTable,
|
|
2054
|
+
sizeof(prevEntropy->fse.litlengthCTable),
|
|
2055
|
+
entropyWorkspace, entropyWkspSize);
|
|
2056
|
+
FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for LitLens failed");
|
|
2555
2057
|
if (LLtype == set_compressed)
|
|
2556
2058
|
lastNCount = op;
|
|
2557
2059
|
op += countSize;
|
|
2060
|
+
assert(op <= oend);
|
|
2558
2061
|
} }
|
|
2559
2062
|
/* build CTable for Offsets */
|
|
2560
2063
|
{ unsigned max = MaxOff;
|
|
2561
|
-
size_t const mostFrequent = HIST_countFast_wksp(
|
|
2064
|
+
size_t const mostFrequent = HIST_countFast_wksp(
|
|
2065
|
+
count, &max, ofCodeTable, nbSeq, entropyWorkspace, entropyWkspSize); /* can't fail */
|
|
2562
2066
|
/* We can only use the basic table if max <= DefaultMaxOff, otherwise the offsets are too large */
|
|
2563
2067
|
ZSTD_defaultPolicy_e const defaultPolicy = (max <= DefaultMaxOff) ? ZSTD_defaultAllowed : ZSTD_defaultDisallowed;
|
|
2564
2068
|
DEBUGLOG(5, "Building OF table");
|
|
@@ -2569,18 +2073,24 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
|
|
|
2569
2073
|
OF_defaultNorm, OF_defaultNormLog,
|
|
2570
2074
|
defaultPolicy, strategy);
|
|
2571
2075
|
assert(!(Offtype < set_compressed && nextEntropy->fse.offcode_repeatMode != FSE_repeat_none)); /* We don't copy tables */
|
|
2572
|
-
{ size_t const countSize = ZSTD_buildCTable(
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2076
|
+
{ size_t const countSize = ZSTD_buildCTable(
|
|
2077
|
+
op, (size_t)(oend - op),
|
|
2078
|
+
CTable_OffsetBits, OffFSELog, (symbolEncodingType_e)Offtype,
|
|
2079
|
+
count, max, ofCodeTable, nbSeq,
|
|
2080
|
+
OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
|
|
2081
|
+
prevEntropy->fse.offcodeCTable,
|
|
2082
|
+
sizeof(prevEntropy->fse.offcodeCTable),
|
|
2083
|
+
entropyWorkspace, entropyWkspSize);
|
|
2084
|
+
FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for Offsets failed");
|
|
2577
2085
|
if (Offtype == set_compressed)
|
|
2578
2086
|
lastNCount = op;
|
|
2579
2087
|
op += countSize;
|
|
2088
|
+
assert(op <= oend);
|
|
2580
2089
|
} }
|
|
2581
2090
|
/* build CTable for MatchLengths */
|
|
2582
2091
|
{ unsigned max = MaxML;
|
|
2583
|
-
size_t const mostFrequent = HIST_countFast_wksp(
|
|
2092
|
+
size_t const mostFrequent = HIST_countFast_wksp(
|
|
2093
|
+
count, &max, mlCodeTable, nbSeq, entropyWorkspace, entropyWkspSize); /* can't fail */
|
|
2584
2094
|
DEBUGLOG(5, "Building ML table (remaining space : %i)", (int)(oend-op));
|
|
2585
2095
|
nextEntropy->fse.matchlength_repeatMode = prevEntropy->fse.matchlength_repeatMode;
|
|
2586
2096
|
MLtype = ZSTD_selectEncodingType(&nextEntropy->fse.matchlength_repeatMode,
|
|
@@ -2589,27 +2099,33 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
|
|
|
2589
2099
|
ML_defaultNorm, ML_defaultNormLog,
|
|
2590
2100
|
ZSTD_defaultAllowed, strategy);
|
|
2591
2101
|
assert(!(MLtype < set_compressed && nextEntropy->fse.matchlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */
|
|
2592
|
-
{ size_t const countSize = ZSTD_buildCTable(
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2102
|
+
{ size_t const countSize = ZSTD_buildCTable(
|
|
2103
|
+
op, (size_t)(oend - op),
|
|
2104
|
+
CTable_MatchLength, MLFSELog, (symbolEncodingType_e)MLtype,
|
|
2105
|
+
count, max, mlCodeTable, nbSeq,
|
|
2106
|
+
ML_defaultNorm, ML_defaultNormLog, MaxML,
|
|
2107
|
+
prevEntropy->fse.matchlengthCTable,
|
|
2108
|
+
sizeof(prevEntropy->fse.matchlengthCTable),
|
|
2109
|
+
entropyWorkspace, entropyWkspSize);
|
|
2110
|
+
FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for MatchLengths failed");
|
|
2597
2111
|
if (MLtype == set_compressed)
|
|
2598
2112
|
lastNCount = op;
|
|
2599
2113
|
op += countSize;
|
|
2114
|
+
assert(op <= oend);
|
|
2600
2115
|
} }
|
|
2601
2116
|
|
|
2602
2117
|
*seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2));
|
|
2603
2118
|
|
|
2604
2119
|
{ size_t const bitstreamSize = ZSTD_encodeSequences(
|
|
2605
|
-
op, oend - op,
|
|
2120
|
+
op, (size_t)(oend - op),
|
|
2606
2121
|
CTable_MatchLength, mlCodeTable,
|
|
2607
2122
|
CTable_OffsetBits, ofCodeTable,
|
|
2608
2123
|
CTable_LitLength, llCodeTable,
|
|
2609
2124
|
sequences, nbSeq,
|
|
2610
2125
|
longOffsets, bmi2);
|
|
2611
|
-
FORWARD_IF_ERROR(bitstreamSize);
|
|
2126
|
+
FORWARD_IF_ERROR(bitstreamSize, "ZSTD_encodeSequences failed");
|
|
2612
2127
|
op += bitstreamSize;
|
|
2128
|
+
assert(op <= oend);
|
|
2613
2129
|
/* zstd versions <= 1.3.4 mistakenly report corruption when
|
|
2614
2130
|
* FSE_readNCount() receives a buffer < 4 bytes.
|
|
2615
2131
|
* Fixed by https://github.com/facebook/zstd/pull/1146.
|
|
@@ -2628,7 +2144,7 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
|
|
|
2628
2144
|
}
|
|
2629
2145
|
|
|
2630
2146
|
DEBUGLOG(5, "compressed block size : %u", (unsigned)(op - ostart));
|
|
2631
|
-
return op - ostart;
|
|
2147
|
+
return (size_t)(op - ostart);
|
|
2632
2148
|
}
|
|
2633
2149
|
|
|
2634
2150
|
MEM_STATIC size_t
|
|
@@ -2638,20 +2154,20 @@ ZSTD_compressSequences(seqStore_t* seqStorePtr,
|
|
|
2638
2154
|
const ZSTD_CCtx_params* cctxParams,
|
|
2639
2155
|
void* dst, size_t dstCapacity,
|
|
2640
2156
|
size_t srcSize,
|
|
2641
|
-
void*
|
|
2157
|
+
void* entropyWorkspace, size_t entropyWkspSize,
|
|
2642
2158
|
int bmi2)
|
|
2643
2159
|
{
|
|
2644
2160
|
size_t const cSize = ZSTD_compressSequences_internal(
|
|
2645
2161
|
seqStorePtr, prevEntropy, nextEntropy, cctxParams,
|
|
2646
2162
|
dst, dstCapacity,
|
|
2647
|
-
|
|
2163
|
+
entropyWorkspace, entropyWkspSize, bmi2);
|
|
2648
2164
|
if (cSize == 0) return 0;
|
|
2649
2165
|
/* When srcSize <= dstCapacity, there is enough space to write a raw uncompressed block.
|
|
2650
2166
|
* Since we ran out of space, block must be not compressible, so fall back to raw uncompressed block.
|
|
2651
2167
|
*/
|
|
2652
2168
|
if ((cSize == ERROR(dstSize_tooSmall)) & (srcSize <= dstCapacity))
|
|
2653
2169
|
return 0; /* block not compressed */
|
|
2654
|
-
FORWARD_IF_ERROR(cSize);
|
|
2170
|
+
FORWARD_IF_ERROR(cSize, "ZSTD_compressSequences_internal failed");
|
|
2655
2171
|
|
|
2656
2172
|
/* Check compressibility */
|
|
2657
2173
|
{ size_t const maxCSize = srcSize - ZSTD_minGain(srcSize, cctxParams->cParams.strategy);
|
|
@@ -2721,30 +2237,24 @@ void ZSTD_resetSeqStore(seqStore_t* ssPtr)
|
|
|
2721
2237
|
ssPtr->longLengthID = 0;
|
|
2722
2238
|
}
|
|
2723
2239
|
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2240
|
+
typedef enum { ZSTDbss_compress, ZSTDbss_noCompress } ZSTD_buildSeqStore_e;
|
|
2241
|
+
|
|
2242
|
+
static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
|
|
2727
2243
|
{
|
|
2728
2244
|
ZSTD_matchState_t* const ms = &zc->blockState.matchState;
|
|
2729
|
-
|
|
2730
|
-
DEBUGLOG(5, "ZSTD_compressBlock_internal (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u)",
|
|
2731
|
-
(unsigned)dstCapacity, (unsigned)ms->window.dictLimit, (unsigned)ms->nextToUpdate);
|
|
2245
|
+
DEBUGLOG(5, "ZSTD_buildSeqStore (srcSize=%zu)", srcSize);
|
|
2732
2246
|
assert(srcSize <= ZSTD_BLOCKSIZE_MAX);
|
|
2733
|
-
|
|
2734
2247
|
/* Assert that we have correctly flushed the ctx params into the ms's copy */
|
|
2735
2248
|
ZSTD_assertEqualCParams(zc->appliedParams.cParams, ms->cParams);
|
|
2736
|
-
|
|
2737
2249
|
if (srcSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1) {
|
|
2738
2250
|
ZSTD_ldm_skipSequences(&zc->externSeqStore, srcSize, zc->appliedParams.cParams.minMatch);
|
|
2739
|
-
|
|
2740
|
-
goto out; /* don't even attempt compression below a certain srcSize */
|
|
2251
|
+
return ZSTDbss_noCompress; /* don't even attempt compression below a certain srcSize */
|
|
2741
2252
|
}
|
|
2742
2253
|
ZSTD_resetSeqStore(&(zc->seqStore));
|
|
2743
2254
|
/* required for optimal parser to read stats from dictionary */
|
|
2744
2255
|
ms->opt.symbolCosts = &zc->blockState.prevCBlock->entropy;
|
|
2745
2256
|
/* tell the optimal parser how we expect to compress literals */
|
|
2746
2257
|
ms->opt.literalCompressionMode = zc->appliedParams.literalCompressionMode;
|
|
2747
|
-
|
|
2748
2258
|
/* a gap between an attached dict and the current window is not safe,
|
|
2749
2259
|
* they must remain adjacent,
|
|
2750
2260
|
* and when that stops being the case, the dict must be unset */
|
|
@@ -2783,7 +2293,7 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
|
|
|
2783
2293
|
/* Updates ldmSeqStore.size */
|
|
2784
2294
|
FORWARD_IF_ERROR(ZSTD_ldm_generateSequences(&zc->ldmState, &ldmSeqStore,
|
|
2785
2295
|
&zc->appliedParams.ldmParams,
|
|
2786
|
-
src, srcSize));
|
|
2296
|
+
src, srcSize), "");
|
|
2787
2297
|
/* Updates ldmSeqStore.pos */
|
|
2788
2298
|
lastLLSize =
|
|
2789
2299
|
ZSTD_ldm_blockCompress(&ldmSeqStore,
|
|
@@ -2798,6 +2308,134 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
|
|
|
2798
2308
|
{ const BYTE* const lastLiterals = (const BYTE*)src + srcSize - lastLLSize;
|
|
2799
2309
|
ZSTD_storeLastLiterals(&zc->seqStore, lastLiterals, lastLLSize);
|
|
2800
2310
|
} }
|
|
2311
|
+
return ZSTDbss_compress;
|
|
2312
|
+
}
|
|
2313
|
+
|
|
2314
|
+
static void ZSTD_copyBlockSequences(ZSTD_CCtx* zc)
|
|
2315
|
+
{
|
|
2316
|
+
const seqStore_t* seqStore = ZSTD_getSeqStore(zc);
|
|
2317
|
+
const seqDef* seqs = seqStore->sequencesStart;
|
|
2318
|
+
size_t seqsSize = seqStore->sequences - seqs;
|
|
2319
|
+
|
|
2320
|
+
ZSTD_Sequence* outSeqs = &zc->seqCollector.seqStart[zc->seqCollector.seqIndex];
|
|
2321
|
+
size_t i; size_t position; int repIdx;
|
|
2322
|
+
|
|
2323
|
+
assert(zc->seqCollector.seqIndex + 1 < zc->seqCollector.maxSequences);
|
|
2324
|
+
for (i = 0, position = 0; i < seqsSize; ++i) {
|
|
2325
|
+
outSeqs[i].offset = seqs[i].offset;
|
|
2326
|
+
outSeqs[i].litLength = seqs[i].litLength;
|
|
2327
|
+
outSeqs[i].matchLength = seqs[i].matchLength + MINMATCH;
|
|
2328
|
+
|
|
2329
|
+
if (i == seqStore->longLengthPos) {
|
|
2330
|
+
if (seqStore->longLengthID == 1) {
|
|
2331
|
+
outSeqs[i].litLength += 0x10000;
|
|
2332
|
+
} else if (seqStore->longLengthID == 2) {
|
|
2333
|
+
outSeqs[i].matchLength += 0x10000;
|
|
2334
|
+
}
|
|
2335
|
+
}
|
|
2336
|
+
|
|
2337
|
+
if (outSeqs[i].offset <= ZSTD_REP_NUM) {
|
|
2338
|
+
outSeqs[i].rep = outSeqs[i].offset;
|
|
2339
|
+
repIdx = (unsigned int)i - outSeqs[i].offset;
|
|
2340
|
+
|
|
2341
|
+
if (outSeqs[i].litLength == 0) {
|
|
2342
|
+
if (outSeqs[i].offset < 3) {
|
|
2343
|
+
--repIdx;
|
|
2344
|
+
} else {
|
|
2345
|
+
repIdx = (unsigned int)i - 1;
|
|
2346
|
+
}
|
|
2347
|
+
++outSeqs[i].rep;
|
|
2348
|
+
}
|
|
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
|
+
}
|
|
2357
|
+
|
|
2358
|
+
position += outSeqs[i].litLength;
|
|
2359
|
+
outSeqs[i].matchPos = (unsigned int)position;
|
|
2360
|
+
position += outSeqs[i].matchLength;
|
|
2361
|
+
}
|
|
2362
|
+
zc->seqCollector.seqIndex += seqsSize;
|
|
2363
|
+
}
|
|
2364
|
+
|
|
2365
|
+
size_t ZSTD_getSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs,
|
|
2366
|
+
size_t outSeqsSize, const void* src, size_t srcSize)
|
|
2367
|
+
{
|
|
2368
|
+
const size_t dstCapacity = ZSTD_compressBound(srcSize);
|
|
2369
|
+
void* dst = ZSTD_malloc(dstCapacity, ZSTD_defaultCMem);
|
|
2370
|
+
SeqCollector seqCollector;
|
|
2371
|
+
|
|
2372
|
+
RETURN_ERROR_IF(dst == NULL, memory_allocation, "NULL pointer!");
|
|
2373
|
+
|
|
2374
|
+
seqCollector.collectSequences = 1;
|
|
2375
|
+
seqCollector.seqStart = outSeqs;
|
|
2376
|
+
seqCollector.seqIndex = 0;
|
|
2377
|
+
seqCollector.maxSequences = outSeqsSize;
|
|
2378
|
+
zc->seqCollector = seqCollector;
|
|
2379
|
+
|
|
2380
|
+
ZSTD_compress2(zc, dst, dstCapacity, src, srcSize);
|
|
2381
|
+
ZSTD_free(dst, ZSTD_defaultCMem);
|
|
2382
|
+
return zc->seqCollector.seqIndex;
|
|
2383
|
+
}
|
|
2384
|
+
|
|
2385
|
+
/* Returns true if the given block is a RLE block */
|
|
2386
|
+
static int ZSTD_isRLE(const BYTE *ip, size_t length) {
|
|
2387
|
+
size_t i;
|
|
2388
|
+
if (length < 2) return 1;
|
|
2389
|
+
for (i = 1; i < length; ++i) {
|
|
2390
|
+
if (ip[0] != ip[i]) return 0;
|
|
2391
|
+
}
|
|
2392
|
+
return 1;
|
|
2393
|
+
}
|
|
2394
|
+
|
|
2395
|
+
/* Returns true if the given block may be RLE.
|
|
2396
|
+
* This is just a heuristic based on the compressibility.
|
|
2397
|
+
* It may return both false positives and false negatives.
|
|
2398
|
+
*/
|
|
2399
|
+
static int ZSTD_maybeRLE(seqStore_t const* seqStore)
|
|
2400
|
+
{
|
|
2401
|
+
size_t const nbSeqs = (size_t)(seqStore->sequences - seqStore->sequencesStart);
|
|
2402
|
+
size_t const nbLits = (size_t)(seqStore->lit - seqStore->litStart);
|
|
2403
|
+
|
|
2404
|
+
return nbSeqs < 4 && nbLits < 10;
|
|
2405
|
+
}
|
|
2406
|
+
|
|
2407
|
+
static void ZSTD_confirmRepcodesAndEntropyTables(ZSTD_CCtx* zc)
|
|
2408
|
+
{
|
|
2409
|
+
ZSTD_compressedBlockState_t* const tmp = zc->blockState.prevCBlock;
|
|
2410
|
+
zc->blockState.prevCBlock = zc->blockState.nextCBlock;
|
|
2411
|
+
zc->blockState.nextCBlock = tmp;
|
|
2412
|
+
}
|
|
2413
|
+
|
|
2414
|
+
static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
|
|
2415
|
+
void* dst, size_t dstCapacity,
|
|
2416
|
+
const void* src, size_t srcSize, U32 frame)
|
|
2417
|
+
{
|
|
2418
|
+
/* This the upper bound for the length of an rle block.
|
|
2419
|
+
* This isn't the actual upper bound. Finding the real threshold
|
|
2420
|
+
* needs further investigation.
|
|
2421
|
+
*/
|
|
2422
|
+
const U32 rleMaxLength = 25;
|
|
2423
|
+
size_t cSize;
|
|
2424
|
+
const BYTE* ip = (const BYTE*)src;
|
|
2425
|
+
BYTE* op = (BYTE*)dst;
|
|
2426
|
+
DEBUGLOG(5, "ZSTD_compressBlock_internal (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u)",
|
|
2427
|
+
(unsigned)dstCapacity, (unsigned)zc->blockState.matchState.window.dictLimit,
|
|
2428
|
+
(unsigned)zc->blockState.matchState.nextToUpdate);
|
|
2429
|
+
|
|
2430
|
+
{ const size_t bss = ZSTD_buildSeqStore(zc, src, srcSize);
|
|
2431
|
+
FORWARD_IF_ERROR(bss, "ZSTD_buildSeqStore failed");
|
|
2432
|
+
if (bss == ZSTDbss_noCompress) { cSize = 0; goto out; }
|
|
2433
|
+
}
|
|
2434
|
+
|
|
2435
|
+
if (zc->seqCollector.collectSequences) {
|
|
2436
|
+
ZSTD_copyBlockSequences(zc);
|
|
2437
|
+
return 0;
|
|
2438
|
+
}
|
|
2801
2439
|
|
|
2802
2440
|
/* encode sequences and literals */
|
|
2803
2441
|
cSize = ZSTD_compressSequences(&zc->seqStore,
|
|
@@ -2808,12 +2446,22 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
|
|
|
2808
2446
|
zc->entropyWorkspace, HUF_WORKSPACE_SIZE /* statically allocated in resetCCtx */,
|
|
2809
2447
|
zc->bmi2);
|
|
2810
2448
|
|
|
2449
|
+
if (frame &&
|
|
2450
|
+
/* We don't want to emit our first block as a RLE even if it qualifies because
|
|
2451
|
+
* doing so will cause the decoder (cli only) to throw a "should consume all input error."
|
|
2452
|
+
* This is only an issue for zstd <= v1.4.3
|
|
2453
|
+
*/
|
|
2454
|
+
!zc->isFirstBlock &&
|
|
2455
|
+
cSize < rleMaxLength &&
|
|
2456
|
+
ZSTD_isRLE(ip, srcSize))
|
|
2457
|
+
{
|
|
2458
|
+
cSize = 1;
|
|
2459
|
+
op[0] = ip[0];
|
|
2460
|
+
}
|
|
2461
|
+
|
|
2811
2462
|
out:
|
|
2812
|
-
if (!ZSTD_isError(cSize) && cSize
|
|
2813
|
-
|
|
2814
|
-
ZSTD_compressedBlockState_t* const tmp = zc->blockState.prevCBlock;
|
|
2815
|
-
zc->blockState.prevCBlock = zc->blockState.nextCBlock;
|
|
2816
|
-
zc->blockState.nextCBlock = tmp;
|
|
2463
|
+
if (!ZSTD_isError(cSize) && cSize > 1) {
|
|
2464
|
+
ZSTD_confirmRepcodesAndEntropyTables(zc);
|
|
2817
2465
|
}
|
|
2818
2466
|
/* We check that dictionaries have offset codes available for the first
|
|
2819
2467
|
* block. After the first block, the offcode table might not have large
|
|
@@ -2825,6 +2473,104 @@ out:
|
|
|
2825
2473
|
return cSize;
|
|
2826
2474
|
}
|
|
2827
2475
|
|
|
2476
|
+
static size_t ZSTD_compressBlock_targetCBlockSize_body(ZSTD_CCtx* zc,
|
|
2477
|
+
void* dst, size_t dstCapacity,
|
|
2478
|
+
const void* src, size_t srcSize,
|
|
2479
|
+
const size_t bss, U32 lastBlock)
|
|
2480
|
+
{
|
|
2481
|
+
DEBUGLOG(6, "Attempting ZSTD_compressSuperBlock()");
|
|
2482
|
+
if (bss == ZSTDbss_compress) {
|
|
2483
|
+
if (/* We don't want to emit our first block as a RLE even if it qualifies because
|
|
2484
|
+
* doing so will cause the decoder (cli only) to throw a "should consume all input error."
|
|
2485
|
+
* This is only an issue for zstd <= v1.4.3
|
|
2486
|
+
*/
|
|
2487
|
+
!zc->isFirstBlock &&
|
|
2488
|
+
ZSTD_maybeRLE(&zc->seqStore) &&
|
|
2489
|
+
ZSTD_isRLE((BYTE const*)src, srcSize))
|
|
2490
|
+
{
|
|
2491
|
+
return ZSTD_rleCompressBlock(dst, dstCapacity, *(BYTE const*)src, srcSize, lastBlock);
|
|
2492
|
+
}
|
|
2493
|
+
/* Attempt superblock compression.
|
|
2494
|
+
*
|
|
2495
|
+
* Note that compressed size of ZSTD_compressSuperBlock() is not bound by the
|
|
2496
|
+
* standard ZSTD_compressBound(). This is a problem, because even if we have
|
|
2497
|
+
* space now, taking an extra byte now could cause us to run out of space later
|
|
2498
|
+
* and violate ZSTD_compressBound().
|
|
2499
|
+
*
|
|
2500
|
+
* Define blockBound(blockSize) = blockSize + ZSTD_blockHeaderSize.
|
|
2501
|
+
*
|
|
2502
|
+
* In order to respect ZSTD_compressBound() we must attempt to emit a raw
|
|
2503
|
+
* uncompressed block in these cases:
|
|
2504
|
+
* * cSize == 0: Return code for an uncompressed block.
|
|
2505
|
+
* * cSize == dstSize_tooSmall: We may have expanded beyond blockBound(srcSize).
|
|
2506
|
+
* ZSTD_noCompressBlock() will return dstSize_tooSmall if we are really out of
|
|
2507
|
+
* output space.
|
|
2508
|
+
* * cSize >= blockBound(srcSize): We have expanded the block too much so
|
|
2509
|
+
* emit an uncompressed block.
|
|
2510
|
+
*/
|
|
2511
|
+
{
|
|
2512
|
+
size_t const cSize = ZSTD_compressSuperBlock(zc, dst, dstCapacity, src, srcSize, lastBlock);
|
|
2513
|
+
if (cSize != ERROR(dstSize_tooSmall)) {
|
|
2514
|
+
size_t const maxCSize = srcSize - ZSTD_minGain(srcSize, zc->appliedParams.cParams.strategy);
|
|
2515
|
+
FORWARD_IF_ERROR(cSize, "ZSTD_compressSuperBlock failed");
|
|
2516
|
+
if (cSize != 0 && cSize < maxCSize + ZSTD_blockHeaderSize) {
|
|
2517
|
+
ZSTD_confirmRepcodesAndEntropyTables(zc);
|
|
2518
|
+
return cSize;
|
|
2519
|
+
}
|
|
2520
|
+
}
|
|
2521
|
+
}
|
|
2522
|
+
}
|
|
2523
|
+
|
|
2524
|
+
DEBUGLOG(6, "Resorting to ZSTD_noCompressBlock()");
|
|
2525
|
+
/* Superblock compression failed, attempt to emit a single no compress block.
|
|
2526
|
+
* The decoder will be able to stream this block since it is uncompressed.
|
|
2527
|
+
*/
|
|
2528
|
+
return ZSTD_noCompressBlock(dst, dstCapacity, src, srcSize, lastBlock);
|
|
2529
|
+
}
|
|
2530
|
+
|
|
2531
|
+
static size_t ZSTD_compressBlock_targetCBlockSize(ZSTD_CCtx* zc,
|
|
2532
|
+
void* dst, size_t dstCapacity,
|
|
2533
|
+
const void* src, size_t srcSize,
|
|
2534
|
+
U32 lastBlock)
|
|
2535
|
+
{
|
|
2536
|
+
size_t cSize = 0;
|
|
2537
|
+
const size_t bss = ZSTD_buildSeqStore(zc, src, srcSize);
|
|
2538
|
+
DEBUGLOG(5, "ZSTD_compressBlock_targetCBlockSize (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u, srcSize=%zu)",
|
|
2539
|
+
(unsigned)dstCapacity, (unsigned)zc->blockState.matchState.window.dictLimit, (unsigned)zc->blockState.matchState.nextToUpdate, srcSize);
|
|
2540
|
+
FORWARD_IF_ERROR(bss, "ZSTD_buildSeqStore failed");
|
|
2541
|
+
|
|
2542
|
+
cSize = ZSTD_compressBlock_targetCBlockSize_body(zc, dst, dstCapacity, src, srcSize, bss, lastBlock);
|
|
2543
|
+
FORWARD_IF_ERROR(cSize, "ZSTD_compressBlock_targetCBlockSize_body failed");
|
|
2544
|
+
|
|
2545
|
+
if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid)
|
|
2546
|
+
zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check;
|
|
2547
|
+
|
|
2548
|
+
return cSize;
|
|
2549
|
+
}
|
|
2550
|
+
|
|
2551
|
+
static void ZSTD_overflowCorrectIfNeeded(ZSTD_matchState_t* ms,
|
|
2552
|
+
ZSTD_cwksp* ws,
|
|
2553
|
+
ZSTD_CCtx_params const* params,
|
|
2554
|
+
void const* ip,
|
|
2555
|
+
void const* iend)
|
|
2556
|
+
{
|
|
2557
|
+
if (ZSTD_window_needOverflowCorrection(ms->window, iend)) {
|
|
2558
|
+
U32 const maxDist = (U32)1 << params->cParams.windowLog;
|
|
2559
|
+
U32 const cycleLog = ZSTD_cycleLog(params->cParams.chainLog, params->cParams.strategy);
|
|
2560
|
+
U32 const correction = ZSTD_window_correctOverflow(&ms->window, cycleLog, maxDist, ip);
|
|
2561
|
+
ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30);
|
|
2562
|
+
ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30);
|
|
2563
|
+
ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31);
|
|
2564
|
+
ZSTD_cwksp_mark_tables_dirty(ws);
|
|
2565
|
+
ZSTD_reduceIndex(ms, params, correction);
|
|
2566
|
+
ZSTD_cwksp_mark_tables_clean(ws);
|
|
2567
|
+
if (ms->nextToUpdate < correction) ms->nextToUpdate = 0;
|
|
2568
|
+
else ms->nextToUpdate -= correction;
|
|
2569
|
+
/* invalidate dictionaries on overflow correction */
|
|
2570
|
+
ms->loadedDictEnd = 0;
|
|
2571
|
+
ms->dictMatchState = NULL;
|
|
2572
|
+
}
|
|
2573
|
+
}
|
|
2828
2574
|
|
|
2829
2575
|
/*! ZSTD_compress_frameChunk() :
|
|
2830
2576
|
* Compress a chunk of data into one or multiple blocks.
|
|
@@ -2844,7 +2590,8 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
|
|
|
2844
2590
|
BYTE* const ostart = (BYTE*)dst;
|
|
2845
2591
|
BYTE* op = ostart;
|
|
2846
2592
|
U32 const maxDist = (U32)1 << cctx->appliedParams.cParams.windowLog;
|
|
2847
|
-
|
|
2593
|
+
|
|
2594
|
+
assert(cctx->appliedParams.cParams.windowLog <= ZSTD_WINDOWLOG_MAX);
|
|
2848
2595
|
|
|
2849
2596
|
DEBUGLOG(5, "ZSTD_compress_frameChunk (blockSize=%u)", (unsigned)blockSize);
|
|
2850
2597
|
if (cctx->appliedParams.fParams.checksumFlag && srcSize)
|
|
@@ -2859,70 +2606,75 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
|
|
|
2859
2606
|
"not enough space to store compressed block");
|
|
2860
2607
|
if (remaining < blockSize) blockSize = remaining;
|
|
2861
2608
|
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30);
|
|
2866
|
-
ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30);
|
|
2867
|
-
ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31);
|
|
2868
|
-
ZSTD_reduceIndex(cctx, correction);
|
|
2869
|
-
if (ms->nextToUpdate < correction) ms->nextToUpdate = 0;
|
|
2870
|
-
else ms->nextToUpdate -= correction;
|
|
2871
|
-
ms->loadedDictEnd = 0;
|
|
2872
|
-
ms->dictMatchState = NULL;
|
|
2873
|
-
}
|
|
2874
|
-
ZSTD_window_enforceMaxDist(&ms->window, ip + blockSize, maxDist, &ms->loadedDictEnd, &ms->dictMatchState);
|
|
2875
|
-
if (ms->nextToUpdate < ms->window.lowLimit) ms->nextToUpdate = ms->window.lowLimit;
|
|
2609
|
+
ZSTD_overflowCorrectIfNeeded(
|
|
2610
|
+
ms, &cctx->workspace, &cctx->appliedParams, ip, ip + blockSize);
|
|
2611
|
+
ZSTD_checkDictValidity(&ms->window, ip + blockSize, maxDist, &ms->loadedDictEnd, &ms->dictMatchState);
|
|
2876
2612
|
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
ip, blockSize);
|
|
2880
|
-
FORWARD_IF_ERROR(cSize);
|
|
2613
|
+
/* Ensure hash/chain table insertion resumes no sooner than lowlimit */
|
|
2614
|
+
if (ms->nextToUpdate < ms->window.lowLimit) ms->nextToUpdate = ms->window.lowLimit;
|
|
2881
2615
|
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2616
|
+
{ size_t cSize;
|
|
2617
|
+
if (ZSTD_useTargetCBlockSize(&cctx->appliedParams)) {
|
|
2618
|
+
cSize = ZSTD_compressBlock_targetCBlockSize(cctx, op, dstCapacity, ip, blockSize, lastBlock);
|
|
2619
|
+
FORWARD_IF_ERROR(cSize, "ZSTD_compressBlock_targetCBlockSize failed");
|
|
2620
|
+
assert(cSize > 0);
|
|
2621
|
+
assert(cSize <= blockSize + ZSTD_blockHeaderSize);
|
|
2885
2622
|
} else {
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2623
|
+
cSize = ZSTD_compressBlock_internal(cctx,
|
|
2624
|
+
op+ZSTD_blockHeaderSize, dstCapacity-ZSTD_blockHeaderSize,
|
|
2625
|
+
ip, blockSize, 1 /* frame */);
|
|
2626
|
+
FORWARD_IF_ERROR(cSize, "ZSTD_compressBlock_internal failed");
|
|
2627
|
+
|
|
2628
|
+
if (cSize == 0) { /* block is not compressible */
|
|
2629
|
+
cSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock);
|
|
2630
|
+
FORWARD_IF_ERROR(cSize, "ZSTD_noCompressBlock failed");
|
|
2631
|
+
} else {
|
|
2632
|
+
U32 const cBlockHeader = cSize == 1 ?
|
|
2633
|
+
lastBlock + (((U32)bt_rle)<<1) + (U32)(blockSize << 3) :
|
|
2634
|
+
lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3);
|
|
2635
|
+
MEM_writeLE24(op, cBlockHeader);
|
|
2636
|
+
cSize += ZSTD_blockHeaderSize;
|
|
2637
|
+
}
|
|
2889
2638
|
}
|
|
2890
2639
|
|
|
2640
|
+
|
|
2891
2641
|
ip += blockSize;
|
|
2892
2642
|
assert(remaining >= blockSize);
|
|
2893
2643
|
remaining -= blockSize;
|
|
2894
2644
|
op += cSize;
|
|
2895
2645
|
assert(dstCapacity >= cSize);
|
|
2896
2646
|
dstCapacity -= cSize;
|
|
2647
|
+
cctx->isFirstBlock = 0;
|
|
2897
2648
|
DEBUGLOG(5, "ZSTD_compress_frameChunk: adding a block of size %u",
|
|
2898
2649
|
(unsigned)cSize);
|
|
2899
2650
|
} }
|
|
2900
2651
|
|
|
2901
2652
|
if (lastFrameChunk && (op>ostart)) cctx->stage = ZSTDcs_ending;
|
|
2902
|
-
return op-ostart;
|
|
2653
|
+
return (size_t)(op-ostart);
|
|
2903
2654
|
}
|
|
2904
2655
|
|
|
2905
2656
|
|
|
2906
2657
|
static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
|
|
2907
|
-
ZSTD_CCtx_params params, U64 pledgedSrcSize, U32 dictID)
|
|
2658
|
+
const ZSTD_CCtx_params* params, U64 pledgedSrcSize, U32 dictID)
|
|
2908
2659
|
{ BYTE* const op = (BYTE*)dst;
|
|
2909
2660
|
U32 const dictIDSizeCodeLength = (dictID>0) + (dictID>=256) + (dictID>=65536); /* 0-3 */
|
|
2910
|
-
U32 const dictIDSizeCode = params
|
|
2911
|
-
U32 const checksumFlag = params
|
|
2912
|
-
U32 const windowSize = (U32)1 << params
|
|
2913
|
-
U32 const singleSegment = params
|
|
2914
|
-
BYTE const windowLogByte = (BYTE)((params
|
|
2915
|
-
U32 const fcsCode = params
|
|
2661
|
+
U32 const dictIDSizeCode = params->fParams.noDictIDFlag ? 0 : dictIDSizeCodeLength; /* 0-3 */
|
|
2662
|
+
U32 const checksumFlag = params->fParams.checksumFlag>0;
|
|
2663
|
+
U32 const windowSize = (U32)1 << params->cParams.windowLog;
|
|
2664
|
+
U32 const singleSegment = params->fParams.contentSizeFlag && (windowSize >= pledgedSrcSize);
|
|
2665
|
+
BYTE const windowLogByte = (BYTE)((params->cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3);
|
|
2666
|
+
U32 const fcsCode = params->fParams.contentSizeFlag ?
|
|
2916
2667
|
(pledgedSrcSize>=256) + (pledgedSrcSize>=65536+256) + (pledgedSrcSize>=0xFFFFFFFFU) : 0; /* 0-3 */
|
|
2917
2668
|
BYTE const frameHeaderDescriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag<<2) + (singleSegment<<5) + (fcsCode<<6) );
|
|
2918
2669
|
size_t pos=0;
|
|
2919
2670
|
|
|
2920
|
-
assert(!(params
|
|
2921
|
-
RETURN_ERROR_IF(dstCapacity < ZSTD_FRAMEHEADERSIZE_MAX, dstSize_tooSmall
|
|
2671
|
+
assert(!(params->fParams.contentSizeFlag && pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN));
|
|
2672
|
+
RETURN_ERROR_IF(dstCapacity < ZSTD_FRAMEHEADERSIZE_MAX, dstSize_tooSmall,
|
|
2673
|
+
"dst buf is too small to fit worst-case frame header size.");
|
|
2922
2674
|
DEBUGLOG(4, "ZSTD_writeFrameHeader : dictIDFlag : %u ; dictID : %u ; dictIDSizeCode : %u",
|
|
2923
|
-
!params
|
|
2675
|
+
!params->fParams.noDictIDFlag, (unsigned)dictID, (unsigned)dictIDSizeCode);
|
|
2924
2676
|
|
|
2925
|
-
if (params
|
|
2677
|
+
if (params->format == ZSTD_f_zstd1) {
|
|
2926
2678
|
MEM_writeLE32(dst, ZSTD_MAGICNUMBER);
|
|
2927
2679
|
pos = 4;
|
|
2928
2680
|
}
|
|
@@ -2954,7 +2706,8 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
|
|
|
2954
2706
|
*/
|
|
2955
2707
|
size_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity)
|
|
2956
2708
|
{
|
|
2957
|
-
RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize, dstSize_tooSmall
|
|
2709
|
+
RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize, dstSize_tooSmall,
|
|
2710
|
+
"dst buf is too small to write frame trailer empty block.");
|
|
2958
2711
|
{ U32 const cBlockHeader24 = 1 /*lastBlock*/ + (((U32)bt_raw)<<1); /* 0 size */
|
|
2959
2712
|
MEM_writeLE24(dst, cBlockHeader24);
|
|
2960
2713
|
return ZSTD_blockHeaderSize;
|
|
@@ -2963,9 +2716,11 @@ size_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity)
|
|
|
2963
2716
|
|
|
2964
2717
|
size_t ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSeq)
|
|
2965
2718
|
{
|
|
2966
|
-
RETURN_ERROR_IF(cctx->stage != ZSTDcs_init, stage_wrong
|
|
2719
|
+
RETURN_ERROR_IF(cctx->stage != ZSTDcs_init, stage_wrong,
|
|
2720
|
+
"wrong cctx stage");
|
|
2967
2721
|
RETURN_ERROR_IF(cctx->appliedParams.ldmParams.enableLdm,
|
|
2968
|
-
parameter_unsupported
|
|
2722
|
+
parameter_unsupported,
|
|
2723
|
+
"incompatible with ldm");
|
|
2969
2724
|
cctx->externSeqStore.seq = seq;
|
|
2970
2725
|
cctx->externSeqStore.size = nbSeq;
|
|
2971
2726
|
cctx->externSeqStore.capacity = nbSeq;
|
|
@@ -2988,9 +2743,10 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
|
|
|
2988
2743
|
"missing init (ZSTD_compressBegin)");
|
|
2989
2744
|
|
|
2990
2745
|
if (frame && (cctx->stage==ZSTDcs_init)) {
|
|
2991
|
-
fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, cctx->appliedParams,
|
|
2746
|
+
fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, &cctx->appliedParams,
|
|
2992
2747
|
cctx->pledgedSrcSizePlusOne-1, cctx->dictID);
|
|
2993
|
-
FORWARD_IF_ERROR(fhSize);
|
|
2748
|
+
FORWARD_IF_ERROR(fhSize, "ZSTD_writeFrameHeader failed");
|
|
2749
|
+
assert(fhSize <= dstCapacity);
|
|
2994
2750
|
dstCapacity -= fhSize;
|
|
2995
2751
|
dst = (char*)dst + fhSize;
|
|
2996
2752
|
cctx->stage = ZSTDcs_ongoing;
|
|
@@ -3007,25 +2763,16 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
|
|
|
3007
2763
|
|
|
3008
2764
|
if (!frame) {
|
|
3009
2765
|
/* overflow check and correction for block mode */
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30);
|
|
3014
|
-
ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30);
|
|
3015
|
-
ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31);
|
|
3016
|
-
ZSTD_reduceIndex(cctx, correction);
|
|
3017
|
-
if (ms->nextToUpdate < correction) ms->nextToUpdate = 0;
|
|
3018
|
-
else ms->nextToUpdate -= correction;
|
|
3019
|
-
ms->loadedDictEnd = 0;
|
|
3020
|
-
ms->dictMatchState = NULL;
|
|
3021
|
-
}
|
|
2766
|
+
ZSTD_overflowCorrectIfNeeded(
|
|
2767
|
+
ms, &cctx->workspace, &cctx->appliedParams,
|
|
2768
|
+
src, (BYTE const*)src + srcSize);
|
|
3022
2769
|
}
|
|
3023
2770
|
|
|
3024
2771
|
DEBUGLOG(5, "ZSTD_compressContinue_internal (blockSize=%u)", (unsigned)cctx->blockSize);
|
|
3025
2772
|
{ size_t const cSize = frame ?
|
|
3026
2773
|
ZSTD_compress_frameChunk (cctx, dst, dstCapacity, src, srcSize, lastFrameChunk) :
|
|
3027
|
-
ZSTD_compressBlock_internal (cctx, dst, dstCapacity, src, srcSize);
|
|
3028
|
-
FORWARD_IF_ERROR(cSize);
|
|
2774
|
+
ZSTD_compressBlock_internal (cctx, dst, dstCapacity, src, srcSize, 0 /* frame */);
|
|
2775
|
+
FORWARD_IF_ERROR(cSize, "%s", frame ? "ZSTD_compress_frameChunk failed" : "ZSTD_compressBlock_internal failed");
|
|
3029
2776
|
cctx->consumedSrcSize += srcSize;
|
|
3030
2777
|
cctx->producedCSize += (cSize + fhSize);
|
|
3031
2778
|
assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0));
|
|
@@ -3060,8 +2807,9 @@ size_t ZSTD_getBlockSize(const ZSTD_CCtx* cctx)
|
|
|
3060
2807
|
|
|
3061
2808
|
size_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
|
|
3062
2809
|
{
|
|
3063
|
-
|
|
3064
|
-
|
|
2810
|
+
DEBUGLOG(5, "ZSTD_compressBlock: srcSize = %u", (unsigned)srcSize);
|
|
2811
|
+
{ size_t const blockSizeMax = ZSTD_getBlockSize(cctx);
|
|
2812
|
+
RETURN_ERROR_IF(srcSize > blockSizeMax, srcSize_wrong, "input is larger than a block"); }
|
|
3065
2813
|
|
|
3066
2814
|
return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 0 /* frame mode */, 0 /* last chunk */);
|
|
3067
2815
|
}
|
|
@@ -3070,47 +2818,67 @@ size_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const
|
|
|
3070
2818
|
* @return : 0, or an error code
|
|
3071
2819
|
*/
|
|
3072
2820
|
static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms,
|
|
2821
|
+
ldmState_t* ls,
|
|
2822
|
+
ZSTD_cwksp* ws,
|
|
3073
2823
|
ZSTD_CCtx_params const* params,
|
|
3074
2824
|
const void* src, size_t srcSize,
|
|
3075
2825
|
ZSTD_dictTableLoadMethod_e dtlm)
|
|
3076
2826
|
{
|
|
3077
|
-
const BYTE*
|
|
2827
|
+
const BYTE* ip = (const BYTE*) src;
|
|
3078
2828
|
const BYTE* const iend = ip + srcSize;
|
|
3079
2829
|
|
|
3080
2830
|
ZSTD_window_update(&ms->window, src, srcSize);
|
|
3081
2831
|
ms->loadedDictEnd = params->forceWindow ? 0 : (U32)(iend - ms->window.base);
|
|
3082
2832
|
|
|
2833
|
+
if (params->ldmParams.enableLdm && ls != NULL) {
|
|
2834
|
+
ZSTD_window_update(&ls->window, src, srcSize);
|
|
2835
|
+
ls->loadedDictEnd = params->forceWindow ? 0 : (U32)(iend - ls->window.base);
|
|
2836
|
+
}
|
|
2837
|
+
|
|
3083
2838
|
/* Assert that we the ms params match the params we're being given */
|
|
3084
2839
|
ZSTD_assertEqualCParams(params->cParams, ms->cParams);
|
|
3085
2840
|
|
|
3086
2841
|
if (srcSize <= HASH_READ_SIZE) return 0;
|
|
3087
2842
|
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
break;
|
|
3093
|
-
case ZSTD_dfast:
|
|
3094
|
-
ZSTD_fillDoubleHashTable(ms, iend, dtlm);
|
|
3095
|
-
break;
|
|
2843
|
+
while (iend - ip > HASH_READ_SIZE) {
|
|
2844
|
+
size_t const remaining = (size_t)(iend - ip);
|
|
2845
|
+
size_t const chunk = MIN(remaining, ZSTD_CHUNKSIZE_MAX);
|
|
2846
|
+
const BYTE* const ichunk = ip + chunk;
|
|
3096
2847
|
|
|
3097
|
-
|
|
3098
|
-
case ZSTD_lazy:
|
|
3099
|
-
case ZSTD_lazy2:
|
|
3100
|
-
if (srcSize >= HASH_READ_SIZE)
|
|
3101
|
-
ZSTD_insertAndFindFirstIndex(ms, iend-HASH_READ_SIZE);
|
|
3102
|
-
break;
|
|
2848
|
+
ZSTD_overflowCorrectIfNeeded(ms, ws, params, ip, ichunk);
|
|
3103
2849
|
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
case ZSTD_btultra:
|
|
3107
|
-
case ZSTD_btultra2:
|
|
3108
|
-
if (srcSize >= HASH_READ_SIZE)
|
|
3109
|
-
ZSTD_updateTree(ms, iend-HASH_READ_SIZE, iend);
|
|
3110
|
-
break;
|
|
2850
|
+
if (params->ldmParams.enableLdm && ls != NULL)
|
|
2851
|
+
ZSTD_ldm_fillHashTable(ls, (const BYTE*)src, (const BYTE*)src + srcSize, ¶ms->ldmParams);
|
|
3111
2852
|
|
|
3112
|
-
|
|
3113
|
-
|
|
2853
|
+
switch(params->cParams.strategy)
|
|
2854
|
+
{
|
|
2855
|
+
case ZSTD_fast:
|
|
2856
|
+
ZSTD_fillHashTable(ms, ichunk, dtlm);
|
|
2857
|
+
break;
|
|
2858
|
+
case ZSTD_dfast:
|
|
2859
|
+
ZSTD_fillDoubleHashTable(ms, ichunk, dtlm);
|
|
2860
|
+
break;
|
|
2861
|
+
|
|
2862
|
+
case ZSTD_greedy:
|
|
2863
|
+
case ZSTD_lazy:
|
|
2864
|
+
case ZSTD_lazy2:
|
|
2865
|
+
if (chunk >= HASH_READ_SIZE)
|
|
2866
|
+
ZSTD_insertAndFindFirstIndex(ms, ichunk-HASH_READ_SIZE);
|
|
2867
|
+
break;
|
|
2868
|
+
|
|
2869
|
+
case ZSTD_btlazy2: /* we want the dictionary table fully sorted */
|
|
2870
|
+
case ZSTD_btopt:
|
|
2871
|
+
case ZSTD_btultra:
|
|
2872
|
+
case ZSTD_btultra2:
|
|
2873
|
+
if (chunk >= HASH_READ_SIZE)
|
|
2874
|
+
ZSTD_updateTree(ms, ichunk-HASH_READ_SIZE, ichunk);
|
|
2875
|
+
break;
|
|
2876
|
+
|
|
2877
|
+
default:
|
|
2878
|
+
assert(0); /* not possible : not a valid strategy id */
|
|
2879
|
+
}
|
|
2880
|
+
|
|
2881
|
+
ip = ichunk;
|
|
3114
2882
|
}
|
|
3115
2883
|
|
|
3116
2884
|
ms->nextToUpdate = (U32)(iend - ms->window.base);
|
|
@@ -3124,101 +2892,123 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms,
|
|
|
3124
2892
|
NOTE: This behavior is not standard and could be improved in the future. */
|
|
3125
2893
|
static size_t ZSTD_checkDictNCount(short* normalizedCounter, unsigned dictMaxSymbolValue, unsigned maxSymbolValue) {
|
|
3126
2894
|
U32 s;
|
|
3127
|
-
RETURN_ERROR_IF(dictMaxSymbolValue < maxSymbolValue, dictionary_corrupted);
|
|
2895
|
+
RETURN_ERROR_IF(dictMaxSymbolValue < maxSymbolValue, dictionary_corrupted, "dict fse tables don't have all symbols");
|
|
3128
2896
|
for (s = 0; s <= maxSymbolValue; ++s) {
|
|
3129
|
-
RETURN_ERROR_IF(normalizedCounter[s] == 0, dictionary_corrupted);
|
|
2897
|
+
RETURN_ERROR_IF(normalizedCounter[s] == 0, dictionary_corrupted, "dict fse tables don't have all symbols");
|
|
3130
2898
|
}
|
|
3131
2899
|
return 0;
|
|
3132
2900
|
}
|
|
3133
2901
|
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
*
|
|
3137
|
-
* https://github.com/facebook/zstd/blob/master/doc/zstd_compression_format.md#dictionary-format
|
|
3138
|
-
*/
|
|
3139
|
-
/*! ZSTD_loadZstdDictionary() :
|
|
3140
|
-
* @return : dictID, or an error code
|
|
3141
|
-
* assumptions : magic number supposed already checked
|
|
3142
|
-
* dictSize supposed > 8
|
|
3143
|
-
*/
|
|
3144
|
-
static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs,
|
|
3145
|
-
ZSTD_matchState_t* ms,
|
|
3146
|
-
ZSTD_CCtx_params const* params,
|
|
3147
|
-
const void* dict, size_t dictSize,
|
|
3148
|
-
ZSTD_dictTableLoadMethod_e dtlm,
|
|
3149
|
-
void* workspace)
|
|
2902
|
+
size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace,
|
|
2903
|
+
short* offcodeNCount, unsigned* offcodeMaxValue,
|
|
2904
|
+
const void* const dict, size_t dictSize)
|
|
3150
2905
|
{
|
|
3151
|
-
const BYTE* dictPtr = (const BYTE*)dict;
|
|
2906
|
+
const BYTE* dictPtr = (const BYTE*)dict; /* skip magic num and dict ID */
|
|
3152
2907
|
const BYTE* const dictEnd = dictPtr + dictSize;
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
size_t dictID;
|
|
2908
|
+
dictPtr += 8;
|
|
2909
|
+
bs->entropy.huf.repeatMode = HUF_repeat_check;
|
|
3156
2910
|
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
2911
|
+
{ unsigned maxSymbolValue = 255;
|
|
2912
|
+
unsigned hasZeroWeights = 1;
|
|
2913
|
+
size_t const hufHeaderSize = HUF_readCTable((HUF_CElt*)bs->entropy.huf.CTable, &maxSymbolValue, dictPtr,
|
|
2914
|
+
dictEnd-dictPtr, &hasZeroWeights);
|
|
3160
2915
|
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
2916
|
+
/* We only set the loaded table as valid if it contains all non-zero
|
|
2917
|
+
* weights. Otherwise, we set it to check */
|
|
2918
|
+
if (!hasZeroWeights)
|
|
2919
|
+
bs->entropy.huf.repeatMode = HUF_repeat_valid;
|
|
3164
2920
|
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
RETURN_ERROR_IF(HUF_isError(hufHeaderSize), dictionary_corrupted);
|
|
3168
|
-
RETURN_ERROR_IF(maxSymbolValue < 255, dictionary_corrupted);
|
|
2921
|
+
RETURN_ERROR_IF(HUF_isError(hufHeaderSize), dictionary_corrupted, "");
|
|
2922
|
+
RETURN_ERROR_IF(maxSymbolValue < 255, dictionary_corrupted, "");
|
|
3169
2923
|
dictPtr += hufHeaderSize;
|
|
3170
2924
|
}
|
|
3171
2925
|
|
|
3172
2926
|
{ unsigned offcodeLog;
|
|
3173
|
-
size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount,
|
|
3174
|
-
RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted);
|
|
3175
|
-
RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted);
|
|
2927
|
+
size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
|
|
2928
|
+
RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted, "");
|
|
2929
|
+
RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted, "");
|
|
3176
2930
|
/* Defer checking offcodeMaxValue because we need to know the size of the dictionary content */
|
|
3177
2931
|
/* fill all offset symbols to avoid garbage at end of table */
|
|
3178
2932
|
RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(
|
|
3179
2933
|
bs->entropy.fse.offcodeCTable,
|
|
3180
2934
|
offcodeNCount, MaxOff, offcodeLog,
|
|
3181
2935
|
workspace, HUF_WORKSPACE_SIZE)),
|
|
3182
|
-
dictionary_corrupted);
|
|
2936
|
+
dictionary_corrupted, "");
|
|
3183
2937
|
dictPtr += offcodeHeaderSize;
|
|
3184
2938
|
}
|
|
3185
2939
|
|
|
3186
2940
|
{ short matchlengthNCount[MaxML+1];
|
|
3187
2941
|
unsigned matchlengthMaxValue = MaxML, matchlengthLog;
|
|
3188
2942
|
size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
|
|
3189
|
-
RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted);
|
|
3190
|
-
RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted);
|
|
2943
|
+
RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted, "");
|
|
2944
|
+
RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted, "");
|
|
3191
2945
|
/* Every match length code must have non-zero probability */
|
|
3192
|
-
FORWARD_IF_ERROR( ZSTD_checkDictNCount(matchlengthNCount, matchlengthMaxValue, MaxML));
|
|
2946
|
+
FORWARD_IF_ERROR( ZSTD_checkDictNCount(matchlengthNCount, matchlengthMaxValue, MaxML), "");
|
|
3193
2947
|
RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(
|
|
3194
2948
|
bs->entropy.fse.matchlengthCTable,
|
|
3195
2949
|
matchlengthNCount, matchlengthMaxValue, matchlengthLog,
|
|
3196
2950
|
workspace, HUF_WORKSPACE_SIZE)),
|
|
3197
|
-
dictionary_corrupted);
|
|
2951
|
+
dictionary_corrupted, "");
|
|
3198
2952
|
dictPtr += matchlengthHeaderSize;
|
|
3199
2953
|
}
|
|
3200
2954
|
|
|
3201
2955
|
{ short litlengthNCount[MaxLL+1];
|
|
3202
2956
|
unsigned litlengthMaxValue = MaxLL, litlengthLog;
|
|
3203
2957
|
size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
|
|
3204
|
-
RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted);
|
|
3205
|
-
RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted);
|
|
2958
|
+
RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted, "");
|
|
2959
|
+
RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted, "");
|
|
3206
2960
|
/* Every literal length code must have non-zero probability */
|
|
3207
|
-
FORWARD_IF_ERROR( ZSTD_checkDictNCount(litlengthNCount, litlengthMaxValue, MaxLL));
|
|
2961
|
+
FORWARD_IF_ERROR( ZSTD_checkDictNCount(litlengthNCount, litlengthMaxValue, MaxLL), "");
|
|
3208
2962
|
RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(
|
|
3209
2963
|
bs->entropy.fse.litlengthCTable,
|
|
3210
2964
|
litlengthNCount, litlengthMaxValue, litlengthLog,
|
|
3211
2965
|
workspace, HUF_WORKSPACE_SIZE)),
|
|
3212
|
-
dictionary_corrupted);
|
|
2966
|
+
dictionary_corrupted, "");
|
|
3213
2967
|
dictPtr += litlengthHeaderSize;
|
|
3214
2968
|
}
|
|
3215
2969
|
|
|
3216
|
-
RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted);
|
|
2970
|
+
RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted, "");
|
|
3217
2971
|
bs->rep[0] = MEM_readLE32(dictPtr+0);
|
|
3218
2972
|
bs->rep[1] = MEM_readLE32(dictPtr+4);
|
|
3219
2973
|
bs->rep[2] = MEM_readLE32(dictPtr+8);
|
|
3220
2974
|
dictPtr += 12;
|
|
3221
2975
|
|
|
2976
|
+
return dictPtr - (const BYTE*)dict;
|
|
2977
|
+
}
|
|
2978
|
+
|
|
2979
|
+
/* Dictionary format :
|
|
2980
|
+
* See :
|
|
2981
|
+
* https://github.com/facebook/zstd/blob/master/doc/zstd_compression_format.md#dictionary-format
|
|
2982
|
+
*/
|
|
2983
|
+
/*! ZSTD_loadZstdDictionary() :
|
|
2984
|
+
* @return : dictID, or an error code
|
|
2985
|
+
* assumptions : magic number supposed already checked
|
|
2986
|
+
* dictSize supposed >= 8
|
|
2987
|
+
*/
|
|
2988
|
+
static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs,
|
|
2989
|
+
ZSTD_matchState_t* ms,
|
|
2990
|
+
ZSTD_cwksp* ws,
|
|
2991
|
+
ZSTD_CCtx_params const* params,
|
|
2992
|
+
const void* dict, size_t dictSize,
|
|
2993
|
+
ZSTD_dictTableLoadMethod_e dtlm,
|
|
2994
|
+
void* workspace)
|
|
2995
|
+
{
|
|
2996
|
+
const BYTE* dictPtr = (const BYTE*)dict;
|
|
2997
|
+
const BYTE* const dictEnd = dictPtr + dictSize;
|
|
2998
|
+
short offcodeNCount[MaxOff+1];
|
|
2999
|
+
unsigned offcodeMaxValue = MaxOff;
|
|
3000
|
+
size_t dictID;
|
|
3001
|
+
size_t eSize;
|
|
3002
|
+
|
|
3003
|
+
ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<<MAX(MLFSELog,LLFSELog)));
|
|
3004
|
+
assert(dictSize >= 8);
|
|
3005
|
+
assert(MEM_readLE32(dictPtr) == ZSTD_MAGIC_DICTIONARY);
|
|
3006
|
+
|
|
3007
|
+
dictID = params->fParams.noDictIDFlag ? 0 : MEM_readLE32(dictPtr + 4 /* skip magic number */ );
|
|
3008
|
+
eSize = ZSTD_loadCEntropy(bs, workspace, offcodeNCount, &offcodeMaxValue, dict, dictSize);
|
|
3009
|
+
FORWARD_IF_ERROR(eSize, "ZSTD_loadCEntropy failed");
|
|
3010
|
+
dictPtr += eSize;
|
|
3011
|
+
|
|
3222
3012
|
{ size_t const dictContentSize = (size_t)(dictEnd - dictPtr);
|
|
3223
3013
|
U32 offcodeMax = MaxOff;
|
|
3224
3014
|
if (dictContentSize <= ((U32)-1) - 128 KB) {
|
|
@@ -3226,19 +3016,19 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs,
|
|
|
3226
3016
|
offcodeMax = ZSTD_highbit32(maxOffset); /* Calculate minimum offset code required to represent maxOffset */
|
|
3227
3017
|
}
|
|
3228
3018
|
/* All offset values <= dictContentSize + 128 KB must be representable */
|
|
3229
|
-
FORWARD_IF_ERROR(ZSTD_checkDictNCount(offcodeNCount, offcodeMaxValue, MIN(offcodeMax, MaxOff)));
|
|
3019
|
+
FORWARD_IF_ERROR(ZSTD_checkDictNCount(offcodeNCount, offcodeMaxValue, MIN(offcodeMax, MaxOff)), "");
|
|
3230
3020
|
/* All repCodes must be <= dictContentSize and != 0*/
|
|
3231
3021
|
{ U32 u;
|
|
3232
3022
|
for (u=0; u<3; u++) {
|
|
3233
|
-
RETURN_ERROR_IF(bs->rep[u] == 0, dictionary_corrupted);
|
|
3234
|
-
RETURN_ERROR_IF(bs->rep[u] > dictContentSize, dictionary_corrupted);
|
|
3023
|
+
RETURN_ERROR_IF(bs->rep[u] == 0, dictionary_corrupted, "");
|
|
3024
|
+
RETURN_ERROR_IF(bs->rep[u] > dictContentSize, dictionary_corrupted, "");
|
|
3235
3025
|
} }
|
|
3236
3026
|
|
|
3237
|
-
bs->entropy.huf.repeatMode = HUF_repeat_valid;
|
|
3238
3027
|
bs->entropy.fse.offcode_repeatMode = FSE_repeat_valid;
|
|
3239
3028
|
bs->entropy.fse.matchlength_repeatMode = FSE_repeat_valid;
|
|
3240
3029
|
bs->entropy.fse.litlength_repeatMode = FSE_repeat_valid;
|
|
3241
|
-
FORWARD_IF_ERROR(ZSTD_loadDictionaryContent(
|
|
3030
|
+
FORWARD_IF_ERROR(ZSTD_loadDictionaryContent(
|
|
3031
|
+
ms, NULL, ws, params, dictPtr, dictContentSize, dtlm), "");
|
|
3242
3032
|
return dictID;
|
|
3243
3033
|
}
|
|
3244
3034
|
}
|
|
@@ -3248,6 +3038,8 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs,
|
|
|
3248
3038
|
static size_t
|
|
3249
3039
|
ZSTD_compress_insertDictionary(ZSTD_compressedBlockState_t* bs,
|
|
3250
3040
|
ZSTD_matchState_t* ms,
|
|
3041
|
+
ldmState_t* ls,
|
|
3042
|
+
ZSTD_cwksp* ws,
|
|
3251
3043
|
const ZSTD_CCtx_params* params,
|
|
3252
3044
|
const void* dict, size_t dictSize,
|
|
3253
3045
|
ZSTD_dictContentType_e dictContentType,
|
|
@@ -3255,27 +3047,35 @@ ZSTD_compress_insertDictionary(ZSTD_compressedBlockState_t* bs,
|
|
|
3255
3047
|
void* workspace)
|
|
3256
3048
|
{
|
|
3257
3049
|
DEBUGLOG(4, "ZSTD_compress_insertDictionary (dictSize=%u)", (U32)dictSize);
|
|
3258
|
-
if ((dict==NULL) || (dictSize
|
|
3050
|
+
if ((dict==NULL) || (dictSize<8)) {
|
|
3051
|
+
RETURN_ERROR_IF(dictContentType == ZSTD_dct_fullDict, dictionary_wrong, "");
|
|
3052
|
+
return 0;
|
|
3053
|
+
}
|
|
3259
3054
|
|
|
3260
3055
|
ZSTD_reset_compressedBlockState(bs);
|
|
3261
3056
|
|
|
3262
3057
|
/* dict restricted modes */
|
|
3263
3058
|
if (dictContentType == ZSTD_dct_rawContent)
|
|
3264
|
-
return ZSTD_loadDictionaryContent(ms, params, dict, dictSize, dtlm);
|
|
3059
|
+
return ZSTD_loadDictionaryContent(ms, ls, ws, params, dict, dictSize, dtlm);
|
|
3265
3060
|
|
|
3266
3061
|
if (MEM_readLE32(dict) != ZSTD_MAGIC_DICTIONARY) {
|
|
3267
3062
|
if (dictContentType == ZSTD_dct_auto) {
|
|
3268
3063
|
DEBUGLOG(4, "raw content dictionary detected");
|
|
3269
|
-
return ZSTD_loadDictionaryContent(
|
|
3064
|
+
return ZSTD_loadDictionaryContent(
|
|
3065
|
+
ms, ls, ws, params, dict, dictSize, dtlm);
|
|
3270
3066
|
}
|
|
3271
|
-
RETURN_ERROR_IF(dictContentType == ZSTD_dct_fullDict, dictionary_wrong);
|
|
3067
|
+
RETURN_ERROR_IF(dictContentType == ZSTD_dct_fullDict, dictionary_wrong, "");
|
|
3272
3068
|
assert(0); /* impossible */
|
|
3273
3069
|
}
|
|
3274
3070
|
|
|
3275
3071
|
/* dict as full zstd dictionary */
|
|
3276
|
-
return ZSTD_loadZstdDictionary(
|
|
3072
|
+
return ZSTD_loadZstdDictionary(
|
|
3073
|
+
bs, ms, ws, params, dict, dictSize, dtlm, workspace);
|
|
3277
3074
|
}
|
|
3278
3075
|
|
|
3076
|
+
#define ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF (128 KB)
|
|
3077
|
+
#define ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER (6)
|
|
3078
|
+
|
|
3279
3079
|
/*! ZSTD_compressBegin_internal() :
|
|
3280
3080
|
* @return : 0, or an error code */
|
|
3281
3081
|
static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
|
|
@@ -3283,26 +3083,37 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
|
|
|
3283
3083
|
ZSTD_dictContentType_e dictContentType,
|
|
3284
3084
|
ZSTD_dictTableLoadMethod_e dtlm,
|
|
3285
3085
|
const ZSTD_CDict* cdict,
|
|
3286
|
-
ZSTD_CCtx_params params, U64 pledgedSrcSize,
|
|
3086
|
+
const ZSTD_CCtx_params* params, U64 pledgedSrcSize,
|
|
3287
3087
|
ZSTD_buffered_policy_e zbuff)
|
|
3288
3088
|
{
|
|
3289
|
-
DEBUGLOG(4, "ZSTD_compressBegin_internal: wlog=%u", params
|
|
3089
|
+
DEBUGLOG(4, "ZSTD_compressBegin_internal: wlog=%u", params->cParams.windowLog);
|
|
3290
3090
|
/* params are supposed to be fully validated at this point */
|
|
3291
|
-
assert(!ZSTD_isError(ZSTD_checkCParams(params
|
|
3091
|
+
assert(!ZSTD_isError(ZSTD_checkCParams(params->cParams)));
|
|
3292
3092
|
assert(!((dict) && (cdict))); /* either dict or cdict, not both */
|
|
3293
|
-
|
|
3294
|
-
|
|
3093
|
+
if ( (cdict)
|
|
3094
|
+
&& (cdict->dictContentSize > 0)
|
|
3095
|
+
&& ( pledgedSrcSize < ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF
|
|
3096
|
+
|| pledgedSrcSize < cdict->dictContentSize * ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER
|
|
3097
|
+
|| pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN
|
|
3098
|
+
|| cdict->compressionLevel == 0)
|
|
3099
|
+
&& (params->attachDictPref != ZSTD_dictForceLoad) ) {
|
|
3295
3100
|
return ZSTD_resetCCtx_usingCDict(cctx, cdict, params, pledgedSrcSize, zbuff);
|
|
3296
3101
|
}
|
|
3297
3102
|
|
|
3298
|
-
FORWARD_IF_ERROR( ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
|
|
3299
|
-
|
|
3300
|
-
{
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3103
|
+
FORWARD_IF_ERROR( ZSTD_resetCCtx_internal(cctx, *params, pledgedSrcSize,
|
|
3104
|
+
ZSTDcrp_makeClean, zbuff) , "");
|
|
3105
|
+
{ size_t const dictID = cdict ?
|
|
3106
|
+
ZSTD_compress_insertDictionary(
|
|
3107
|
+
cctx->blockState.prevCBlock, &cctx->blockState.matchState,
|
|
3108
|
+
&cctx->ldmState, &cctx->workspace, &cctx->appliedParams, cdict->dictContent,
|
|
3109
|
+
cdict->dictContentSize, dictContentType, dtlm,
|
|
3110
|
+
cctx->entropyWorkspace)
|
|
3111
|
+
: ZSTD_compress_insertDictionary(
|
|
3112
|
+
cctx->blockState.prevCBlock, &cctx->blockState.matchState,
|
|
3113
|
+
&cctx->ldmState, &cctx->workspace, &cctx->appliedParams, dict, dictSize,
|
|
3114
|
+
dictContentType, dtlm, cctx->entropyWorkspace);
|
|
3115
|
+
FORWARD_IF_ERROR(dictID, "ZSTD_compress_insertDictionary failed");
|
|
3116
|
+
assert(dictID <= UINT_MAX);
|
|
3306
3117
|
cctx->dictID = (U32)dictID;
|
|
3307
3118
|
}
|
|
3308
3119
|
return 0;
|
|
@@ -3313,12 +3124,12 @@ size_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx,
|
|
|
3313
3124
|
ZSTD_dictContentType_e dictContentType,
|
|
3314
3125
|
ZSTD_dictTableLoadMethod_e dtlm,
|
|
3315
3126
|
const ZSTD_CDict* cdict,
|
|
3316
|
-
ZSTD_CCtx_params params,
|
|
3127
|
+
const ZSTD_CCtx_params* params,
|
|
3317
3128
|
unsigned long long pledgedSrcSize)
|
|
3318
3129
|
{
|
|
3319
|
-
DEBUGLOG(4, "ZSTD_compressBegin_advanced_internal: wlog=%u", params
|
|
3130
|
+
DEBUGLOG(4, "ZSTD_compressBegin_advanced_internal: wlog=%u", params->cParams.windowLog);
|
|
3320
3131
|
/* compression parameters verification and optimization */
|
|
3321
|
-
FORWARD_IF_ERROR( ZSTD_checkCParams(params
|
|
3132
|
+
FORWARD_IF_ERROR( ZSTD_checkCParams(params->cParams) , "");
|
|
3322
3133
|
return ZSTD_compressBegin_internal(cctx,
|
|
3323
3134
|
dict, dictSize, dictContentType, dtlm,
|
|
3324
3135
|
cdict,
|
|
@@ -3333,21 +3144,21 @@ size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx,
|
|
|
3333
3144
|
ZSTD_parameters params, unsigned long long pledgedSrcSize)
|
|
3334
3145
|
{
|
|
3335
3146
|
ZSTD_CCtx_params const cctxParams =
|
|
3336
|
-
ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
|
|
3147
|
+
ZSTD_assignParamsToCCtxParams(&cctx->requestedParams, ¶ms);
|
|
3337
3148
|
return ZSTD_compressBegin_advanced_internal(cctx,
|
|
3338
3149
|
dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast,
|
|
3339
3150
|
NULL /*cdict*/,
|
|
3340
|
-
cctxParams, pledgedSrcSize);
|
|
3151
|
+
&cctxParams, pledgedSrcSize);
|
|
3341
3152
|
}
|
|
3342
3153
|
|
|
3343
3154
|
size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel)
|
|
3344
3155
|
{
|
|
3345
|
-
ZSTD_parameters const params =
|
|
3156
|
+
ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize);
|
|
3346
3157
|
ZSTD_CCtx_params const cctxParams =
|
|
3347
|
-
ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
|
|
3158
|
+
ZSTD_assignParamsToCCtxParams(&cctx->requestedParams, ¶ms);
|
|
3348
3159
|
DEBUGLOG(4, "ZSTD_compressBegin_usingDict (dictSize=%u)", (unsigned)dictSize);
|
|
3349
3160
|
return ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, NULL,
|
|
3350
|
-
cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, ZSTDb_not_buffered);
|
|
3161
|
+
&cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, ZSTDb_not_buffered);
|
|
3351
3162
|
}
|
|
3352
3163
|
|
|
3353
3164
|
size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel)
|
|
@@ -3370,8 +3181,8 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
|
|
|
3370
3181
|
|
|
3371
3182
|
/* special case : empty frame */
|
|
3372
3183
|
if (cctx->stage == ZSTDcs_init) {
|
|
3373
|
-
fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, cctx->appliedParams, 0, 0);
|
|
3374
|
-
FORWARD_IF_ERROR(fhSize);
|
|
3184
|
+
fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, &cctx->appliedParams, 0, 0);
|
|
3185
|
+
FORWARD_IF_ERROR(fhSize, "ZSTD_writeFrameHeader failed");
|
|
3375
3186
|
dstCapacity -= fhSize;
|
|
3376
3187
|
op += fhSize;
|
|
3377
3188
|
cctx->stage = ZSTDcs_ongoing;
|
|
@@ -3380,7 +3191,7 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
|
|
|
3380
3191
|
if (cctx->stage != ZSTDcs_ending) {
|
|
3381
3192
|
/* write one last empty block, make it the "last" block */
|
|
3382
3193
|
U32 const cBlockHeader24 = 1 /* last block */ + (((U32)bt_raw)<<1) + 0;
|
|
3383
|
-
RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall);
|
|
3194
|
+
RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, "no room for epilogue");
|
|
3384
3195
|
MEM_writeLE32(op, cBlockHeader24);
|
|
3385
3196
|
op += ZSTD_blockHeaderSize;
|
|
3386
3197
|
dstCapacity -= ZSTD_blockHeaderSize;
|
|
@@ -3388,7 +3199,7 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
|
|
|
3388
3199
|
|
|
3389
3200
|
if (cctx->appliedParams.fParams.checksumFlag) {
|
|
3390
3201
|
U32 const checksum = (U32) XXH64_digest(&cctx->xxhState);
|
|
3391
|
-
RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall);
|
|
3202
|
+
RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, "no room for checksum");
|
|
3392
3203
|
DEBUGLOG(4, "ZSTD_writeEpilogue: write checksum : %08X", (unsigned)checksum);
|
|
3393
3204
|
MEM_writeLE32(op, checksum);
|
|
3394
3205
|
op += 4;
|
|
@@ -3406,9 +3217,9 @@ size_t ZSTD_compressEnd (ZSTD_CCtx* cctx,
|
|
|
3406
3217
|
size_t const cSize = ZSTD_compressContinue_internal(cctx,
|
|
3407
3218
|
dst, dstCapacity, src, srcSize,
|
|
3408
3219
|
1 /* frame mode */, 1 /* last chunk */);
|
|
3409
|
-
FORWARD_IF_ERROR(cSize);
|
|
3220
|
+
FORWARD_IF_ERROR(cSize, "ZSTD_compressContinue_internal failed");
|
|
3410
3221
|
endResult = ZSTD_writeEpilogue(cctx, (char*)dst + cSize, dstCapacity-cSize);
|
|
3411
|
-
FORWARD_IF_ERROR(endResult);
|
|
3222
|
+
FORWARD_IF_ERROR(endResult, "ZSTD_writeEpilogue failed");
|
|
3412
3223
|
assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0));
|
|
3413
3224
|
if (cctx->pledgedSrcSizePlusOne != 0) { /* control src size */
|
|
3414
3225
|
ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN == (unsigned long long)-1);
|
|
@@ -3428,16 +3239,16 @@ static size_t ZSTD_compress_internal (ZSTD_CCtx* cctx,
|
|
|
3428
3239
|
void* dst, size_t dstCapacity,
|
|
3429
3240
|
const void* src, size_t srcSize,
|
|
3430
3241
|
const void* dict,size_t dictSize,
|
|
3431
|
-
|
|
3242
|
+
const ZSTD_parameters* params)
|
|
3432
3243
|
{
|
|
3433
3244
|
ZSTD_CCtx_params const cctxParams =
|
|
3434
|
-
ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
|
|
3245
|
+
ZSTD_assignParamsToCCtxParams(&cctx->requestedParams, params);
|
|
3435
3246
|
DEBUGLOG(4, "ZSTD_compress_internal");
|
|
3436
3247
|
return ZSTD_compress_advanced_internal(cctx,
|
|
3437
3248
|
dst, dstCapacity,
|
|
3438
3249
|
src, srcSize,
|
|
3439
3250
|
dict, dictSize,
|
|
3440
|
-
cctxParams);
|
|
3251
|
+
&cctxParams);
|
|
3441
3252
|
}
|
|
3442
3253
|
|
|
3443
3254
|
size_t ZSTD_compress_advanced (ZSTD_CCtx* cctx,
|
|
@@ -3447,12 +3258,12 @@ size_t ZSTD_compress_advanced (ZSTD_CCtx* cctx,
|
|
|
3447
3258
|
ZSTD_parameters params)
|
|
3448
3259
|
{
|
|
3449
3260
|
DEBUGLOG(4, "ZSTD_compress_advanced");
|
|
3450
|
-
FORWARD_IF_ERROR(ZSTD_checkCParams(params.cParams));
|
|
3261
|
+
FORWARD_IF_ERROR(ZSTD_checkCParams(params.cParams), "");
|
|
3451
3262
|
return ZSTD_compress_internal(cctx,
|
|
3452
3263
|
dst, dstCapacity,
|
|
3453
3264
|
src, srcSize,
|
|
3454
3265
|
dict, dictSize,
|
|
3455
|
-
params);
|
|
3266
|
+
¶ms);
|
|
3456
3267
|
}
|
|
3457
3268
|
|
|
3458
3269
|
/* Internal */
|
|
@@ -3461,12 +3272,12 @@ size_t ZSTD_compress_advanced_internal(
|
|
|
3461
3272
|
void* dst, size_t dstCapacity,
|
|
3462
3273
|
const void* src, size_t srcSize,
|
|
3463
3274
|
const void* dict,size_t dictSize,
|
|
3464
|
-
ZSTD_CCtx_params params)
|
|
3275
|
+
const ZSTD_CCtx_params* params)
|
|
3465
3276
|
{
|
|
3466
3277
|
DEBUGLOG(4, "ZSTD_compress_advanced_internal (srcSize:%u)", (unsigned)srcSize);
|
|
3467
3278
|
FORWARD_IF_ERROR( ZSTD_compressBegin_internal(cctx,
|
|
3468
3279
|
dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, NULL,
|
|
3469
|
-
params, srcSize, ZSTDb_not_buffered) );
|
|
3280
|
+
params, srcSize, ZSTDb_not_buffered) , "");
|
|
3470
3281
|
return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize);
|
|
3471
3282
|
}
|
|
3472
3283
|
|
|
@@ -3476,10 +3287,11 @@ size_t ZSTD_compress_usingDict(ZSTD_CCtx* cctx,
|
|
|
3476
3287
|
const void* dict, size_t dictSize,
|
|
3477
3288
|
int compressionLevel)
|
|
3478
3289
|
{
|
|
3479
|
-
ZSTD_parameters const params =
|
|
3480
|
-
ZSTD_CCtx_params cctxParams = ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
|
|
3290
|
+
ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, srcSize, dict ? dictSize : 0);
|
|
3291
|
+
ZSTD_CCtx_params cctxParams = ZSTD_assignParamsToCCtxParams(&cctx->requestedParams, ¶ms);
|
|
3292
|
+
DEBUGLOG(4, "ZSTD_compress_usingDict (srcSize=%u)", (unsigned)srcSize);
|
|
3481
3293
|
assert(params.fParams.contentSizeFlag == 1);
|
|
3482
|
-
return ZSTD_compress_advanced_internal(cctx, dst, dstCapacity, src, srcSize, dict, dictSize, cctxParams);
|
|
3294
|
+
return ZSTD_compress_advanced_internal(cctx, dst, dstCapacity, src, srcSize, dict, dictSize, &cctxParams);
|
|
3483
3295
|
}
|
|
3484
3296
|
|
|
3485
3297
|
size_t ZSTD_compressCCtx(ZSTD_CCtx* cctx,
|
|
@@ -3514,13 +3326,16 @@ size_t ZSTD_estimateCDictSize_advanced(
|
|
|
3514
3326
|
ZSTD_dictLoadMethod_e dictLoadMethod)
|
|
3515
3327
|
{
|
|
3516
3328
|
DEBUGLOG(5, "sizeof(ZSTD_CDict) : %u", (unsigned)sizeof(ZSTD_CDict));
|
|
3517
|
-
return sizeof(ZSTD_CDict)
|
|
3518
|
-
|
|
3329
|
+
return ZSTD_cwksp_alloc_size(sizeof(ZSTD_CDict))
|
|
3330
|
+
+ ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE)
|
|
3331
|
+
+ ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 0)
|
|
3332
|
+
+ (dictLoadMethod == ZSTD_dlm_byRef ? 0
|
|
3333
|
+
: ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(dictSize, sizeof(void *))));
|
|
3519
3334
|
}
|
|
3520
3335
|
|
|
3521
3336
|
size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel)
|
|
3522
3337
|
{
|
|
3523
|
-
ZSTD_compressionParameters const cParams =
|
|
3338
|
+
ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize);
|
|
3524
3339
|
return ZSTD_estimateCDictSize_advanced(dictSize, cParams, ZSTD_dlm_byCopy);
|
|
3525
3340
|
}
|
|
3526
3341
|
|
|
@@ -3528,7 +3343,9 @@ size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict)
|
|
|
3528
3343
|
{
|
|
3529
3344
|
if (cdict==NULL) return 0; /* support sizeof on NULL */
|
|
3530
3345
|
DEBUGLOG(5, "sizeof(*cdict) : %u", (unsigned)sizeof(*cdict));
|
|
3531
|
-
|
|
3346
|
+
/* cdict may be in the workspace */
|
|
3347
|
+
return (cdict->workspace.workspace == cdict ? 0 : sizeof(*cdict))
|
|
3348
|
+
+ ZSTD_cwksp_sizeof(&cdict->workspace);
|
|
3532
3349
|
}
|
|
3533
3350
|
|
|
3534
3351
|
static size_t ZSTD_initCDict_internal(
|
|
@@ -3542,28 +3359,29 @@ static size_t ZSTD_initCDict_internal(
|
|
|
3542
3359
|
assert(!ZSTD_checkCParams(cParams));
|
|
3543
3360
|
cdict->matchState.cParams = cParams;
|
|
3544
3361
|
if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dictBuffer) || (!dictSize)) {
|
|
3545
|
-
cdict->dictBuffer = NULL;
|
|
3546
3362
|
cdict->dictContent = dictBuffer;
|
|
3547
3363
|
} else {
|
|
3548
|
-
|
|
3549
|
-
|
|
3364
|
+
void *internalBuffer = ZSTD_cwksp_reserve_object(&cdict->workspace, ZSTD_cwksp_align(dictSize, sizeof(void*)));
|
|
3365
|
+
RETURN_ERROR_IF(!internalBuffer, memory_allocation, "NULL pointer!");
|
|
3550
3366
|
cdict->dictContent = internalBuffer;
|
|
3551
|
-
RETURN_ERROR_IF(!internalBuffer, memory_allocation);
|
|
3552
3367
|
memcpy(internalBuffer, dictBuffer, dictSize);
|
|
3553
3368
|
}
|
|
3554
3369
|
cdict->dictContentSize = dictSize;
|
|
3555
3370
|
|
|
3371
|
+
cdict->entropyWorkspace = (U32*)ZSTD_cwksp_reserve_object(&cdict->workspace, HUF_WORKSPACE_SIZE);
|
|
3372
|
+
|
|
3373
|
+
|
|
3556
3374
|
/* Reset the state to no dictionary */
|
|
3557
3375
|
ZSTD_reset_compressedBlockState(&cdict->cBlockState);
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
3376
|
+
FORWARD_IF_ERROR(ZSTD_reset_matchState(
|
|
3377
|
+
&cdict->matchState,
|
|
3378
|
+
&cdict->workspace,
|
|
3379
|
+
&cParams,
|
|
3380
|
+
ZSTDcrp_makeClean,
|
|
3381
|
+
ZSTDirp_reset,
|
|
3382
|
+
ZSTD_resetTarget_CDict), "");
|
|
3565
3383
|
/* (Maybe) load the dictionary
|
|
3566
|
-
* Skips loading the dictionary if it is
|
|
3384
|
+
* Skips loading the dictionary if it is < 8 bytes.
|
|
3567
3385
|
*/
|
|
3568
3386
|
{ ZSTD_CCtx_params params;
|
|
3569
3387
|
memset(¶ms, 0, sizeof(params));
|
|
@@ -3571,10 +3389,10 @@ static size_t ZSTD_initCDict_internal(
|
|
|
3571
3389
|
params.fParams.contentSizeFlag = 1;
|
|
3572
3390
|
params.cParams = cParams;
|
|
3573
3391
|
{ size_t const dictID = ZSTD_compress_insertDictionary(
|
|
3574
|
-
&cdict->cBlockState, &cdict->matchState, &
|
|
3575
|
-
cdict->dictContent, cdict->dictContentSize,
|
|
3576
|
-
dictContentType, ZSTD_dtlm_full, cdict->
|
|
3577
|
-
FORWARD_IF_ERROR(dictID);
|
|
3392
|
+
&cdict->cBlockState, &cdict->matchState, NULL, &cdict->workspace,
|
|
3393
|
+
¶ms, cdict->dictContent, cdict->dictContentSize,
|
|
3394
|
+
dictContentType, ZSTD_dtlm_full, cdict->entropyWorkspace);
|
|
3395
|
+
FORWARD_IF_ERROR(dictID, "ZSTD_compress_insertDictionary failed");
|
|
3578
3396
|
assert(dictID <= (size_t)(U32)-1);
|
|
3579
3397
|
cdict->dictID = (U32)dictID;
|
|
3580
3398
|
}
|
|
@@ -3591,18 +3409,29 @@ ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize,
|
|
|
3591
3409
|
DEBUGLOG(3, "ZSTD_createCDict_advanced, mode %u", (unsigned)dictContentType);
|
|
3592
3410
|
if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
|
|
3593
3411
|
|
|
3594
|
-
{
|
|
3595
|
-
|
|
3412
|
+
{ size_t const workspaceSize =
|
|
3413
|
+
ZSTD_cwksp_alloc_size(sizeof(ZSTD_CDict)) +
|
|
3414
|
+
ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE) +
|
|
3415
|
+
ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 0) +
|
|
3416
|
+
(dictLoadMethod == ZSTD_dlm_byRef ? 0
|
|
3417
|
+
: ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(dictSize, sizeof(void*))));
|
|
3596
3418
|
void* const workspace = ZSTD_malloc(workspaceSize, customMem);
|
|
3419
|
+
ZSTD_cwksp ws;
|
|
3420
|
+
ZSTD_CDict* cdict;
|
|
3597
3421
|
|
|
3598
|
-
if (!
|
|
3599
|
-
ZSTD_free(cdict, customMem);
|
|
3422
|
+
if (!workspace) {
|
|
3600
3423
|
ZSTD_free(workspace, customMem);
|
|
3601
3424
|
return NULL;
|
|
3602
3425
|
}
|
|
3426
|
+
|
|
3427
|
+
ZSTD_cwksp_init(&ws, workspace, workspaceSize);
|
|
3428
|
+
|
|
3429
|
+
cdict = (ZSTD_CDict*)ZSTD_cwksp_reserve_object(&ws, sizeof(ZSTD_CDict));
|
|
3430
|
+
assert(cdict != NULL);
|
|
3431
|
+
ZSTD_cwksp_move(&cdict->workspace, &ws);
|
|
3603
3432
|
cdict->customMem = customMem;
|
|
3604
|
-
cdict->
|
|
3605
|
-
|
|
3433
|
+
cdict->compressionLevel = 0; /* signals advanced API usage */
|
|
3434
|
+
|
|
3606
3435
|
if (ZSTD_isError( ZSTD_initCDict_internal(cdict,
|
|
3607
3436
|
dictBuffer, dictSize,
|
|
3608
3437
|
dictLoadMethod, dictContentType,
|
|
@@ -3617,15 +3446,18 @@ ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize,
|
|
|
3617
3446
|
|
|
3618
3447
|
ZSTD_CDict* ZSTD_createCDict(const void* dict, size_t dictSize, int compressionLevel)
|
|
3619
3448
|
{
|
|
3620
|
-
ZSTD_compressionParameters cParams =
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3449
|
+
ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize);
|
|
3450
|
+
ZSTD_CDict* cdict = ZSTD_createCDict_advanced(dict, dictSize,
|
|
3451
|
+
ZSTD_dlm_byCopy, ZSTD_dct_auto,
|
|
3452
|
+
cParams, ZSTD_defaultCMem);
|
|
3453
|
+
if (cdict)
|
|
3454
|
+
cdict->compressionLevel = compressionLevel == 0 ? ZSTD_CLEVEL_DEFAULT : compressionLevel;
|
|
3455
|
+
return cdict;
|
|
3624
3456
|
}
|
|
3625
3457
|
|
|
3626
3458
|
ZSTD_CDict* ZSTD_createCDict_byReference(const void* dict, size_t dictSize, int compressionLevel)
|
|
3627
3459
|
{
|
|
3628
|
-
ZSTD_compressionParameters cParams =
|
|
3460
|
+
ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize);
|
|
3629
3461
|
return ZSTD_createCDict_advanced(dict, dictSize,
|
|
3630
3462
|
ZSTD_dlm_byRef, ZSTD_dct_auto,
|
|
3631
3463
|
cParams, ZSTD_defaultCMem);
|
|
@@ -3635,9 +3467,11 @@ size_t ZSTD_freeCDict(ZSTD_CDict* cdict)
|
|
|
3635
3467
|
{
|
|
3636
3468
|
if (cdict==NULL) return 0; /* support free on NULL */
|
|
3637
3469
|
{ ZSTD_customMem const cMem = cdict->customMem;
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3470
|
+
int cdictInWorkspace = ZSTD_cwksp_owns_buffer(&cdict->workspace, cdict);
|
|
3471
|
+
ZSTD_cwksp_free(&cdict->workspace, cMem);
|
|
3472
|
+
if (!cdictInWorkspace) {
|
|
3473
|
+
ZSTD_free(cdict, cMem);
|
|
3474
|
+
}
|
|
3641
3475
|
return 0;
|
|
3642
3476
|
}
|
|
3643
3477
|
}
|
|
@@ -3663,28 +3497,30 @@ const ZSTD_CDict* ZSTD_initStaticCDict(
|
|
|
3663
3497
|
ZSTD_compressionParameters cParams)
|
|
3664
3498
|
{
|
|
3665
3499
|
size_t const matchStateSize = ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 0);
|
|
3666
|
-
size_t const neededSize = sizeof(ZSTD_CDict)
|
|
3667
|
-
+
|
|
3668
|
-
|
|
3669
|
-
|
|
3500
|
+
size_t const neededSize = ZSTD_cwksp_alloc_size(sizeof(ZSTD_CDict))
|
|
3501
|
+
+ (dictLoadMethod == ZSTD_dlm_byRef ? 0
|
|
3502
|
+
: ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(dictSize, sizeof(void*))))
|
|
3503
|
+
+ ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE)
|
|
3504
|
+
+ matchStateSize;
|
|
3505
|
+
ZSTD_CDict* cdict;
|
|
3506
|
+
|
|
3670
3507
|
if ((size_t)workspace & 7) return NULL; /* 8-aligned */
|
|
3508
|
+
|
|
3509
|
+
{
|
|
3510
|
+
ZSTD_cwksp ws;
|
|
3511
|
+
ZSTD_cwksp_init(&ws, workspace, workspaceSize);
|
|
3512
|
+
cdict = (ZSTD_CDict*)ZSTD_cwksp_reserve_object(&ws, sizeof(ZSTD_CDict));
|
|
3513
|
+
if (cdict == NULL) return NULL;
|
|
3514
|
+
ZSTD_cwksp_move(&cdict->workspace, &ws);
|
|
3515
|
+
}
|
|
3516
|
+
|
|
3671
3517
|
DEBUGLOG(4, "(workspaceSize < neededSize) : (%u < %u) => %u",
|
|
3672
3518
|
(unsigned)workspaceSize, (unsigned)neededSize, (unsigned)(workspaceSize < neededSize));
|
|
3673
3519
|
if (workspaceSize < neededSize) return NULL;
|
|
3674
3520
|
|
|
3675
|
-
if (dictLoadMethod == ZSTD_dlm_byCopy) {
|
|
3676
|
-
memcpy(cdict+1, dict, dictSize);
|
|
3677
|
-
dict = cdict+1;
|
|
3678
|
-
ptr = (char*)workspace + sizeof(ZSTD_CDict) + dictSize;
|
|
3679
|
-
} else {
|
|
3680
|
-
ptr = cdict+1;
|
|
3681
|
-
}
|
|
3682
|
-
cdict->workspace = ptr;
|
|
3683
|
-
cdict->workspaceSize = HUF_WORKSPACE_SIZE + matchStateSize;
|
|
3684
|
-
|
|
3685
3521
|
if (ZSTD_isError( ZSTD_initCDict_internal(cdict,
|
|
3686
3522
|
dict, dictSize,
|
|
3687
|
-
|
|
3523
|
+
dictLoadMethod, dictContentType,
|
|
3688
3524
|
cParams) ))
|
|
3689
3525
|
return NULL;
|
|
3690
3526
|
|
|
@@ -3704,9 +3540,17 @@ size_t ZSTD_compressBegin_usingCDict_advanced(
|
|
|
3704
3540
|
ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize)
|
|
3705
3541
|
{
|
|
3706
3542
|
DEBUGLOG(4, "ZSTD_compressBegin_usingCDict_advanced");
|
|
3707
|
-
RETURN_ERROR_IF(cdict==NULL, dictionary_wrong);
|
|
3543
|
+
RETURN_ERROR_IF(cdict==NULL, dictionary_wrong, "NULL pointer!");
|
|
3708
3544
|
{ ZSTD_CCtx_params params = cctx->requestedParams;
|
|
3709
|
-
params.cParams =
|
|
3545
|
+
params.cParams = ( pledgedSrcSize < ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF
|
|
3546
|
+
|| pledgedSrcSize < cdict->dictContentSize * ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER
|
|
3547
|
+
|| pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN
|
|
3548
|
+
|| cdict->compressionLevel == 0 )
|
|
3549
|
+
&& (params.attachDictPref != ZSTD_dictForceLoad) ?
|
|
3550
|
+
ZSTD_getCParamsFromCDict(cdict)
|
|
3551
|
+
: ZSTD_getCParams(cdict->compressionLevel,
|
|
3552
|
+
pledgedSrcSize,
|
|
3553
|
+
cdict->dictContentSize);
|
|
3710
3554
|
/* Increase window log to fit the entire dictionary and source if the
|
|
3711
3555
|
* source size is known. Limit the increase to 19, which is the
|
|
3712
3556
|
* window log for compression level 1 with the largest source size.
|
|
@@ -3720,7 +3564,7 @@ size_t ZSTD_compressBegin_usingCDict_advanced(
|
|
|
3720
3564
|
return ZSTD_compressBegin_internal(cctx,
|
|
3721
3565
|
NULL, 0, ZSTD_dct_auto, ZSTD_dtlm_fast,
|
|
3722
3566
|
cdict,
|
|
3723
|
-
params, pledgedSrcSize,
|
|
3567
|
+
¶ms, pledgedSrcSize,
|
|
3724
3568
|
ZSTDb_not_buffered);
|
|
3725
3569
|
}
|
|
3726
3570
|
}
|
|
@@ -3740,7 +3584,7 @@ size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx,
|
|
|
3740
3584
|
const void* src, size_t srcSize,
|
|
3741
3585
|
const ZSTD_CDict* cdict, ZSTD_frameParameters fParams)
|
|
3742
3586
|
{
|
|
3743
|
-
FORWARD_IF_ERROR(ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, srcSize)); /* will check if cdict != NULL */
|
|
3587
|
+
FORWARD_IF_ERROR(ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, srcSize), ""); /* will check if cdict != NULL */
|
|
3744
3588
|
return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize);
|
|
3745
3589
|
}
|
|
3746
3590
|
|
|
@@ -3811,8 +3655,8 @@ static size_t ZSTD_resetCStream_internal(ZSTD_CStream* cctx,
|
|
|
3811
3655
|
FORWARD_IF_ERROR( ZSTD_compressBegin_internal(cctx,
|
|
3812
3656
|
dict, dictSize, dictContentType, ZSTD_dtlm_fast,
|
|
3813
3657
|
cdict,
|
|
3814
|
-
params, pledgedSrcSize,
|
|
3815
|
-
ZSTDb_buffered) );
|
|
3658
|
+
¶ms, pledgedSrcSize,
|
|
3659
|
+
ZSTDb_buffered) , "");
|
|
3816
3660
|
|
|
3817
3661
|
cctx->inToCompress = 0;
|
|
3818
3662
|
cctx->inBuffPos = 0;
|
|
@@ -3834,8 +3678,8 @@ size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pss)
|
|
|
3834
3678
|
*/
|
|
3835
3679
|
U64 const pledgedSrcSize = (pss==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss;
|
|
3836
3680
|
DEBUGLOG(4, "ZSTD_resetCStream: pledgedSrcSize = %u", (unsigned)pledgedSrcSize);
|
|
3837
|
-
FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
|
|
3838
|
-
FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) );
|
|
3681
|
+
FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
|
|
3682
|
+
FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , "");
|
|
3839
3683
|
return 0;
|
|
3840
3684
|
}
|
|
3841
3685
|
|
|
@@ -3845,19 +3689,20 @@ size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pss)
|
|
|
3845
3689
|
* Assumption 2 : either dict, or cdict, is defined, not both */
|
|
3846
3690
|
size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
|
|
3847
3691
|
const void* dict, size_t dictSize, const ZSTD_CDict* cdict,
|
|
3848
|
-
ZSTD_CCtx_params params,
|
|
3692
|
+
const ZSTD_CCtx_params* params,
|
|
3693
|
+
unsigned long long pledgedSrcSize)
|
|
3849
3694
|
{
|
|
3850
3695
|
DEBUGLOG(4, "ZSTD_initCStream_internal");
|
|
3851
|
-
FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
|
|
3852
|
-
FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) );
|
|
3853
|
-
assert(!ZSTD_isError(ZSTD_checkCParams(params
|
|
3854
|
-
zcs->requestedParams = params;
|
|
3696
|
+
FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
|
|
3697
|
+
FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , "");
|
|
3698
|
+
assert(!ZSTD_isError(ZSTD_checkCParams(params->cParams)));
|
|
3699
|
+
zcs->requestedParams = *params;
|
|
3855
3700
|
assert(!((dict) && (cdict))); /* either dict or cdict, not both */
|
|
3856
3701
|
if (dict) {
|
|
3857
|
-
FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) );
|
|
3702
|
+
FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) , "");
|
|
3858
3703
|
} else {
|
|
3859
3704
|
/* Dictionary is cleared if !cdict */
|
|
3860
|
-
FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) );
|
|
3705
|
+
FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) , "");
|
|
3861
3706
|
}
|
|
3862
3707
|
return 0;
|
|
3863
3708
|
}
|
|
@@ -3870,10 +3715,10 @@ size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs,
|
|
|
3870
3715
|
unsigned long long pledgedSrcSize)
|
|
3871
3716
|
{
|
|
3872
3717
|
DEBUGLOG(4, "ZSTD_initCStream_usingCDict_advanced");
|
|
3873
|
-
FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
|
|
3874
|
-
FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) );
|
|
3718
|
+
FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
|
|
3719
|
+
FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , "");
|
|
3875
3720
|
zcs->requestedParams.fParams = fParams;
|
|
3876
|
-
FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) );
|
|
3721
|
+
FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) , "");
|
|
3877
3722
|
return 0;
|
|
3878
3723
|
}
|
|
3879
3724
|
|
|
@@ -3881,8 +3726,8 @@ size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs,
|
|
|
3881
3726
|
size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict)
|
|
3882
3727
|
{
|
|
3883
3728
|
DEBUGLOG(4, "ZSTD_initCStream_usingCDict");
|
|
3884
|
-
FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
|
|
3885
|
-
FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) );
|
|
3729
|
+
FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
|
|
3730
|
+
FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) , "");
|
|
3886
3731
|
return 0;
|
|
3887
3732
|
}
|
|
3888
3733
|
|
|
@@ -3890,7 +3735,7 @@ size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict)
|
|
|
3890
3735
|
/* ZSTD_initCStream_advanced() :
|
|
3891
3736
|
* pledgedSrcSize must be exact.
|
|
3892
3737
|
* if srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN.
|
|
3893
|
-
* dict is loaded with default parameters
|
|
3738
|
+
* dict is loaded with default parameters ZSTD_dct_auto and ZSTD_dlm_byCopy. */
|
|
3894
3739
|
size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,
|
|
3895
3740
|
const void* dict, size_t dictSize,
|
|
3896
3741
|
ZSTD_parameters params, unsigned long long pss)
|
|
@@ -3901,20 +3746,20 @@ size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,
|
|
|
3901
3746
|
*/
|
|
3902
3747
|
U64 const pledgedSrcSize = (pss==0 && params.fParams.contentSizeFlag==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss;
|
|
3903
3748
|
DEBUGLOG(4, "ZSTD_initCStream_advanced");
|
|
3904
|
-
FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
|
|
3905
|
-
FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) );
|
|
3906
|
-
FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) );
|
|
3907
|
-
zcs->requestedParams = ZSTD_assignParamsToCCtxParams(zcs->requestedParams, params);
|
|
3908
|
-
FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) );
|
|
3749
|
+
FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
|
|
3750
|
+
FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , "");
|
|
3751
|
+
FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) , "");
|
|
3752
|
+
zcs->requestedParams = ZSTD_assignParamsToCCtxParams(&zcs->requestedParams, ¶ms);
|
|
3753
|
+
FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) , "");
|
|
3909
3754
|
return 0;
|
|
3910
3755
|
}
|
|
3911
3756
|
|
|
3912
3757
|
size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel)
|
|
3913
3758
|
{
|
|
3914
3759
|
DEBUGLOG(4, "ZSTD_initCStream_usingDict");
|
|
3915
|
-
FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
|
|
3916
|
-
FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) );
|
|
3917
|
-
FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) );
|
|
3760
|
+
FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
|
|
3761
|
+
FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) , "");
|
|
3762
|
+
FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) , "");
|
|
3918
3763
|
return 0;
|
|
3919
3764
|
}
|
|
3920
3765
|
|
|
@@ -3926,19 +3771,19 @@ size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigne
|
|
|
3926
3771
|
*/
|
|
3927
3772
|
U64 const pledgedSrcSize = (pss==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss;
|
|
3928
3773
|
DEBUGLOG(4, "ZSTD_initCStream_srcSize");
|
|
3929
|
-
FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
|
|
3930
|
-
FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, NULL) );
|
|
3931
|
-
FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) );
|
|
3932
|
-
FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) );
|
|
3774
|
+
FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
|
|
3775
|
+
FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, NULL) , "");
|
|
3776
|
+
FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) , "");
|
|
3777
|
+
FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , "");
|
|
3933
3778
|
return 0;
|
|
3934
3779
|
}
|
|
3935
3780
|
|
|
3936
3781
|
size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel)
|
|
3937
3782
|
{
|
|
3938
3783
|
DEBUGLOG(4, "ZSTD_initCStream");
|
|
3939
|
-
FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) );
|
|
3940
|
-
FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, NULL) );
|
|
3941
|
-
FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) );
|
|
3784
|
+
FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
|
|
3785
|
+
FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, NULL) , "");
|
|
3786
|
+
FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) , "");
|
|
3942
3787
|
return 0;
|
|
3943
3788
|
}
|
|
3944
3789
|
|
|
@@ -3951,14 +3796,6 @@ static size_t ZSTD_nextInputSizeHint(const ZSTD_CCtx* cctx)
|
|
|
3951
3796
|
return hintInSize;
|
|
3952
3797
|
}
|
|
3953
3798
|
|
|
3954
|
-
static size_t ZSTD_limitCopy(void* dst, size_t dstCapacity,
|
|
3955
|
-
const void* src, size_t srcSize)
|
|
3956
|
-
{
|
|
3957
|
-
size_t const length = MIN(dstCapacity, srcSize);
|
|
3958
|
-
if (length) memcpy(dst, src, length);
|
|
3959
|
-
return length;
|
|
3960
|
-
}
|
|
3961
|
-
|
|
3962
3799
|
/** ZSTD_compressStream_generic():
|
|
3963
3800
|
* internal function for all *compressStream*() variants
|
|
3964
3801
|
* non-static, because can be called from zstdmt_compress.c
|
|
@@ -3969,11 +3806,11 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
|
|
|
3969
3806
|
ZSTD_EndDirective const flushMode)
|
|
3970
3807
|
{
|
|
3971
3808
|
const char* const istart = (const char*)input->src;
|
|
3972
|
-
const char* const iend = istart + input->size;
|
|
3973
|
-
const char* ip = istart + input->pos;
|
|
3809
|
+
const char* const iend = input->size != 0 ? istart + input->size : istart;
|
|
3810
|
+
const char* ip = input->pos != 0 ? istart + input->pos : istart;
|
|
3974
3811
|
char* const ostart = (char*)output->dst;
|
|
3975
|
-
char* const oend = ostart + output->size;
|
|
3976
|
-
char* op = ostart + output->pos;
|
|
3812
|
+
char* const oend = output->size != 0 ? ostart + output->size : ostart;
|
|
3813
|
+
char* op = output->pos != 0 ? ostart + output->pos : ostart;
|
|
3977
3814
|
U32 someMoreWork = 1;
|
|
3978
3815
|
|
|
3979
3816
|
/* check expectations */
|
|
@@ -3999,7 +3836,7 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
|
|
|
3999
3836
|
size_t const cSize = ZSTD_compressEnd(zcs,
|
|
4000
3837
|
op, oend-op, ip, iend-ip);
|
|
4001
3838
|
DEBUGLOG(4, "ZSTD_compressEnd : cSize=%u", (unsigned)cSize);
|
|
4002
|
-
FORWARD_IF_ERROR(cSize);
|
|
3839
|
+
FORWARD_IF_ERROR(cSize, "ZSTD_compressEnd failed");
|
|
4003
3840
|
ip = iend;
|
|
4004
3841
|
op += cSize;
|
|
4005
3842
|
zcs->frameEnded = 1;
|
|
@@ -4012,7 +3849,8 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
|
|
|
4012
3849
|
zcs->inBuff + zcs->inBuffPos, toLoad,
|
|
4013
3850
|
ip, iend-ip);
|
|
4014
3851
|
zcs->inBuffPos += loaded;
|
|
4015
|
-
|
|
3852
|
+
if (loaded != 0)
|
|
3853
|
+
ip += loaded;
|
|
4016
3854
|
if ( (flushMode == ZSTD_e_continue)
|
|
4017
3855
|
&& (zcs->inBuffPos < zcs->inBuffTarget) ) {
|
|
4018
3856
|
/* not enough input to fill full block : stop here */
|
|
@@ -4040,7 +3878,7 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
|
|
|
4040
3878
|
zcs->inBuff + zcs->inToCompress, iSize) :
|
|
4041
3879
|
ZSTD_compressContinue(zcs, cDst, oSize,
|
|
4042
3880
|
zcs->inBuff + zcs->inToCompress, iSize);
|
|
4043
|
-
FORWARD_IF_ERROR(cSize);
|
|
3881
|
+
FORWARD_IF_ERROR(cSize, "%s", lastBlock ? "ZSTD_compressEnd failed" : "ZSTD_compressContinue failed");
|
|
4044
3882
|
zcs->frameEnded = lastBlock;
|
|
4045
3883
|
/* prepare next block */
|
|
4046
3884
|
zcs->inBuffTarget = zcs->inBuffPos + zcs->blockSize;
|
|
@@ -4068,11 +3906,12 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
|
|
|
4068
3906
|
case zcss_flush:
|
|
4069
3907
|
DEBUGLOG(5, "flush stage");
|
|
4070
3908
|
{ size_t const toFlush = zcs->outBuffContentSize - zcs->outBuffFlushedSize;
|
|
4071
|
-
size_t const flushed = ZSTD_limitCopy(op, oend-op,
|
|
3909
|
+
size_t const flushed = ZSTD_limitCopy(op, (size_t)(oend-op),
|
|
4072
3910
|
zcs->outBuff + zcs->outBuffFlushedSize, toFlush);
|
|
4073
3911
|
DEBUGLOG(5, "toFlush: %u into %u ==> flushed: %u",
|
|
4074
3912
|
(unsigned)toFlush, (unsigned)(oend-op), (unsigned)flushed);
|
|
4075
|
-
|
|
3913
|
+
if (flushed)
|
|
3914
|
+
op += flushed;
|
|
4076
3915
|
zcs->outBuffFlushedSize += flushed;
|
|
4077
3916
|
if (toFlush!=flushed) {
|
|
4078
3917
|
/* flush not fully completed, presumably because dst is too small */
|
|
@@ -4116,7 +3955,7 @@ static size_t ZSTD_nextInputSizeHint_MTorST(const ZSTD_CCtx* cctx)
|
|
|
4116
3955
|
|
|
4117
3956
|
size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
|
|
4118
3957
|
{
|
|
4119
|
-
FORWARD_IF_ERROR( ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue) );
|
|
3958
|
+
FORWARD_IF_ERROR( ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue) , "");
|
|
4120
3959
|
return ZSTD_nextInputSizeHint_MTorST(zcs);
|
|
4121
3960
|
}
|
|
4122
3961
|
|
|
@@ -4128,15 +3967,15 @@ size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
|
|
|
4128
3967
|
{
|
|
4129
3968
|
DEBUGLOG(5, "ZSTD_compressStream2, endOp=%u ", (unsigned)endOp);
|
|
4130
3969
|
/* check conditions */
|
|
4131
|
-
RETURN_ERROR_IF(output->pos > output->size, GENERIC);
|
|
4132
|
-
RETURN_ERROR_IF(input->pos > input->size, GENERIC);
|
|
3970
|
+
RETURN_ERROR_IF(output->pos > output->size, GENERIC, "invalid buffer");
|
|
3971
|
+
RETURN_ERROR_IF(input->pos > input->size, GENERIC, "invalid buffer");
|
|
4133
3972
|
assert(cctx!=NULL);
|
|
4134
3973
|
|
|
4135
3974
|
/* transparent initialization stage */
|
|
4136
3975
|
if (cctx->streamStage == zcss_init) {
|
|
4137
3976
|
ZSTD_CCtx_params params = cctx->requestedParams;
|
|
4138
3977
|
ZSTD_prefixDict const prefixDict = cctx->prefixDict;
|
|
4139
|
-
FORWARD_IF_ERROR( ZSTD_initLocalDict(cctx) ); /* Init the local dict if present. */
|
|
3978
|
+
FORWARD_IF_ERROR( ZSTD_initLocalDict(cctx) , ""); /* Init the local dict if present. */
|
|
4140
3979
|
memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); /* single usage */
|
|
4141
3980
|
assert(prefixDict.dict==NULL || cctx->cdict==NULL); /* only one can be set */
|
|
4142
3981
|
DEBUGLOG(4, "ZSTD_compressStream2 : transparent init stage");
|
|
@@ -4154,15 +3993,15 @@ size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
|
|
|
4154
3993
|
if (cctx->mtctx == NULL) {
|
|
4155
3994
|
DEBUGLOG(4, "ZSTD_compressStream2: creating new mtctx for nbWorkers=%u",
|
|
4156
3995
|
params.nbWorkers);
|
|
4157
|
-
cctx->mtctx = ZSTDMT_createCCtx_advanced(params.nbWorkers, cctx->customMem);
|
|
4158
|
-
RETURN_ERROR_IF(cctx->mtctx == NULL, memory_allocation);
|
|
3996
|
+
cctx->mtctx = ZSTDMT_createCCtx_advanced((U32)params.nbWorkers, cctx->customMem);
|
|
3997
|
+
RETURN_ERROR_IF(cctx->mtctx == NULL, memory_allocation, "NULL pointer!");
|
|
4159
3998
|
}
|
|
4160
3999
|
/* mt compression */
|
|
4161
4000
|
DEBUGLOG(4, "call ZSTDMT_initCStream_internal as nbWorkers=%u", params.nbWorkers);
|
|
4162
4001
|
FORWARD_IF_ERROR( ZSTDMT_initCStream_internal(
|
|
4163
4002
|
cctx->mtctx,
|
|
4164
|
-
prefixDict.dict, prefixDict.dictSize,
|
|
4165
|
-
cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) );
|
|
4003
|
+
prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType,
|
|
4004
|
+
cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) , "");
|
|
4166
4005
|
cctx->streamStage = zcss_load;
|
|
4167
4006
|
cctx->appliedParams.nbWorkers = params.nbWorkers;
|
|
4168
4007
|
} else
|
|
@@ -4170,7 +4009,7 @@ size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
|
|
|
4170
4009
|
{ FORWARD_IF_ERROR( ZSTD_resetCStream_internal(cctx,
|
|
4171
4010
|
prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType,
|
|
4172
4011
|
cctx->cdict,
|
|
4173
|
-
params, cctx->pledgedSrcSizePlusOne-1) );
|
|
4012
|
+
params, cctx->pledgedSrcSizePlusOne-1) , "");
|
|
4174
4013
|
assert(cctx->streamStage == zcss_load);
|
|
4175
4014
|
assert(cctx->appliedParams.nbWorkers == 0);
|
|
4176
4015
|
} }
|
|
@@ -4192,7 +4031,7 @@ size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
|
|
|
4192
4031
|
|| (endOp == ZSTD_e_end && flushMin == 0) ) { /* compression completed */
|
|
4193
4032
|
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);
|
|
4194
4033
|
}
|
|
4195
|
-
FORWARD_IF_ERROR(flushMin);
|
|
4034
|
+
FORWARD_IF_ERROR(flushMin, "ZSTDMT_compressStream_generic failed");
|
|
4196
4035
|
} while (forceMaxProgress && flushMin != 0 && output->pos < output->size);
|
|
4197
4036
|
DEBUGLOG(5, "completed ZSTD_compressStream2 delegating to ZSTDMT_compressStream_generic");
|
|
4198
4037
|
/* Either we don't require maximum forward progress, we've finished the
|
|
@@ -4202,7 +4041,7 @@ size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
|
|
|
4202
4041
|
return flushMin;
|
|
4203
4042
|
}
|
|
4204
4043
|
#endif
|
|
4205
|
-
FORWARD_IF_ERROR( ZSTD_compressStream_generic(cctx, output, input, endOp) );
|
|
4044
|
+
FORWARD_IF_ERROR( ZSTD_compressStream_generic(cctx, output, input, endOp) , "");
|
|
4206
4045
|
DEBUGLOG(5, "completed ZSTD_compressStream2");
|
|
4207
4046
|
return cctx->outBuffContentSize - cctx->outBuffFlushedSize; /* remaining to flush */
|
|
4208
4047
|
}
|
|
@@ -4226,6 +4065,7 @@ size_t ZSTD_compress2(ZSTD_CCtx* cctx,
|
|
|
4226
4065
|
void* dst, size_t dstCapacity,
|
|
4227
4066
|
const void* src, size_t srcSize)
|
|
4228
4067
|
{
|
|
4068
|
+
DEBUGLOG(4, "ZSTD_compress2 (srcSize=%u)", (unsigned)srcSize);
|
|
4229
4069
|
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);
|
|
4230
4070
|
{ size_t oPos = 0;
|
|
4231
4071
|
size_t iPos = 0;
|
|
@@ -4233,10 +4073,10 @@ size_t ZSTD_compress2(ZSTD_CCtx* cctx,
|
|
|
4233
4073
|
dst, dstCapacity, &oPos,
|
|
4234
4074
|
src, srcSize, &iPos,
|
|
4235
4075
|
ZSTD_e_end);
|
|
4236
|
-
FORWARD_IF_ERROR(result);
|
|
4076
|
+
FORWARD_IF_ERROR(result, "ZSTD_compressStream2_simpleArgs failed");
|
|
4237
4077
|
if (result != 0) { /* compression not completed, due to lack of output space */
|
|
4238
4078
|
assert(oPos == dstCapacity);
|
|
4239
|
-
RETURN_ERROR(dstSize_tooSmall);
|
|
4079
|
+
RETURN_ERROR(dstSize_tooSmall, "");
|
|
4240
4080
|
}
|
|
4241
4081
|
assert(iPos == srcSize); /* all input is expected consumed */
|
|
4242
4082
|
return oPos;
|
|
@@ -4258,11 +4098,11 @@ size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output)
|
|
|
4258
4098
|
{
|
|
4259
4099
|
ZSTD_inBuffer input = { NULL, 0, 0 };
|
|
4260
4100
|
size_t const remainingToFlush = ZSTD_compressStream2(zcs, output, &input, ZSTD_e_end);
|
|
4261
|
-
FORWARD_IF_ERROR( remainingToFlush );
|
|
4101
|
+
FORWARD_IF_ERROR( remainingToFlush , "ZSTD_compressStream2 failed");
|
|
4262
4102
|
if (zcs->appliedParams.nbWorkers > 0) return remainingToFlush; /* minimal estimation */
|
|
4263
4103
|
/* single thread mode : attempt to calculate remaining to flush more precisely */
|
|
4264
4104
|
{ size_t const lastBlockSize = zcs->frameEnded ? 0 : ZSTD_BLOCKHEADERSIZE;
|
|
4265
|
-
size_t const checksumSize = zcs->frameEnded ? 0 : zcs->appliedParams.fParams.checksumFlag * 4;
|
|
4105
|
+
size_t const checksumSize = (size_t)(zcs->frameEnded ? 0 : zcs->appliedParams.fParams.checksumFlag * 4);
|
|
4266
4106
|
size_t const toFlush = remainingToFlush + lastBlockSize + checksumSize;
|
|
4267
4107
|
DEBUGLOG(4, "ZSTD_endStream : remaining to flush : %u", (unsigned)toFlush);
|
|
4268
4108
|
return toFlush;
|
|
@@ -4282,8 +4122,8 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
|
|
|
4282
4122
|
{ 19, 12, 13, 1, 6, 1, ZSTD_fast }, /* base for negative levels */
|
|
4283
4123
|
{ 19, 13, 14, 1, 7, 0, ZSTD_fast }, /* level 1 */
|
|
4284
4124
|
{ 20, 15, 16, 1, 6, 0, ZSTD_fast }, /* level 2 */
|
|
4285
|
-
{ 21, 16, 17, 1, 5,
|
|
4286
|
-
{ 21, 18, 18, 1, 5,
|
|
4125
|
+
{ 21, 16, 17, 1, 5, 0, ZSTD_dfast }, /* level 3 */
|
|
4126
|
+
{ 21, 18, 18, 1, 5, 0, ZSTD_dfast }, /* level 4 */
|
|
4287
4127
|
{ 21, 18, 19, 2, 5, 2, ZSTD_greedy }, /* level 5 */
|
|
4288
4128
|
{ 21, 19, 19, 3, 5, 4, ZSTD_greedy }, /* level 6 */
|
|
4289
4129
|
{ 21, 19, 19, 3, 5, 8, ZSTD_lazy }, /* level 7 */
|
|
@@ -4307,8 +4147,8 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
|
|
|
4307
4147
|
/* W, C, H, S, L, T, strat */
|
|
4308
4148
|
{ 18, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */
|
|
4309
4149
|
{ 18, 13, 14, 1, 6, 0, ZSTD_fast }, /* level 1 */
|
|
4310
|
-
{ 18, 14, 14, 1, 5,
|
|
4311
|
-
{ 18, 16, 16, 1, 4,
|
|
4150
|
+
{ 18, 14, 14, 1, 5, 0, ZSTD_dfast }, /* level 2 */
|
|
4151
|
+
{ 18, 16, 16, 1, 4, 0, ZSTD_dfast }, /* level 3 */
|
|
4312
4152
|
{ 18, 16, 17, 2, 5, 2, ZSTD_greedy }, /* level 4.*/
|
|
4313
4153
|
{ 18, 18, 18, 3, 5, 2, ZSTD_greedy }, /* level 5.*/
|
|
4314
4154
|
{ 18, 18, 19, 3, 5, 4, ZSTD_lazy }, /* level 6.*/
|
|
@@ -4334,8 +4174,8 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
|
|
|
4334
4174
|
{ 17, 12, 12, 1, 5, 1, ZSTD_fast }, /* base for negative levels */
|
|
4335
4175
|
{ 17, 12, 13, 1, 6, 0, ZSTD_fast }, /* level 1 */
|
|
4336
4176
|
{ 17, 13, 15, 1, 5, 0, ZSTD_fast }, /* level 2 */
|
|
4337
|
-
{ 17, 15, 16, 2, 5,
|
|
4338
|
-
{ 17, 17, 17, 2, 4,
|
|
4177
|
+
{ 17, 15, 16, 2, 5, 0, ZSTD_dfast }, /* level 3 */
|
|
4178
|
+
{ 17, 17, 17, 2, 4, 0, ZSTD_dfast }, /* level 4 */
|
|
4339
4179
|
{ 17, 16, 17, 3, 4, 2, ZSTD_greedy }, /* level 5 */
|
|
4340
4180
|
{ 17, 17, 17, 3, 4, 4, ZSTD_lazy }, /* level 6 */
|
|
4341
4181
|
{ 17, 17, 17, 3, 4, 8, ZSTD_lazy2 }, /* level 7 */
|
|
@@ -4360,7 +4200,7 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
|
|
|
4360
4200
|
{ 14, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */
|
|
4361
4201
|
{ 14, 14, 15, 1, 5, 0, ZSTD_fast }, /* level 1 */
|
|
4362
4202
|
{ 14, 14, 15, 1, 4, 0, ZSTD_fast }, /* level 2 */
|
|
4363
|
-
{ 14, 14, 15, 2, 4,
|
|
4203
|
+
{ 14, 14, 15, 2, 4, 0, ZSTD_dfast }, /* level 3 */
|
|
4364
4204
|
{ 14, 14, 14, 4, 4, 2, ZSTD_greedy }, /* level 4 */
|
|
4365
4205
|
{ 14, 14, 14, 3, 4, 4, ZSTD_lazy }, /* level 5.*/
|
|
4366
4206
|
{ 14, 14, 14, 4, 4, 8, ZSTD_lazy2 }, /* level 6 */
|
|
@@ -4383,35 +4223,56 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
|
|
|
4383
4223
|
},
|
|
4384
4224
|
};
|
|
4385
4225
|
|
|
4386
|
-
/*!
|
|
4226
|
+
/*! ZSTD_getCParams_internal() :
|
|
4387
4227
|
* @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize.
|
|
4388
|
-
*
|
|
4389
|
-
|
|
4228
|
+
* Note: srcSizeHint 0 means 0, use ZSTD_CONTENTSIZE_UNKNOWN for unknown.
|
|
4229
|
+
* Use dictSize == 0 for unknown or unused. */
|
|
4230
|
+
static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize)
|
|
4390
4231
|
{
|
|
4391
|
-
|
|
4392
|
-
|
|
4232
|
+
int const unknown = srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN;
|
|
4233
|
+
size_t const addedSize = unknown && dictSize > 0 ? 500 : 0;
|
|
4234
|
+
U64 const rSize = unknown && dictSize == 0 ? ZSTD_CONTENTSIZE_UNKNOWN : srcSizeHint+dictSize+addedSize;
|
|
4393
4235
|
U32 const tableID = (rSize <= 256 KB) + (rSize <= 128 KB) + (rSize <= 16 KB);
|
|
4394
4236
|
int row = compressionLevel;
|
|
4395
|
-
DEBUGLOG(5, "
|
|
4237
|
+
DEBUGLOG(5, "ZSTD_getCParams_internal (cLevel=%i)", compressionLevel);
|
|
4396
4238
|
if (compressionLevel == 0) row = ZSTD_CLEVEL_DEFAULT; /* 0 == default */
|
|
4397
4239
|
if (compressionLevel < 0) row = 0; /* entry 0 is baseline for fast mode */
|
|
4398
4240
|
if (compressionLevel > ZSTD_MAX_CLEVEL) row = ZSTD_MAX_CLEVEL;
|
|
4399
4241
|
{ ZSTD_compressionParameters cp = ZSTD_defaultCParameters[tableID][row];
|
|
4400
4242
|
if (compressionLevel < 0) cp.targetLength = (unsigned)(-compressionLevel); /* acceleration factor */
|
|
4401
|
-
|
|
4243
|
+
/* refine parameters based on srcSize & dictSize */
|
|
4244
|
+
return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize);
|
|
4402
4245
|
}
|
|
4403
4246
|
}
|
|
4404
4247
|
|
|
4248
|
+
/*! ZSTD_getCParams() :
|
|
4249
|
+
* @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize.
|
|
4250
|
+
* Size values are optional, provide 0 if not known or unused */
|
|
4251
|
+
ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize)
|
|
4252
|
+
{
|
|
4253
|
+
if (srcSizeHint == 0) srcSizeHint = ZSTD_CONTENTSIZE_UNKNOWN;
|
|
4254
|
+
return ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize);
|
|
4255
|
+
}
|
|
4256
|
+
|
|
4405
4257
|
/*! ZSTD_getParams() :
|
|
4406
4258
|
* same idea as ZSTD_getCParams()
|
|
4407
4259
|
* @return a `ZSTD_parameters` structure (instead of `ZSTD_compressionParameters`).
|
|
4408
4260
|
* Fields of `ZSTD_frameParameters` are set to default values */
|
|
4409
|
-
ZSTD_parameters
|
|
4261
|
+
static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) {
|
|
4410
4262
|
ZSTD_parameters params;
|
|
4411
|
-
ZSTD_compressionParameters const cParams =
|
|
4263
|
+
ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize);
|
|
4412
4264
|
DEBUGLOG(5, "ZSTD_getParams (cLevel=%i)", compressionLevel);
|
|
4413
4265
|
memset(¶ms, 0, sizeof(params));
|
|
4414
4266
|
params.cParams = cParams;
|
|
4415
4267
|
params.fParams.contentSizeFlag = 1;
|
|
4416
4268
|
return params;
|
|
4417
4269
|
}
|
|
4270
|
+
|
|
4271
|
+
/*! ZSTD_getParams() :
|
|
4272
|
+
* same idea as ZSTD_getCParams()
|
|
4273
|
+
* @return a `ZSTD_parameters` structure (instead of `ZSTD_compressionParameters`).
|
|
4274
|
+
* Fields of `ZSTD_frameParameters` are set to default values */
|
|
4275
|
+
ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) {
|
|
4276
|
+
if (srcSizeHint == 0) srcSizeHint = ZSTD_CONTENTSIZE_UNKNOWN;
|
|
4277
|
+
return ZSTD_getParams_internal(compressionLevel, srcSizeHint, dictSize);
|
|
4278
|
+
}
|