zstd-ruby 1.3.8.0 → 1.4.5.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/.travis.yml +6 -5
- data/README.md +1 -1
- data/ext/zstdruby/libzstd/Makefile +133 -61
- data/ext/zstdruby/libzstd/README.md +51 -18
- data/ext/zstdruby/libzstd/common/bitstream.h +38 -39
- data/ext/zstdruby/libzstd/common/compiler.h +41 -6
- data/ext/zstdruby/libzstd/common/cpu.h +1 -1
- data/ext/zstdruby/libzstd/common/debug.c +11 -31
- data/ext/zstdruby/libzstd/common/debug.h +11 -31
- data/ext/zstdruby/libzstd/common/entropy_common.c +13 -33
- data/ext/zstdruby/libzstd/common/error_private.c +2 -1
- data/ext/zstdruby/libzstd/common/error_private.h +6 -2
- data/ext/zstdruby/libzstd/common/fse.h +13 -33
- data/ext/zstdruby/libzstd/common/fse_decompress.c +12 -35
- data/ext/zstdruby/libzstd/common/huf.h +15 -33
- data/ext/zstdruby/libzstd/common/mem.h +75 -2
- data/ext/zstdruby/libzstd/common/pool.c +8 -4
- data/ext/zstdruby/libzstd/common/pool.h +2 -2
- data/ext/zstdruby/libzstd/common/threading.c +52 -6
- data/ext/zstdruby/libzstd/common/threading.h +36 -4
- data/ext/zstdruby/libzstd/common/xxhash.c +25 -37
- data/ext/zstdruby/libzstd/common/xxhash.h +11 -31
- data/ext/zstdruby/libzstd/common/zstd_common.c +1 -1
- data/ext/zstdruby/libzstd/common/zstd_errors.h +2 -1
- data/ext/zstdruby/libzstd/common/zstd_internal.h +203 -22
- data/ext/zstdruby/libzstd/compress/fse_compress.c +19 -42
- data/ext/zstdruby/libzstd/compress/hist.c +15 -35
- data/ext/zstdruby/libzstd/compress/hist.h +12 -32
- data/ext/zstdruby/libzstd/compress/huf_compress.c +92 -92
- data/ext/zstdruby/libzstd/compress/zstd_compress.c +1460 -1472
- data/ext/zstdruby/libzstd/compress/zstd_compress_internal.h +330 -65
- data/ext/zstdruby/libzstd/compress/zstd_compress_literals.c +158 -0
- data/ext/zstdruby/libzstd/compress/zstd_compress_literals.h +29 -0
- data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.c +419 -0
- data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.h +54 -0
- data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.c +845 -0
- data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.h +32 -0
- data/ext/zstdruby/libzstd/compress/zstd_cwksp.h +525 -0
- data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +65 -43
- data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +2 -2
- data/ext/zstdruby/libzstd/compress/zstd_fast.c +264 -159
- data/ext/zstdruby/libzstd/compress/zstd_fast.h +2 -2
- data/ext/zstdruby/libzstd/compress/zstd_lazy.c +74 -42
- data/ext/zstdruby/libzstd/compress/zstd_lazy.h +2 -2
- data/ext/zstdruby/libzstd/compress/zstd_ldm.c +33 -11
- data/ext/zstdruby/libzstd/compress/zstd_ldm.h +7 -2
- data/ext/zstdruby/libzstd/compress/zstd_opt.c +108 -125
- data/ext/zstdruby/libzstd/compress/zstd_opt.h +1 -1
- data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +129 -93
- data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +46 -28
- data/ext/zstdruby/libzstd/decompress/huf_decompress.c +76 -60
- data/ext/zstdruby/libzstd/decompress/zstd_ddict.c +14 -10
- data/ext/zstdruby/libzstd/decompress/zstd_ddict.h +2 -2
- data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +471 -258
- data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.c +471 -346
- data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.h +3 -3
- data/ext/zstdruby/libzstd/decompress/zstd_decompress_internal.h +25 -4
- data/ext/zstdruby/libzstd/deprecated/zbuff.h +9 -8
- data/ext/zstdruby/libzstd/deprecated/zbuff_common.c +2 -2
- data/ext/zstdruby/libzstd/deprecated/zbuff_compress.c +1 -1
- data/ext/zstdruby/libzstd/deprecated/zbuff_decompress.c +1 -1
- data/ext/zstdruby/libzstd/dictBuilder/cover.c +220 -65
- data/ext/zstdruby/libzstd/dictBuilder/cover.h +81 -7
- data/ext/zstdruby/libzstd/dictBuilder/fastcover.c +85 -56
- data/ext/zstdruby/libzstd/dictBuilder/zdict.c +43 -19
- data/ext/zstdruby/libzstd/dictBuilder/zdict.h +73 -35
- data/ext/zstdruby/libzstd/dll/example/Makefile +2 -1
- data/ext/zstdruby/libzstd/dll/example/build_package.bat +3 -2
- data/ext/zstdruby/libzstd/legacy/zstd_legacy.h +49 -15
- data/ext/zstdruby/libzstd/legacy/zstd_v01.c +142 -117
- data/ext/zstdruby/libzstd/legacy/zstd_v01.h +13 -8
- data/ext/zstdruby/libzstd/legacy/zstd_v02.c +54 -25
- data/ext/zstdruby/libzstd/legacy/zstd_v02.h +13 -8
- data/ext/zstdruby/libzstd/legacy/zstd_v03.c +55 -25
- data/ext/zstdruby/libzstd/legacy/zstd_v03.h +13 -8
- data/ext/zstdruby/libzstd/legacy/zstd_v04.c +62 -29
- data/ext/zstdruby/libzstd/legacy/zstd_v04.h +13 -8
- data/ext/zstdruby/libzstd/legacy/zstd_v05.c +145 -109
- data/ext/zstdruby/libzstd/legacy/zstd_v05.h +14 -9
- data/ext/zstdruby/libzstd/legacy/zstd_v06.c +56 -26
- data/ext/zstdruby/libzstd/legacy/zstd_v06.h +11 -6
- data/ext/zstdruby/libzstd/legacy/zstd_v07.c +65 -28
- data/ext/zstdruby/libzstd/legacy/zstd_v07.h +11 -6
- data/ext/zstdruby/libzstd/libzstd.pc.in +3 -2
- data/ext/zstdruby/libzstd/zstd.h +921 -597
- data/lib/zstd-ruby/version.rb +1 -1
- data/zstd-ruby.gemspec +2 -2
- metadata +19 -14
- data/ext/zstdruby/libzstd/dll/libzstd.def +0 -87
|
@@ -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,46 +90,72 @@ 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
|
}
|
|
105
116
|
|
|
117
|
+
/**
|
|
118
|
+
* Clears and frees all of the dictionaries in the CCtx.
|
|
119
|
+
*/
|
|
120
|
+
static void ZSTD_clearAllDicts(ZSTD_CCtx* cctx)
|
|
121
|
+
{
|
|
122
|
+
ZSTD_free(cctx->localDict.dictBuffer, cctx->customMem);
|
|
123
|
+
ZSTD_freeCDict(cctx->localDict.cdict);
|
|
124
|
+
memset(&cctx->localDict, 0, sizeof(cctx->localDict));
|
|
125
|
+
memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict));
|
|
126
|
+
cctx->cdict = NULL;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
static size_t ZSTD_sizeof_localDict(ZSTD_localDict dict)
|
|
130
|
+
{
|
|
131
|
+
size_t const bufferSize = dict.dictBuffer != NULL ? dict.dictSize : 0;
|
|
132
|
+
size_t const cdictSize = ZSTD_sizeof_CDict(dict.cdict);
|
|
133
|
+
return bufferSize + cdictSize;
|
|
134
|
+
}
|
|
135
|
+
|
|
106
136
|
static void ZSTD_freeCCtxContent(ZSTD_CCtx* cctx)
|
|
107
137
|
{
|
|
108
138
|
assert(cctx != NULL);
|
|
109
139
|
assert(cctx->staticSize == 0);
|
|
110
|
-
|
|
111
|
-
ZSTD_freeCDict(cctx->cdictLocal); cctx->cdictLocal = NULL;
|
|
140
|
+
ZSTD_clearAllDicts(cctx);
|
|
112
141
|
#ifdef ZSTD_MULTITHREAD
|
|
113
142
|
ZSTDMT_freeCCtx(cctx->mtctx); cctx->mtctx = NULL;
|
|
114
143
|
#endif
|
|
144
|
+
ZSTD_cwksp_free(&cctx->workspace, cctx->customMem);
|
|
115
145
|
}
|
|
116
146
|
|
|
117
147
|
size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
|
|
118
148
|
{
|
|
119
149
|
if (cctx==NULL) return 0; /* support free on NULL */
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
150
|
+
RETURN_ERROR_IF(cctx->staticSize, memory_allocation,
|
|
151
|
+
"not compatible with static CCtx");
|
|
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
|
+
}
|
|
123
159
|
return 0;
|
|
124
160
|
}
|
|
125
161
|
|
|
@@ -138,8 +174,10 @@ static size_t ZSTD_sizeof_mtctx(const ZSTD_CCtx* cctx)
|
|
|
138
174
|
size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx)
|
|
139
175
|
{
|
|
140
176
|
if (cctx==NULL) return 0; /* support sizeof on NULL */
|
|
141
|
-
|
|
142
|
-
|
|
177
|
+
/* cctx may be in the workspace */
|
|
178
|
+
return (cctx->workspace.workspace == cctx ? 0 : sizeof(*cctx))
|
|
179
|
+
+ ZSTD_cwksp_sizeof(&cctx->workspace)
|
|
180
|
+
+ ZSTD_sizeof_localDict(cctx->localDict)
|
|
143
181
|
+ ZSTD_sizeof_mtctx(cctx);
|
|
144
182
|
}
|
|
145
183
|
|
|
@@ -195,7 +233,7 @@ size_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params)
|
|
|
195
233
|
}
|
|
196
234
|
|
|
197
235
|
size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel) {
|
|
198
|
-
|
|
236
|
+
RETURN_ERROR_IF(!cctxParams, GENERIC, "NULL pointer!");
|
|
199
237
|
memset(cctxParams, 0, sizeof(*cctxParams));
|
|
200
238
|
cctxParams->compressionLevel = compressionLevel;
|
|
201
239
|
cctxParams->fParams.contentSizeFlag = 1;
|
|
@@ -204,26 +242,26 @@ size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel)
|
|
|
204
242
|
|
|
205
243
|
size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params)
|
|
206
244
|
{
|
|
207
|
-
|
|
208
|
-
|
|
245
|
+
RETURN_ERROR_IF(!cctxParams, GENERIC, "NULL pointer!");
|
|
246
|
+
FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) , "");
|
|
209
247
|
memset(cctxParams, 0, sizeof(*cctxParams));
|
|
248
|
+
assert(!ZSTD_checkCParams(params.cParams));
|
|
210
249
|
cctxParams->cParams = params.cParams;
|
|
211
250
|
cctxParams->fParams = params.fParams;
|
|
212
251
|
cctxParams->compressionLevel = ZSTD_CLEVEL_DEFAULT; /* should not matter, as all cParams are presumed properly defined */
|
|
213
|
-
assert(!ZSTD_checkCParams(params.cParams));
|
|
214
252
|
return 0;
|
|
215
253
|
}
|
|
216
254
|
|
|
217
255
|
/* ZSTD_assignParamsToCCtxParams() :
|
|
218
256
|
* params is presumed valid at this stage */
|
|
219
257
|
static ZSTD_CCtx_params ZSTD_assignParamsToCCtxParams(
|
|
220
|
-
ZSTD_CCtx_params cctxParams, ZSTD_parameters params)
|
|
258
|
+
const ZSTD_CCtx_params* cctxParams, const ZSTD_parameters* params)
|
|
221
259
|
{
|
|
222
|
-
ZSTD_CCtx_params ret = cctxParams;
|
|
223
|
-
|
|
224
|
-
ret.
|
|
260
|
+
ZSTD_CCtx_params ret = *cctxParams;
|
|
261
|
+
assert(!ZSTD_checkCParams(params->cParams));
|
|
262
|
+
ret.cParams = params->cParams;
|
|
263
|
+
ret.fParams = params->fParams;
|
|
225
264
|
ret.compressionLevel = ZSTD_CLEVEL_DEFAULT; /* should not matter, as all cParams are presumed properly defined */
|
|
226
|
-
assert(!ZSTD_checkCParams(params.cParams));
|
|
227
265
|
return ret;
|
|
228
266
|
}
|
|
229
267
|
|
|
@@ -307,8 +345,13 @@ ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param)
|
|
|
307
345
|
return bounds;
|
|
308
346
|
|
|
309
347
|
case ZSTD_c_overlapLog:
|
|
348
|
+
#ifdef ZSTD_MULTITHREAD
|
|
310
349
|
bounds.lowerBound = ZSTD_OVERLAPLOG_MIN;
|
|
311
350
|
bounds.upperBound = ZSTD_OVERLAPLOG_MAX;
|
|
351
|
+
#else
|
|
352
|
+
bounds.lowerBound = 0;
|
|
353
|
+
bounds.upperBound = 0;
|
|
354
|
+
#endif
|
|
312
355
|
return bounds;
|
|
313
356
|
|
|
314
357
|
case ZSTD_c_enableLongDistanceMatching:
|
|
@@ -356,32 +399,47 @@ ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param)
|
|
|
356
399
|
case ZSTD_c_forceAttachDict:
|
|
357
400
|
ZSTD_STATIC_ASSERT(ZSTD_dictDefaultAttach < ZSTD_dictForceCopy);
|
|
358
401
|
bounds.lowerBound = ZSTD_dictDefaultAttach;
|
|
359
|
-
bounds.upperBound =
|
|
402
|
+
bounds.upperBound = ZSTD_dictForceLoad; /* note : how to ensure at compile time that this is the highest value enum ? */
|
|
403
|
+
return bounds;
|
|
404
|
+
|
|
405
|
+
case ZSTD_c_literalCompressionMode:
|
|
406
|
+
ZSTD_STATIC_ASSERT(ZSTD_lcm_auto < ZSTD_lcm_huffman && ZSTD_lcm_huffman < ZSTD_lcm_uncompressed);
|
|
407
|
+
bounds.lowerBound = ZSTD_lcm_auto;
|
|
408
|
+
bounds.upperBound = ZSTD_lcm_uncompressed;
|
|
409
|
+
return bounds;
|
|
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;
|
|
360
419
|
return bounds;
|
|
361
420
|
|
|
362
421
|
default:
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
}
|
|
422
|
+
bounds.error = ERROR(parameter_unsupported);
|
|
423
|
+
return bounds;
|
|
366
424
|
}
|
|
367
425
|
}
|
|
368
426
|
|
|
369
|
-
/*
|
|
370
|
-
*
|
|
371
|
-
|
|
372
|
-
static
|
|
427
|
+
/* ZSTD_cParam_clampBounds:
|
|
428
|
+
* Clamps the value into the bounded range.
|
|
429
|
+
*/
|
|
430
|
+
static size_t ZSTD_cParam_clampBounds(ZSTD_cParameter cParam, int* value)
|
|
373
431
|
{
|
|
374
432
|
ZSTD_bounds const bounds = ZSTD_cParam_getBounds(cParam);
|
|
375
|
-
if (ZSTD_isError(bounds.error)) return
|
|
376
|
-
if (value < bounds.lowerBound)
|
|
377
|
-
if (value > bounds.upperBound)
|
|
378
|
-
return
|
|
433
|
+
if (ZSTD_isError(bounds.error)) return bounds.error;
|
|
434
|
+
if (*value < bounds.lowerBound) *value = bounds.lowerBound;
|
|
435
|
+
if (*value > bounds.upperBound) *value = bounds.upperBound;
|
|
436
|
+
return 0;
|
|
379
437
|
}
|
|
380
438
|
|
|
381
|
-
#define BOUNDCHECK(cParam, val) {
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
}
|
|
439
|
+
#define BOUNDCHECK(cParam, val) { \
|
|
440
|
+
RETURN_ERROR_IF(!ZSTD_cParam_withinBounds(cParam,val), \
|
|
441
|
+
parameter_outOfBound, "Param out of bounds"); \
|
|
442
|
+
}
|
|
385
443
|
|
|
386
444
|
|
|
387
445
|
static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param)
|
|
@@ -413,6 +471,9 @@ static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param)
|
|
|
413
471
|
case ZSTD_c_ldmBucketSizeLog:
|
|
414
472
|
case ZSTD_c_ldmHashRateLog:
|
|
415
473
|
case ZSTD_c_forceAttachDict:
|
|
474
|
+
case ZSTD_c_literalCompressionMode:
|
|
475
|
+
case ZSTD_c_targetCBlockSize:
|
|
476
|
+
case ZSTD_c_srcSizeHint:
|
|
416
477
|
default:
|
|
417
478
|
return 0;
|
|
418
479
|
}
|
|
@@ -425,18 +486,17 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value)
|
|
|
425
486
|
if (ZSTD_isUpdateAuthorized(param)) {
|
|
426
487
|
cctx->cParamsChanged = 1;
|
|
427
488
|
} else {
|
|
428
|
-
|
|
489
|
+
RETURN_ERROR(stage_wrong, "can only set params in ctx init stage");
|
|
429
490
|
} }
|
|
430
491
|
|
|
431
492
|
switch(param)
|
|
432
493
|
{
|
|
433
|
-
case
|
|
434
|
-
|
|
494
|
+
case ZSTD_c_nbWorkers:
|
|
495
|
+
RETURN_ERROR_IF((value!=0) && cctx->staticSize, parameter_unsupported,
|
|
496
|
+
"MT not compatible with static alloc");
|
|
497
|
+
break;
|
|
435
498
|
|
|
436
499
|
case ZSTD_c_compressionLevel:
|
|
437
|
-
if (cctx->cdict) return ERROR(stage_wrong);
|
|
438
|
-
return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
|
|
439
|
-
|
|
440
500
|
case ZSTD_c_windowLog:
|
|
441
501
|
case ZSTD_c_hashLog:
|
|
442
502
|
case ZSTD_c_chainLog:
|
|
@@ -444,49 +504,34 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value)
|
|
|
444
504
|
case ZSTD_c_minMatch:
|
|
445
505
|
case ZSTD_c_targetLength:
|
|
446
506
|
case ZSTD_c_strategy:
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
507
|
+
case ZSTD_c_ldmHashRateLog:
|
|
508
|
+
case ZSTD_c_format:
|
|
450
509
|
case ZSTD_c_contentSizeFlag:
|
|
451
510
|
case ZSTD_c_checksumFlag:
|
|
452
511
|
case ZSTD_c_dictIDFlag:
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
case ZSTD_c_forceMaxWindow : /* Force back-references to remain < windowSize,
|
|
456
|
-
* even when referencing into Dictionary content.
|
|
457
|
-
* default : 0 when using a CDict, 1 when using a Prefix */
|
|
458
|
-
return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
|
|
459
|
-
|
|
512
|
+
case ZSTD_c_forceMaxWindow:
|
|
460
513
|
case ZSTD_c_forceAttachDict:
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
case ZSTD_c_nbWorkers:
|
|
464
|
-
if ((value!=0) && cctx->staticSize) {
|
|
465
|
-
return ERROR(parameter_unsupported); /* MT not compatible with static alloc */
|
|
466
|
-
}
|
|
467
|
-
return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
|
|
468
|
-
|
|
514
|
+
case ZSTD_c_literalCompressionMode:
|
|
469
515
|
case ZSTD_c_jobSize:
|
|
470
516
|
case ZSTD_c_overlapLog:
|
|
471
517
|
case ZSTD_c_rsyncable:
|
|
472
|
-
return ZSTD_CCtxParam_setParameter(&cctx->requestedParams, param, value);
|
|
473
|
-
|
|
474
518
|
case ZSTD_c_enableLongDistanceMatching:
|
|
475
519
|
case ZSTD_c_ldmHashLog:
|
|
476
520
|
case ZSTD_c_ldmMinMatch:
|
|
477
521
|
case ZSTD_c_ldmBucketSizeLog:
|
|
478
|
-
case
|
|
479
|
-
|
|
480
|
-
|
|
522
|
+
case ZSTD_c_targetCBlockSize:
|
|
523
|
+
case ZSTD_c_srcSizeHint:
|
|
524
|
+
break;
|
|
481
525
|
|
|
482
|
-
default:
|
|
526
|
+
default: RETURN_ERROR(parameter_unsupported, "unknown parameter");
|
|
483
527
|
}
|
|
528
|
+
return ZSTD_CCtxParams_setParameter(&cctx->requestedParams, param, value);
|
|
484
529
|
}
|
|
485
530
|
|
|
486
|
-
size_t
|
|
487
|
-
|
|
531
|
+
size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
|
|
532
|
+
ZSTD_cParameter param, int value)
|
|
488
533
|
{
|
|
489
|
-
DEBUGLOG(4, "
|
|
534
|
+
DEBUGLOG(4, "ZSTD_CCtxParams_setParameter (%i, %i)", (int)param, value);
|
|
490
535
|
switch(param)
|
|
491
536
|
{
|
|
492
537
|
case ZSTD_c_format :
|
|
@@ -495,39 +540,37 @@ size_t ZSTD_CCtxParam_setParameter(ZSTD_CCtx_params* CCtxParams,
|
|
|
495
540
|
return (size_t)CCtxParams->format;
|
|
496
541
|
|
|
497
542
|
case ZSTD_c_compressionLevel : {
|
|
498
|
-
|
|
499
|
-
if (
|
|
500
|
-
|
|
501
|
-
if (cLevel) { /* 0 : does not change current level */
|
|
502
|
-
CCtxParams->compressionLevel = cLevel;
|
|
543
|
+
FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value), "");
|
|
544
|
+
if (value) { /* 0 : does not change current level */
|
|
545
|
+
CCtxParams->compressionLevel = value;
|
|
503
546
|
}
|
|
504
|
-
if (CCtxParams->compressionLevel >= 0) return CCtxParams->compressionLevel;
|
|
547
|
+
if (CCtxParams->compressionLevel >= 0) return (size_t)CCtxParams->compressionLevel;
|
|
505
548
|
return 0; /* return type (size_t) cannot represent negative values */
|
|
506
549
|
}
|
|
507
550
|
|
|
508
551
|
case ZSTD_c_windowLog :
|
|
509
552
|
if (value!=0) /* 0 => use default */
|
|
510
553
|
BOUNDCHECK(ZSTD_c_windowLog, value);
|
|
511
|
-
CCtxParams->cParams.windowLog = value;
|
|
554
|
+
CCtxParams->cParams.windowLog = (U32)value;
|
|
512
555
|
return CCtxParams->cParams.windowLog;
|
|
513
556
|
|
|
514
557
|
case ZSTD_c_hashLog :
|
|
515
558
|
if (value!=0) /* 0 => use default */
|
|
516
559
|
BOUNDCHECK(ZSTD_c_hashLog, value);
|
|
517
|
-
CCtxParams->cParams.hashLog = value;
|
|
560
|
+
CCtxParams->cParams.hashLog = (U32)value;
|
|
518
561
|
return CCtxParams->cParams.hashLog;
|
|
519
562
|
|
|
520
563
|
case ZSTD_c_chainLog :
|
|
521
564
|
if (value!=0) /* 0 => use default */
|
|
522
565
|
BOUNDCHECK(ZSTD_c_chainLog, value);
|
|
523
|
-
CCtxParams->cParams.chainLog = value;
|
|
566
|
+
CCtxParams->cParams.chainLog = (U32)value;
|
|
524
567
|
return CCtxParams->cParams.chainLog;
|
|
525
568
|
|
|
526
569
|
case ZSTD_c_searchLog :
|
|
527
570
|
if (value!=0) /* 0 => use default */
|
|
528
571
|
BOUNDCHECK(ZSTD_c_searchLog, value);
|
|
529
|
-
CCtxParams->cParams.searchLog = value;
|
|
530
|
-
return value;
|
|
572
|
+
CCtxParams->cParams.searchLog = (U32)value;
|
|
573
|
+
return (size_t)value;
|
|
531
574
|
|
|
532
575
|
case ZSTD_c_minMatch :
|
|
533
576
|
if (value!=0) /* 0 => use default */
|
|
@@ -573,33 +616,55 @@ size_t ZSTD_CCtxParam_setParameter(ZSTD_CCtx_params* CCtxParams,
|
|
|
573
616
|
return CCtxParams->attachDictPref;
|
|
574
617
|
}
|
|
575
618
|
|
|
619
|
+
case ZSTD_c_literalCompressionMode : {
|
|
620
|
+
const ZSTD_literalCompressionMode_e lcm = (ZSTD_literalCompressionMode_e)value;
|
|
621
|
+
BOUNDCHECK(ZSTD_c_literalCompressionMode, lcm);
|
|
622
|
+
CCtxParams->literalCompressionMode = lcm;
|
|
623
|
+
return CCtxParams->literalCompressionMode;
|
|
624
|
+
}
|
|
625
|
+
|
|
576
626
|
case ZSTD_c_nbWorkers :
|
|
577
627
|
#ifndef ZSTD_MULTITHREAD
|
|
578
|
-
|
|
628
|
+
RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading");
|
|
579
629
|
return 0;
|
|
580
630
|
#else
|
|
581
|
-
|
|
631
|
+
FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value), "");
|
|
632
|
+
CCtxParams->nbWorkers = value;
|
|
633
|
+
return CCtxParams->nbWorkers;
|
|
582
634
|
#endif
|
|
583
635
|
|
|
584
636
|
case ZSTD_c_jobSize :
|
|
585
637
|
#ifndef ZSTD_MULTITHREAD
|
|
586
|
-
|
|
638
|
+
RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading");
|
|
639
|
+
return 0;
|
|
587
640
|
#else
|
|
588
|
-
|
|
641
|
+
/* Adjust to the minimum non-default value. */
|
|
642
|
+
if (value != 0 && value < ZSTDMT_JOBSIZE_MIN)
|
|
643
|
+
value = ZSTDMT_JOBSIZE_MIN;
|
|
644
|
+
FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value), "");
|
|
645
|
+
assert(value >= 0);
|
|
646
|
+
CCtxParams->jobSize = value;
|
|
647
|
+
return CCtxParams->jobSize;
|
|
589
648
|
#endif
|
|
590
649
|
|
|
591
650
|
case ZSTD_c_overlapLog :
|
|
592
651
|
#ifndef ZSTD_MULTITHREAD
|
|
593
|
-
|
|
652
|
+
RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading");
|
|
653
|
+
return 0;
|
|
594
654
|
#else
|
|
595
|
-
|
|
655
|
+
FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(ZSTD_c_overlapLog, &value), "");
|
|
656
|
+
CCtxParams->overlapLog = value;
|
|
657
|
+
return CCtxParams->overlapLog;
|
|
596
658
|
#endif
|
|
597
659
|
|
|
598
660
|
case ZSTD_c_rsyncable :
|
|
599
661
|
#ifndef ZSTD_MULTITHREAD
|
|
600
|
-
|
|
662
|
+
RETURN_ERROR_IF(value!=0, parameter_unsupported, "not compiled with multithreading");
|
|
663
|
+
return 0;
|
|
601
664
|
#else
|
|
602
|
-
|
|
665
|
+
FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(ZSTD_c_overlapLog, &value), "");
|
|
666
|
+
CCtxParams->rsyncable = value;
|
|
667
|
+
return CCtxParams->rsyncable;
|
|
603
668
|
#endif
|
|
604
669
|
|
|
605
670
|
case ZSTD_c_enableLongDistanceMatching :
|
|
@@ -625,21 +690,33 @@ size_t ZSTD_CCtxParam_setParameter(ZSTD_CCtx_params* CCtxParams,
|
|
|
625
690
|
return CCtxParams->ldmParams.bucketSizeLog;
|
|
626
691
|
|
|
627
692
|
case ZSTD_c_ldmHashRateLog :
|
|
628
|
-
|
|
629
|
-
|
|
693
|
+
RETURN_ERROR_IF(value > ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN,
|
|
694
|
+
parameter_outOfBound, "Param out of bounds!");
|
|
630
695
|
CCtxParams->ldmParams.hashRateLog = value;
|
|
631
696
|
return CCtxParams->ldmParams.hashRateLog;
|
|
632
697
|
|
|
633
|
-
|
|
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
|
+
|
|
710
|
+
default: RETURN_ERROR(parameter_unsupported, "unknown parameter");
|
|
634
711
|
}
|
|
635
712
|
}
|
|
636
713
|
|
|
637
714
|
size_t ZSTD_CCtx_getParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int* value)
|
|
638
715
|
{
|
|
639
|
-
return
|
|
716
|
+
return ZSTD_CCtxParams_getParameter(&cctx->requestedParams, param, value);
|
|
640
717
|
}
|
|
641
718
|
|
|
642
|
-
size_t
|
|
719
|
+
size_t ZSTD_CCtxParams_getParameter(
|
|
643
720
|
ZSTD_CCtx_params* CCtxParams, ZSTD_cParameter param, int* value)
|
|
644
721
|
{
|
|
645
722
|
switch(param)
|
|
@@ -651,13 +728,13 @@ size_t ZSTD_CCtxParam_getParameter(
|
|
|
651
728
|
*value = CCtxParams->compressionLevel;
|
|
652
729
|
break;
|
|
653
730
|
case ZSTD_c_windowLog :
|
|
654
|
-
*value = CCtxParams->cParams.windowLog;
|
|
731
|
+
*value = (int)CCtxParams->cParams.windowLog;
|
|
655
732
|
break;
|
|
656
733
|
case ZSTD_c_hashLog :
|
|
657
|
-
*value = CCtxParams->cParams.hashLog;
|
|
734
|
+
*value = (int)CCtxParams->cParams.hashLog;
|
|
658
735
|
break;
|
|
659
736
|
case ZSTD_c_chainLog :
|
|
660
|
-
*value = CCtxParams->cParams.chainLog;
|
|
737
|
+
*value = (int)CCtxParams->cParams.chainLog;
|
|
661
738
|
break;
|
|
662
739
|
case ZSTD_c_searchLog :
|
|
663
740
|
*value = CCtxParams->cParams.searchLog;
|
|
@@ -686,6 +763,9 @@ size_t ZSTD_CCtxParam_getParameter(
|
|
|
686
763
|
case ZSTD_c_forceAttachDict :
|
|
687
764
|
*value = CCtxParams->attachDictPref;
|
|
688
765
|
break;
|
|
766
|
+
case ZSTD_c_literalCompressionMode :
|
|
767
|
+
*value = CCtxParams->literalCompressionMode;
|
|
768
|
+
break;
|
|
689
769
|
case ZSTD_c_nbWorkers :
|
|
690
770
|
#ifndef ZSTD_MULTITHREAD
|
|
691
771
|
assert(CCtxParams->nbWorkers == 0);
|
|
@@ -694,7 +774,7 @@ size_t ZSTD_CCtxParam_getParameter(
|
|
|
694
774
|
break;
|
|
695
775
|
case ZSTD_c_jobSize :
|
|
696
776
|
#ifndef ZSTD_MULTITHREAD
|
|
697
|
-
|
|
777
|
+
RETURN_ERROR(parameter_unsupported, "not compiled with multithreading");
|
|
698
778
|
#else
|
|
699
779
|
assert(CCtxParams->jobSize <= INT_MAX);
|
|
700
780
|
*value = (int)CCtxParams->jobSize;
|
|
@@ -702,14 +782,14 @@ size_t ZSTD_CCtxParam_getParameter(
|
|
|
702
782
|
#endif
|
|
703
783
|
case ZSTD_c_overlapLog :
|
|
704
784
|
#ifndef ZSTD_MULTITHREAD
|
|
705
|
-
|
|
785
|
+
RETURN_ERROR(parameter_unsupported, "not compiled with multithreading");
|
|
706
786
|
#else
|
|
707
787
|
*value = CCtxParams->overlapLog;
|
|
708
788
|
break;
|
|
709
789
|
#endif
|
|
710
790
|
case ZSTD_c_rsyncable :
|
|
711
791
|
#ifndef ZSTD_MULTITHREAD
|
|
712
|
-
|
|
792
|
+
RETURN_ERROR(parameter_unsupported, "not compiled with multithreading");
|
|
713
793
|
#else
|
|
714
794
|
*value = CCtxParams->rsyncable;
|
|
715
795
|
break;
|
|
@@ -729,7 +809,13 @@ size_t ZSTD_CCtxParam_getParameter(
|
|
|
729
809
|
case ZSTD_c_ldmHashRateLog :
|
|
730
810
|
*value = CCtxParams->ldmParams.hashRateLog;
|
|
731
811
|
break;
|
|
732
|
-
|
|
812
|
+
case ZSTD_c_targetCBlockSize :
|
|
813
|
+
*value = (int)CCtxParams->targetCBlockSize;
|
|
814
|
+
break;
|
|
815
|
+
case ZSTD_c_srcSizeHint :
|
|
816
|
+
*value = (int)CCtxParams->srcSizeHint;
|
|
817
|
+
break;
|
|
818
|
+
default: RETURN_ERROR(parameter_unsupported, "unknown parameter");
|
|
733
819
|
}
|
|
734
820
|
return 0;
|
|
735
821
|
}
|
|
@@ -745,8 +831,11 @@ size_t ZSTD_CCtx_setParametersUsingCCtxParams(
|
|
|
745
831
|
ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params)
|
|
746
832
|
{
|
|
747
833
|
DEBUGLOG(4, "ZSTD_CCtx_setParametersUsingCCtxParams");
|
|
748
|
-
|
|
749
|
-
|
|
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).");
|
|
750
839
|
|
|
751
840
|
cctx->requestedParams = *params;
|
|
752
841
|
return 0;
|
|
@@ -755,33 +844,73 @@ size_t ZSTD_CCtx_setParametersUsingCCtxParams(
|
|
|
755
844
|
ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize)
|
|
756
845
|
{
|
|
757
846
|
DEBUGLOG(4, "ZSTD_CCtx_setPledgedSrcSize to %u bytes", (U32)pledgedSrcSize);
|
|
758
|
-
|
|
847
|
+
RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
|
|
848
|
+
"Can't set pledgedSrcSize when not in init stage.");
|
|
759
849
|
cctx->pledgedSrcSizePlusOne = pledgedSrcSize+1;
|
|
760
850
|
return 0;
|
|
761
851
|
}
|
|
762
852
|
|
|
853
|
+
/**
|
|
854
|
+
* Initializes the local dict using the requested parameters.
|
|
855
|
+
* NOTE: This does not use the pledged src size, because it may be used for more
|
|
856
|
+
* than one compression.
|
|
857
|
+
*/
|
|
858
|
+
static size_t ZSTD_initLocalDict(ZSTD_CCtx* cctx)
|
|
859
|
+
{
|
|
860
|
+
ZSTD_localDict* const dl = &cctx->localDict;
|
|
861
|
+
ZSTD_compressionParameters const cParams = ZSTD_getCParamsFromCCtxParams(
|
|
862
|
+
&cctx->requestedParams, ZSTD_CONTENTSIZE_UNKNOWN, dl->dictSize);
|
|
863
|
+
if (dl->dict == NULL) {
|
|
864
|
+
/* No local dictionary. */
|
|
865
|
+
assert(dl->dictBuffer == NULL);
|
|
866
|
+
assert(dl->cdict == NULL);
|
|
867
|
+
assert(dl->dictSize == 0);
|
|
868
|
+
return 0;
|
|
869
|
+
}
|
|
870
|
+
if (dl->cdict != NULL) {
|
|
871
|
+
assert(cctx->cdict == dl->cdict);
|
|
872
|
+
/* Local dictionary already initialized. */
|
|
873
|
+
return 0;
|
|
874
|
+
}
|
|
875
|
+
assert(dl->dictSize > 0);
|
|
876
|
+
assert(cctx->cdict == NULL);
|
|
877
|
+
assert(cctx->prefixDict.dict == NULL);
|
|
878
|
+
|
|
879
|
+
dl->cdict = ZSTD_createCDict_advanced(
|
|
880
|
+
dl->dict,
|
|
881
|
+
dl->dictSize,
|
|
882
|
+
ZSTD_dlm_byRef,
|
|
883
|
+
dl->dictContentType,
|
|
884
|
+
cParams,
|
|
885
|
+
cctx->customMem);
|
|
886
|
+
RETURN_ERROR_IF(!dl->cdict, memory_allocation, "ZSTD_createCDict_advanced failed");
|
|
887
|
+
cctx->cdict = dl->cdict;
|
|
888
|
+
return 0;
|
|
889
|
+
}
|
|
890
|
+
|
|
763
891
|
size_t ZSTD_CCtx_loadDictionary_advanced(
|
|
764
892
|
ZSTD_CCtx* cctx, const void* dict, size_t dictSize,
|
|
765
893
|
ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType)
|
|
766
894
|
{
|
|
767
|
-
|
|
768
|
-
|
|
895
|
+
RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
|
|
896
|
+
"Can't load a dictionary when ctx is not in init stage.");
|
|
897
|
+
RETURN_ERROR_IF(cctx->staticSize, memory_allocation,
|
|
898
|
+
"no malloc for static CCtx");
|
|
769
899
|
DEBUGLOG(4, "ZSTD_CCtx_loadDictionary_advanced (size: %u)", (U32)dictSize);
|
|
770
|
-
|
|
771
|
-
if (dict==NULL || dictSize==0)
|
|
772
|
-
|
|
773
|
-
|
|
900
|
+
ZSTD_clearAllDicts(cctx); /* in case one already exists */
|
|
901
|
+
if (dict == NULL || dictSize == 0) /* no dictionary mode */
|
|
902
|
+
return 0;
|
|
903
|
+
if (dictLoadMethod == ZSTD_dlm_byRef) {
|
|
904
|
+
cctx->localDict.dict = dict;
|
|
774
905
|
} else {
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
cParams, cctx->customMem);
|
|
781
|
-
cctx->cdict = cctx->cdictLocal;
|
|
782
|
-
if (cctx->cdictLocal == NULL)
|
|
783
|
-
return ERROR(memory_allocation);
|
|
906
|
+
void* dictBuffer = ZSTD_malloc(dictSize, cctx->customMem);
|
|
907
|
+
RETURN_ERROR_IF(!dictBuffer, memory_allocation, "NULL pointer!");
|
|
908
|
+
memcpy(dictBuffer, dict, dictSize);
|
|
909
|
+
cctx->localDict.dictBuffer = dictBuffer;
|
|
910
|
+
cctx->localDict.dict = dictBuffer;
|
|
784
911
|
}
|
|
912
|
+
cctx->localDict.dictSize = dictSize;
|
|
913
|
+
cctx->localDict.dictContentType = dictContentType;
|
|
785
914
|
return 0;
|
|
786
915
|
}
|
|
787
916
|
|
|
@@ -801,9 +930,11 @@ ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, s
|
|
|
801
930
|
|
|
802
931
|
size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict)
|
|
803
932
|
{
|
|
804
|
-
|
|
933
|
+
RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
|
|
934
|
+
"Can't ref a dict when ctx not in init stage.");
|
|
935
|
+
/* Free the existing local cdict (if any) to save memory. */
|
|
936
|
+
ZSTD_clearAllDicts(cctx);
|
|
805
937
|
cctx->cdict = cdict;
|
|
806
|
-
memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); /* exclusive */
|
|
807
938
|
return 0;
|
|
808
939
|
}
|
|
809
940
|
|
|
@@ -815,11 +946,14 @@ size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSiz
|
|
|
815
946
|
size_t ZSTD_CCtx_refPrefix_advanced(
|
|
816
947
|
ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType)
|
|
817
948
|
{
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
cctx
|
|
821
|
-
|
|
822
|
-
|
|
949
|
+
RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
|
|
950
|
+
"Can't ref a prefix when ctx not in init stage.");
|
|
951
|
+
ZSTD_clearAllDicts(cctx);
|
|
952
|
+
if (prefix != NULL && prefixSize > 0) {
|
|
953
|
+
cctx->prefixDict.dict = prefix;
|
|
954
|
+
cctx->prefixDict.dictSize = prefixSize;
|
|
955
|
+
cctx->prefixDict.dictContentType = dictContentType;
|
|
956
|
+
}
|
|
823
957
|
return 0;
|
|
824
958
|
}
|
|
825
959
|
|
|
@@ -834,8 +968,9 @@ size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset)
|
|
|
834
968
|
}
|
|
835
969
|
if ( (reset == ZSTD_reset_parameters)
|
|
836
970
|
|| (reset == ZSTD_reset_session_and_parameters) ) {
|
|
837
|
-
|
|
838
|
-
|
|
971
|
+
RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
|
|
972
|
+
"Can't reset parameters only when not in init stage.");
|
|
973
|
+
ZSTD_clearAllDicts(cctx);
|
|
839
974
|
return ZSTD_CCtxParams_reset(&cctx->requestedParams);
|
|
840
975
|
}
|
|
841
976
|
return 0;
|
|
@@ -847,12 +982,12 @@ size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset)
|
|
|
847
982
|
@return : 0, or an error code if one value is beyond authorized range */
|
|
848
983
|
size_t ZSTD_checkCParams(ZSTD_compressionParameters cParams)
|
|
849
984
|
{
|
|
850
|
-
BOUNDCHECK(ZSTD_c_windowLog, cParams.windowLog);
|
|
851
|
-
BOUNDCHECK(ZSTD_c_chainLog, cParams.chainLog);
|
|
852
|
-
BOUNDCHECK(ZSTD_c_hashLog, cParams.hashLog);
|
|
853
|
-
BOUNDCHECK(ZSTD_c_searchLog, cParams.searchLog);
|
|
854
|
-
BOUNDCHECK(ZSTD_c_minMatch, cParams.minMatch);
|
|
855
|
-
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);
|
|
856
991
|
BOUNDCHECK(ZSTD_c_strategy, cParams.strategy);
|
|
857
992
|
return 0;
|
|
858
993
|
}
|
|
@@ -868,7 +1003,7 @@ ZSTD_clampCParams(ZSTD_compressionParameters cParams)
|
|
|
868
1003
|
if ((int)val<bounds.lowerBound) val=(type)bounds.lowerBound; \
|
|
869
1004
|
else if ((int)val>bounds.upperBound) val=(type)bounds.upperBound; \
|
|
870
1005
|
}
|
|
871
|
-
# define CLAMP(cParam, val) CLAMP_TYPE(cParam, val,
|
|
1006
|
+
# define CLAMP(cParam, val) CLAMP_TYPE(cParam, val, unsigned)
|
|
872
1007
|
CLAMP(ZSTD_c_windowLog, cParams.windowLog);
|
|
873
1008
|
CLAMP(ZSTD_c_chainLog, cParams.chainLog);
|
|
874
1009
|
CLAMP(ZSTD_c_hashLog, cParams.hashLog);
|
|
@@ -881,17 +1016,18 @@ ZSTD_clampCParams(ZSTD_compressionParameters cParams)
|
|
|
881
1016
|
|
|
882
1017
|
/** ZSTD_cycleLog() :
|
|
883
1018
|
* condition for correct operation : hashLog > 1 */
|
|
884
|
-
|
|
1019
|
+
U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat)
|
|
885
1020
|
{
|
|
886
1021
|
U32 const btScale = ((U32)strat >= (U32)ZSTD_btlazy2);
|
|
887
1022
|
return hashLog - btScale;
|
|
888
1023
|
}
|
|
889
1024
|
|
|
890
1025
|
/** ZSTD_adjustCParams_internal() :
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
1026
|
+
* optimize `cPar` for a specified input (`srcSize` and `dictSize`).
|
|
1027
|
+
* mostly downsize to reduce memory consumption and initialization latency.
|
|
1028
|
+
* `srcSize` can be ZSTD_CONTENTSIZE_UNKNOWN when not known.
|
|
1029
|
+
* note : `srcSize==0` means 0!
|
|
1030
|
+
* condition : cPar is presumed validated (can be checked using ZSTD_checkCParams()). */
|
|
895
1031
|
static ZSTD_compressionParameters
|
|
896
1032
|
ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar,
|
|
897
1033
|
unsigned long long srcSize,
|
|
@@ -901,10 +1037,8 @@ ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar,
|
|
|
901
1037
|
static const U64 maxWindowResize = 1ULL << (ZSTD_WINDOWLOG_MAX-1);
|
|
902
1038
|
assert(ZSTD_checkCParams(cPar)==0);
|
|
903
1039
|
|
|
904
|
-
if (dictSize &&
|
|
905
|
-
srcSize = minSrcSize;
|
|
906
|
-
else if (srcSize == 0)
|
|
907
|
-
srcSize = ZSTD_CONTENTSIZE_UNKNOWN; /* 0 == unknown : presumed large */
|
|
1040
|
+
if (dictSize && srcSize == ZSTD_CONTENTSIZE_UNKNOWN)
|
|
1041
|
+
srcSize = minSrcSize;
|
|
908
1042
|
|
|
909
1043
|
/* resize windowLog if input is small enough, to use less memory */
|
|
910
1044
|
if ( (srcSize < maxWindowResize)
|
|
@@ -922,7 +1056,7 @@ ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar,
|
|
|
922
1056
|
}
|
|
923
1057
|
|
|
924
1058
|
if (cPar.windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN)
|
|
925
|
-
cPar.windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN; /* required for frame header */
|
|
1059
|
+
cPar.windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN; /* minimum wlog required for valid frame header */
|
|
926
1060
|
|
|
927
1061
|
return cPar;
|
|
928
1062
|
}
|
|
@@ -932,14 +1066,22 @@ ZSTD_adjustCParams(ZSTD_compressionParameters cPar,
|
|
|
932
1066
|
unsigned long long srcSize,
|
|
933
1067
|
size_t dictSize)
|
|
934
1068
|
{
|
|
935
|
-
cPar = ZSTD_clampCParams(cPar);
|
|
1069
|
+
cPar = ZSTD_clampCParams(cPar); /* resulting cPar is necessarily valid (all parameters within range) */
|
|
1070
|
+
if (srcSize == 0) srcSize = ZSTD_CONTENTSIZE_UNKNOWN;
|
|
936
1071
|
return ZSTD_adjustCParams_internal(cPar, srcSize, dictSize);
|
|
937
1072
|
}
|
|
938
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
|
+
|
|
939
1077
|
ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
|
|
940
1078
|
const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize)
|
|
941
1079
|
{
|
|
942
|
-
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);
|
|
943
1085
|
if (CCtxParams->ldmParams.enableLdm) cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG;
|
|
944
1086
|
if (CCtxParams->cParams.windowLog) cParams.windowLog = CCtxParams->cParams.windowLog;
|
|
945
1087
|
if (CCtxParams->cParams.hashLog) cParams.hashLog = CCtxParams->cParams.hashLog;
|
|
@@ -949,6 +1091,7 @@ ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
|
|
|
949
1091
|
if (CCtxParams->cParams.targetLength) cParams.targetLength = CCtxParams->cParams.targetLength;
|
|
950
1092
|
if (CCtxParams->cParams.strategy) cParams.strategy = CCtxParams->cParams.strategy;
|
|
951
1093
|
assert(!ZSTD_checkCParams(cParams));
|
|
1094
|
+
/* srcSizeHint == 0 means 0 */
|
|
952
1095
|
return ZSTD_adjustCParams_internal(cParams, srcSizeHint, dictSize);
|
|
953
1096
|
}
|
|
954
1097
|
|
|
@@ -959,10 +1102,19 @@ ZSTD_sizeof_matchState(const ZSTD_compressionParameters* const cParams,
|
|
|
959
1102
|
size_t const chainSize = (cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cParams->chainLog);
|
|
960
1103
|
size_t const hSize = ((size_t)1) << cParams->hashLog;
|
|
961
1104
|
U32 const hashLog3 = (forCCtx && cParams->minMatch==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0;
|
|
962
|
-
size_t const h3Size = ((size_t)1) << hashLog3;
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
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));
|
|
966
1118
|
size_t const optSpace = (forCCtx && (cParams->strategy >= ZSTD_btopt))
|
|
967
1119
|
? optPotentialSpace
|
|
968
1120
|
: 0;
|
|
@@ -973,27 +1125,42 @@ ZSTD_sizeof_matchState(const ZSTD_compressionParameters* const cParams,
|
|
|
973
1125
|
|
|
974
1126
|
size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params)
|
|
975
1127
|
{
|
|
976
|
-
|
|
977
|
-
if (params->nbWorkers > 0) { return ERROR(GENERIC); }
|
|
1128
|
+
RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only.");
|
|
978
1129
|
{ ZSTD_compressionParameters const cParams =
|
|
979
|
-
ZSTD_getCParamsFromCCtxParams(params,
|
|
1130
|
+
ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0);
|
|
980
1131
|
size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog);
|
|
981
1132
|
U32 const divider = (cParams.minMatch==3) ? 3 : 4;
|
|
982
1133
|
size_t const maxNbSeq = blockSize / divider;
|
|
983
|
-
size_t const tokenSpace = WILDCOPY_OVERLENGTH + blockSize
|
|
984
|
-
|
|
985
|
-
|
|
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));
|
|
986
1139
|
size_t const matchStateSize = ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 1);
|
|
987
1140
|
|
|
988
1141
|
size_t const ldmSpace = ZSTD_ldm_getTableSize(params->ldmParams);
|
|
989
|
-
size_t const ldmSeqSpace = ZSTD_ldm_getMaxNbSeq(params->ldmParams, blockSize) * sizeof(rawSeq);
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
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;
|
|
997
1164
|
}
|
|
998
1165
|
}
|
|
999
1166
|
|
|
@@ -1005,7 +1172,7 @@ size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams)
|
|
|
1005
1172
|
|
|
1006
1173
|
static size_t ZSTD_estimateCCtxSize_internal(int compressionLevel)
|
|
1007
1174
|
{
|
|
1008
|
-
ZSTD_compressionParameters const cParams =
|
|
1175
|
+
ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0);
|
|
1009
1176
|
return ZSTD_estimateCCtxSize_usingCParams(cParams);
|
|
1010
1177
|
}
|
|
1011
1178
|
|
|
@@ -1022,12 +1189,15 @@ size_t ZSTD_estimateCCtxSize(int compressionLevel)
|
|
|
1022
1189
|
|
|
1023
1190
|
size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params)
|
|
1024
1191
|
{
|
|
1025
|
-
|
|
1026
|
-
{
|
|
1027
|
-
|
|
1028
|
-
size_t const
|
|
1192
|
+
RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only.");
|
|
1193
|
+
{ ZSTD_compressionParameters const cParams =
|
|
1194
|
+
ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0);
|
|
1195
|
+
size_t const CCtxSize = ZSTD_estimateCCtxSize_usingCCtxParams(params);
|
|
1196
|
+
size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog);
|
|
1197
|
+
size_t const inBuffSize = ((size_t)1 << cParams.windowLog) + blockSize;
|
|
1029
1198
|
size_t const outBuffSize = ZSTD_compressBound(blockSize) + 1;
|
|
1030
|
-
size_t const streamingSize = inBuffSize
|
|
1199
|
+
size_t const streamingSize = ZSTD_cwksp_alloc_size(inBuffSize)
|
|
1200
|
+
+ ZSTD_cwksp_alloc_size(outBuffSize);
|
|
1031
1201
|
|
|
1032
1202
|
return CCtxSize + streamingSize;
|
|
1033
1203
|
}
|
|
@@ -1041,7 +1211,7 @@ size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams)
|
|
|
1041
1211
|
|
|
1042
1212
|
static size_t ZSTD_estimateCStreamSize_internal(int compressionLevel)
|
|
1043
1213
|
{
|
|
1044
|
-
ZSTD_compressionParameters const cParams =
|
|
1214
|
+
ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0);
|
|
1045
1215
|
return ZSTD_estimateCStreamSize_usingCParams(cParams);
|
|
1046
1216
|
}
|
|
1047
1217
|
|
|
@@ -1095,17 +1265,6 @@ size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx)
|
|
|
1095
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 */
|
|
1096
1266
|
}
|
|
1097
1267
|
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
static U32 ZSTD_equivalentCParams(ZSTD_compressionParameters cParams1,
|
|
1101
|
-
ZSTD_compressionParameters cParams2)
|
|
1102
|
-
{
|
|
1103
|
-
return (cParams1.hashLog == cParams2.hashLog)
|
|
1104
|
-
& (cParams1.chainLog == cParams2.chainLog)
|
|
1105
|
-
& (cParams1.strategy == cParams2.strategy) /* opt parser space */
|
|
1106
|
-
& ((cParams1.minMatch==3) == (cParams2.minMatch==3)); /* hashlog3 space */
|
|
1107
|
-
}
|
|
1108
|
-
|
|
1109
1268
|
static void ZSTD_assertEqualCParams(ZSTD_compressionParameters cParams1,
|
|
1110
1269
|
ZSTD_compressionParameters cParams2)
|
|
1111
1270
|
{
|
|
@@ -1120,72 +1279,7 @@ static void ZSTD_assertEqualCParams(ZSTD_compressionParameters cParams1,
|
|
|
1120
1279
|
assert(cParams1.strategy == cParams2.strategy);
|
|
1121
1280
|
}
|
|
1122
1281
|
|
|
1123
|
-
|
|
1124
|
-
* all the parameters are equivalent. */
|
|
1125
|
-
static U32 ZSTD_equivalentLdmParams(ldmParams_t ldmParams1,
|
|
1126
|
-
ldmParams_t ldmParams2)
|
|
1127
|
-
{
|
|
1128
|
-
return (!ldmParams1.enableLdm && !ldmParams2.enableLdm) ||
|
|
1129
|
-
(ldmParams1.enableLdm == ldmParams2.enableLdm &&
|
|
1130
|
-
ldmParams1.hashLog == ldmParams2.hashLog &&
|
|
1131
|
-
ldmParams1.bucketSizeLog == ldmParams2.bucketSizeLog &&
|
|
1132
|
-
ldmParams1.minMatchLength == ldmParams2.minMatchLength &&
|
|
1133
|
-
ldmParams1.hashRateLog == ldmParams2.hashRateLog);
|
|
1134
|
-
}
|
|
1135
|
-
|
|
1136
|
-
typedef enum { ZSTDb_not_buffered, ZSTDb_buffered } ZSTD_buffered_policy_e;
|
|
1137
|
-
|
|
1138
|
-
/* ZSTD_sufficientBuff() :
|
|
1139
|
-
* check internal buffers exist for streaming if buffPol == ZSTDb_buffered .
|
|
1140
|
-
* Note : they are assumed to be correctly sized if ZSTD_equivalentCParams()==1 */
|
|
1141
|
-
static U32 ZSTD_sufficientBuff(size_t bufferSize1, size_t maxNbSeq1,
|
|
1142
|
-
size_t maxNbLit1,
|
|
1143
|
-
ZSTD_buffered_policy_e buffPol2,
|
|
1144
|
-
ZSTD_compressionParameters cParams2,
|
|
1145
|
-
U64 pledgedSrcSize)
|
|
1146
|
-
{
|
|
1147
|
-
size_t const windowSize2 = MAX(1, (size_t)MIN(((U64)1 << cParams2.windowLog), pledgedSrcSize));
|
|
1148
|
-
size_t const blockSize2 = MIN(ZSTD_BLOCKSIZE_MAX, windowSize2);
|
|
1149
|
-
size_t const maxNbSeq2 = blockSize2 / ((cParams2.minMatch == 3) ? 3 : 4);
|
|
1150
|
-
size_t const maxNbLit2 = blockSize2;
|
|
1151
|
-
size_t const neededBufferSize2 = (buffPol2==ZSTDb_buffered) ? windowSize2 + blockSize2 : 0;
|
|
1152
|
-
DEBUGLOG(4, "ZSTD_sufficientBuff: is neededBufferSize2=%u <= bufferSize1=%u",
|
|
1153
|
-
(U32)neededBufferSize2, (U32)bufferSize1);
|
|
1154
|
-
DEBUGLOG(4, "ZSTD_sufficientBuff: is maxNbSeq2=%u <= maxNbSeq1=%u",
|
|
1155
|
-
(U32)maxNbSeq2, (U32)maxNbSeq1);
|
|
1156
|
-
DEBUGLOG(4, "ZSTD_sufficientBuff: is maxNbLit2=%u <= maxNbLit1=%u",
|
|
1157
|
-
(U32)maxNbLit2, (U32)maxNbLit1);
|
|
1158
|
-
return (maxNbLit2 <= maxNbLit1)
|
|
1159
|
-
& (maxNbSeq2 <= maxNbSeq1)
|
|
1160
|
-
& (neededBufferSize2 <= bufferSize1);
|
|
1161
|
-
}
|
|
1162
|
-
|
|
1163
|
-
/** Equivalence for resetCCtx purposes */
|
|
1164
|
-
static U32 ZSTD_equivalentParams(ZSTD_CCtx_params params1,
|
|
1165
|
-
ZSTD_CCtx_params params2,
|
|
1166
|
-
size_t buffSize1,
|
|
1167
|
-
size_t maxNbSeq1, size_t maxNbLit1,
|
|
1168
|
-
ZSTD_buffered_policy_e buffPol2,
|
|
1169
|
-
U64 pledgedSrcSize)
|
|
1170
|
-
{
|
|
1171
|
-
DEBUGLOG(4, "ZSTD_equivalentParams: pledgedSrcSize=%u", (U32)pledgedSrcSize);
|
|
1172
|
-
if (!ZSTD_equivalentCParams(params1.cParams, params2.cParams)) {
|
|
1173
|
-
DEBUGLOG(4, "ZSTD_equivalentCParams() == 0");
|
|
1174
|
-
return 0;
|
|
1175
|
-
}
|
|
1176
|
-
if (!ZSTD_equivalentLdmParams(params1.ldmParams, params2.ldmParams)) {
|
|
1177
|
-
DEBUGLOG(4, "ZSTD_equivalentLdmParams() == 0");
|
|
1178
|
-
return 0;
|
|
1179
|
-
}
|
|
1180
|
-
if (!ZSTD_sufficientBuff(buffSize1, maxNbSeq1, maxNbLit1, buffPol2,
|
|
1181
|
-
params2.cParams, pledgedSrcSize)) {
|
|
1182
|
-
DEBUGLOG(4, "ZSTD_sufficientBuff() == 0");
|
|
1183
|
-
return 0;
|
|
1184
|
-
}
|
|
1185
|
-
return 1;
|
|
1186
|
-
}
|
|
1187
|
-
|
|
1188
|
-
static void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs)
|
|
1282
|
+
void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs)
|
|
1189
1283
|
{
|
|
1190
1284
|
int i;
|
|
1191
1285
|
for (i = 0; i < ZSTD_REP_NUM; ++i)
|
|
@@ -1197,132 +1291,143 @@ static void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs)
|
|
|
1197
1291
|
}
|
|
1198
1292
|
|
|
1199
1293
|
/*! ZSTD_invalidateMatchState()
|
|
1200
|
-
*
|
|
1201
|
-
*
|
|
1294
|
+
* Invalidate all the matches in the match finder tables.
|
|
1295
|
+
* Requires nextSrc and base to be set (can be NULL).
|
|
1202
1296
|
*/
|
|
1203
1297
|
static void ZSTD_invalidateMatchState(ZSTD_matchState_t* ms)
|
|
1204
1298
|
{
|
|
1205
1299
|
ZSTD_window_clear(&ms->window);
|
|
1206
1300
|
|
|
1207
1301
|
ms->nextToUpdate = ms->window.dictLimit;
|
|
1208
|
-
ms->nextToUpdate3 = ms->window.dictLimit;
|
|
1209
1302
|
ms->loadedDictEnd = 0;
|
|
1210
1303
|
ms->opt.litLengthSum = 0; /* force reset of btopt stats */
|
|
1211
1304
|
ms->dictMatchState = NULL;
|
|
1212
1305
|
}
|
|
1213
1306
|
|
|
1214
|
-
|
|
1215
|
-
*
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
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;
|
|
1221
1316
|
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
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;
|
|
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;
|
|
1242
1338
|
|
|
1243
|
-
typedef enum {
|
|
1339
|
+
typedef enum {
|
|
1340
|
+
ZSTD_resetTarget_CDict,
|
|
1341
|
+
ZSTD_resetTarget_CCtx
|
|
1342
|
+
} ZSTD_resetTarget_e;
|
|
1244
1343
|
|
|
1245
|
-
static
|
|
1344
|
+
static size_t
|
|
1246
1345
|
ZSTD_reset_matchState(ZSTD_matchState_t* ms,
|
|
1247
|
-
|
|
1346
|
+
ZSTD_cwksp* ws,
|
|
1248
1347
|
const ZSTD_compressionParameters* cParams,
|
|
1249
|
-
|
|
1348
|
+
const ZSTD_compResetPolicy_e crp,
|
|
1349
|
+
const ZSTD_indexResetPolicy_e forceResetIndex,
|
|
1350
|
+
const ZSTD_resetTarget_e forWho)
|
|
1250
1351
|
{
|
|
1251
1352
|
size_t const chainSize = (cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cParams->chainLog);
|
|
1252
1353
|
size_t const hSize = ((size_t)1) << cParams->hashLog;
|
|
1253
|
-
U32 const hashLog3 = (
|
|
1254
|
-
size_t const h3Size = ((size_t)1) << hashLog3;
|
|
1255
|
-
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;
|
|
1256
1356
|
|
|
1257
|
-
|
|
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
|
+
}
|
|
1258
1362
|
|
|
1259
1363
|
ms->hashLog3 = hashLog3;
|
|
1260
|
-
|
|
1261
|
-
ms->window.dictLimit = 1; /* start from 1, so that 1st position is valid */
|
|
1262
|
-
ms->window.lowLimit = 1; /* it ensures first and later CCtx usages compress the same */
|
|
1263
|
-
ms->window.nextSrc = ms->window.base + 1; /* see issue #1241 */
|
|
1364
|
+
|
|
1264
1365
|
ZSTD_invalidateMatchState(ms);
|
|
1265
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
|
+
|
|
1266
1385
|
/* opt parser space */
|
|
1267
|
-
if (
|
|
1386
|
+
if ((forWho == ZSTD_resetTarget_CCtx) && (cParams->strategy >= ZSTD_btopt)) {
|
|
1268
1387
|
DEBUGLOG(4, "reserving optimal parser space");
|
|
1269
|
-
ms->opt.litFreq = (unsigned*)
|
|
1270
|
-
ms->opt.litLengthFreq =
|
|
1271
|
-
ms->opt.matchLengthFreq =
|
|
1272
|
-
ms->opt.offCodeFreq =
|
|
1273
|
-
|
|
1274
|
-
ms->opt.
|
|
1275
|
-
ptr = ms->opt.matchTable + ZSTD_OPT_NUM+1;
|
|
1276
|
-
ms->opt.priceTable = (ZSTD_optimal_t*)ptr;
|
|
1277
|
-
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));
|
|
1278
1394
|
}
|
|
1279
1395
|
|
|
1280
|
-
/* table Space */
|
|
1281
|
-
DEBUGLOG(4, "reset table : %u", crp!=ZSTDcrp_noMemset);
|
|
1282
|
-
assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */
|
|
1283
|
-
if (crp!=ZSTDcrp_noMemset) memset(ptr, 0, tableSpace); /* reset tables only */
|
|
1284
|
-
ms->hashTable = (U32*)(ptr);
|
|
1285
|
-
ms->chainTable = ms->hashTable + hSize;
|
|
1286
|
-
ms->hashTable3 = ms->chainTable + chainSize;
|
|
1287
|
-
ptr = ms->hashTable3 + h3Size;
|
|
1288
|
-
|
|
1289
1396
|
ms->cParams = *cParams;
|
|
1290
1397
|
|
|
1291
|
-
|
|
1292
|
-
|
|
1398
|
+
RETURN_ERROR_IF(ZSTD_cwksp_reserve_failed(ws), memory_allocation,
|
|
1399
|
+
"failed a workspace allocation in ZSTD_reset_matchState");
|
|
1400
|
+
|
|
1401
|
+
return 0;
|
|
1293
1402
|
}
|
|
1294
1403
|
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
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
|
+
}
|
|
1301
1416
|
|
|
1302
1417
|
/*! ZSTD_resetCCtx_internal() :
|
|
1303
1418
|
note : `params` are assumed fully validated at this stage */
|
|
1304
1419
|
static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
|
|
1305
1420
|
ZSTD_CCtx_params params,
|
|
1306
|
-
U64 pledgedSrcSize,
|
|
1421
|
+
U64 const pledgedSrcSize,
|
|
1307
1422
|
ZSTD_compResetPolicy_e const crp,
|
|
1308
1423
|
ZSTD_buffered_policy_e const zbuff)
|
|
1309
1424
|
{
|
|
1425
|
+
ZSTD_cwksp* const ws = &zc->workspace;
|
|
1310
1426
|
DEBUGLOG(4, "ZSTD_resetCCtx_internal: pledgedSrcSize=%u, wlog=%u",
|
|
1311
1427
|
(U32)pledgedSrcSize, params.cParams.windowLog);
|
|
1312
1428
|
assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
|
|
1313
1429
|
|
|
1314
|
-
|
|
1315
|
-
if (ZSTD_equivalentParams(zc->appliedParams, params,
|
|
1316
|
-
zc->inBuffSize,
|
|
1317
|
-
zc->seqStore.maxNbSeq, zc->seqStore.maxNbLit,
|
|
1318
|
-
zbuff, pledgedSrcSize)) {
|
|
1319
|
-
DEBUGLOG(4, "ZSTD_equivalentParams()==1 -> continue mode (wLog1=%u, blockSize1=%zu)",
|
|
1320
|
-
zc->appliedParams.cParams.windowLog, zc->blockSize);
|
|
1321
|
-
zc->workSpaceOversizedDuration += (zc->workSpaceOversizedDuration > 0); /* if it was too large, it still is */
|
|
1322
|
-
if (zc->workSpaceOversizedDuration <= ZSTD_WORKSPACETOOLARGE_MAXDURATION)
|
|
1323
|
-
return ZSTD_continueCCtx(zc, params, pledgedSrcSize);
|
|
1324
|
-
} }
|
|
1325
|
-
DEBUGLOG(4, "ZSTD_equivalentParams()==0 -> reset CCtx");
|
|
1430
|
+
zc->isFirstBlock = 1;
|
|
1326
1431
|
|
|
1327
1432
|
if (params.ldmParams.enableLdm) {
|
|
1328
1433
|
/* Adjust long distance matching parameters */
|
|
@@ -1336,58 +1441,74 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
|
|
|
1336
1441
|
size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, windowSize);
|
|
1337
1442
|
U32 const divider = (params.cParams.minMatch==3) ? 3 : 4;
|
|
1338
1443
|
size_t const maxNbSeq = blockSize / divider;
|
|
1339
|
-
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));
|
|
1340
1447
|
size_t const buffOutSize = (zbuff==ZSTDb_buffered) ? ZSTD_compressBound(blockSize)+1 : 0;
|
|
1341
1448
|
size_t const buffInSize = (zbuff==ZSTDb_buffered) ? windowSize + blockSize : 0;
|
|
1342
1449
|
size_t const matchStateSize = ZSTD_sizeof_matchState(¶ms.cParams, /* forCCtx */ 1);
|
|
1343
1450
|
size_t const maxNbLdmSeq = ZSTD_ldm_getMaxNbSeq(params.ldmParams, blockSize);
|
|
1344
|
-
void* ptr; /* used to partition workSpace */
|
|
1345
1451
|
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
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);
|
|
1350
1465
|
size_t const ldmSpace = ZSTD_ldm_getTableSize(params.ldmParams);
|
|
1351
|
-
size_t const ldmSeqSpace = maxNbLdmSeq * sizeof(rawSeq);
|
|
1466
|
+
size_t const ldmSeqSpace = ZSTD_cwksp_alloc_size(maxNbLdmSeq * sizeof(rawSeq));
|
|
1352
1467
|
|
|
1353
|
-
size_t const neededSpace =
|
|
1354
|
-
|
|
1355
|
-
|
|
1468
|
+
size_t const neededSpace =
|
|
1469
|
+
cctxSpace +
|
|
1470
|
+
entropySpace +
|
|
1471
|
+
blockStateSpace +
|
|
1472
|
+
ldmSpace +
|
|
1473
|
+
ldmSeqSpace +
|
|
1474
|
+
matchStateSize +
|
|
1475
|
+
tokenSpace +
|
|
1476
|
+
bufferSpace;
|
|
1356
1477
|
|
|
1357
|
-
int const
|
|
1358
|
-
int const
|
|
1359
|
-
int const workSpaceWasteful = workSpaceTooLarge && (zc->workSpaceOversizedDuration > ZSTD_WORKSPACETOOLARGE_MAXDURATION);
|
|
1360
|
-
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);
|
|
1361
1480
|
|
|
1362
1481
|
DEBUGLOG(4, "Need %zuKB workspace, including %zuKB for match state, and %zuKB for buffers",
|
|
1363
1482
|
neededSpace>>10, matchStateSize>>10, bufferSpace>>10);
|
|
1364
1483
|
DEBUGLOG(4, "windowSize: %zu - blockSize: %zu", windowSize, blockSize);
|
|
1365
1484
|
|
|
1366
|
-
if (
|
|
1367
|
-
DEBUGLOG(4, "
|
|
1368
|
-
|
|
1485
|
+
if (workspaceTooSmall || workspaceWasteful) {
|
|
1486
|
+
DEBUGLOG(4, "Resize workspaceSize from %zuKB to %zuKB",
|
|
1487
|
+
ZSTD_cwksp_sizeof(ws) >> 10,
|
|
1369
1488
|
neededSpace >> 10);
|
|
1370
|
-
/* static cctx : no resize, error out */
|
|
1371
|
-
if (zc->staticSize) return ERROR(memory_allocation);
|
|
1372
1489
|
|
|
1373
|
-
zc->
|
|
1374
|
-
ZSTD_free(zc->workSpace, zc->customMem);
|
|
1375
|
-
zc->workSpace = ZSTD_malloc(neededSpace, zc->customMem);
|
|
1376
|
-
if (zc->workSpace == NULL) return ERROR(memory_allocation);
|
|
1377
|
-
zc->workSpaceSize = neededSpace;
|
|
1378
|
-
zc->workSpaceOversizedDuration = 0;
|
|
1490
|
+
RETURN_ERROR_IF(zc->staticSize, memory_allocation, "static cctx : no resize");
|
|
1379
1491
|
|
|
1492
|
+
needsIndexReset = ZSTDirp_reset;
|
|
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");
|
|
1380
1498
|
/* Statically sized space.
|
|
1381
1499
|
* entropyWorkspace never moves,
|
|
1382
1500
|
* though prev/next block swap places */
|
|
1383
|
-
assert((
|
|
1384
|
-
|
|
1385
|
-
zc->blockState.prevCBlock
|
|
1386
|
-
zc->blockState.nextCBlock =
|
|
1387
|
-
|
|
1388
|
-
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");
|
|
1389
1508
|
} }
|
|
1390
1509
|
|
|
1510
|
+
ZSTD_cwksp_clear(ws);
|
|
1511
|
+
|
|
1391
1512
|
/* init params */
|
|
1392
1513
|
zc->appliedParams = params;
|
|
1393
1514
|
zc->blockState.matchState.cParams = params.cParams;
|
|
@@ -1406,57 +1527,60 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
|
|
|
1406
1527
|
|
|
1407
1528
|
ZSTD_reset_compressedBlockState(zc->blockState.prevCBlock);
|
|
1408
1529
|
|
|
1409
|
-
ptr = zc->entropyWorkspace + HUF_WORKSPACE_SIZE_U32;
|
|
1410
|
-
|
|
1411
|
-
/* ldm hash table */
|
|
1412
|
-
/* initialize bucketOffsets table later for pointer alignment */
|
|
1413
|
-
if (params.ldmParams.enableLdm) {
|
|
1414
|
-
size_t const ldmHSize = ((size_t)1) << params.ldmParams.hashLog;
|
|
1415
|
-
memset(ptr, 0, ldmHSize * sizeof(ldmEntry_t));
|
|
1416
|
-
assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */
|
|
1417
|
-
zc->ldmState.hashTable = (ldmEntry_t*)ptr;
|
|
1418
|
-
ptr = zc->ldmState.hashTable + ldmHSize;
|
|
1419
|
-
zc->ldmSequences = (rawSeq*)ptr;
|
|
1420
|
-
ptr = zc->ldmSequences + maxNbLdmSeq;
|
|
1421
|
-
zc->maxNbLdmSequences = maxNbLdmSeq;
|
|
1422
|
-
|
|
1423
|
-
memset(&zc->ldmState.window, 0, sizeof(zc->ldmState.window));
|
|
1424
|
-
}
|
|
1425
|
-
assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */
|
|
1426
|
-
|
|
1427
|
-
ptr = ZSTD_reset_matchState(&zc->blockState.matchState, ptr, ¶ms.cParams, crp, /* forCCtx */ 1);
|
|
1428
|
-
|
|
1429
|
-
/* sequences storage */
|
|
1430
|
-
zc->seqStore.maxNbSeq = maxNbSeq;
|
|
1431
|
-
zc->seqStore.sequencesStart = (seqDef*)ptr;
|
|
1432
|
-
ptr = zc->seqStore.sequencesStart + maxNbSeq;
|
|
1433
|
-
zc->seqStore.llCode = (BYTE*) ptr;
|
|
1434
|
-
zc->seqStore.mlCode = zc->seqStore.llCode + maxNbSeq;
|
|
1435
|
-
zc->seqStore.ofCode = zc->seqStore.mlCode + maxNbSeq;
|
|
1436
|
-
zc->seqStore.litStart = zc->seqStore.ofCode + maxNbSeq;
|
|
1437
1530
|
/* ZSTD_wildcopy() is used to copy into the literals buffer,
|
|
1438
1531
|
* so we have to oversize the buffer by WILDCOPY_OVERLENGTH bytes.
|
|
1439
1532
|
*/
|
|
1533
|
+
zc->seqStore.litStart = ZSTD_cwksp_reserve_buffer(ws, blockSize + WILDCOPY_OVERLENGTH);
|
|
1440
1534
|
zc->seqStore.maxNbLit = blockSize;
|
|
1441
|
-
|
|
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);
|
|
1442
1541
|
|
|
1443
1542
|
/* ldm bucketOffsets table */
|
|
1444
1543
|
if (params.ldmParams.enableLdm) {
|
|
1544
|
+
/* TODO: avoid memset? */
|
|
1445
1545
|
size_t const ldmBucketSize =
|
|
1446
1546
|
((size_t)1) << (params.ldmParams.hashLog -
|
|
1447
1547
|
params.ldmParams.bucketSizeLog);
|
|
1448
|
-
|
|
1449
|
-
zc->ldmState.bucketOffsets
|
|
1450
|
-
ptr = zc->ldmState.bucketOffsets + ldmBucketSize;
|
|
1451
|
-
ZSTD_window_clear(&zc->ldmState.window);
|
|
1548
|
+
zc->ldmState.bucketOffsets = ZSTD_cwksp_reserve_buffer(ws, ldmBucketSize);
|
|
1549
|
+
memset(zc->ldmState.bucketOffsets, 0, ldmBucketSize);
|
|
1452
1550
|
}
|
|
1551
|
+
|
|
1552
|
+
/* sequences storage */
|
|
1453
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), "");
|
|
1454
1567
|
|
|
1455
|
-
/*
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
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;
|
|
1460
1584
|
|
|
1461
1585
|
return 0;
|
|
1462
1586
|
}
|
|
@@ -1490,40 +1614,39 @@ static const size_t attachDictSizeCutoffs[ZSTD_STRATEGY_MAX+1] = {
|
|
|
1490
1614
|
};
|
|
1491
1615
|
|
|
1492
1616
|
static int ZSTD_shouldAttachDict(const ZSTD_CDict* cdict,
|
|
1493
|
-
ZSTD_CCtx_params params,
|
|
1617
|
+
const ZSTD_CCtx_params* params,
|
|
1494
1618
|
U64 pledgedSrcSize)
|
|
1495
1619
|
{
|
|
1496
1620
|
size_t cutoff = attachDictSizeCutoffs[cdict->matchState.cParams.strategy];
|
|
1497
1621
|
return ( pledgedSrcSize <= cutoff
|
|
1498
1622
|
|| pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN
|
|
1499
|
-
|| params
|
|
1500
|
-
&& params
|
|
1501
|
-
&& !params
|
|
1623
|
+
|| params->attachDictPref == ZSTD_dictForceAttach )
|
|
1624
|
+
&& params->attachDictPref != ZSTD_dictForceCopy
|
|
1625
|
+
&& !params->forceWindow; /* dictMatchState isn't correctly
|
|
1502
1626
|
* handled in _enforceMaxDist */
|
|
1503
1627
|
}
|
|
1504
1628
|
|
|
1505
|
-
static size_t
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
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)
|
|
1511
1635
|
{
|
|
1512
|
-
{
|
|
1513
|
-
const ZSTD_compressionParameters *cdict_cParams = &cdict->matchState.cParams;
|
|
1636
|
+
{ const ZSTD_compressionParameters* const cdict_cParams = &cdict->matchState.cParams;
|
|
1514
1637
|
unsigned const windowLog = params.cParams.windowLog;
|
|
1515
1638
|
assert(windowLog != 0);
|
|
1516
1639
|
/* Resize working context table params for input only, since the dict
|
|
1517
1640
|
* has its own tables. */
|
|
1641
|
+
/* pledgeSrcSize == 0 means 0! */
|
|
1518
1642
|
params.cParams = ZSTD_adjustCParams_internal(*cdict_cParams, pledgedSrcSize, 0);
|
|
1519
1643
|
params.cParams.windowLog = windowLog;
|
|
1520
|
-
ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
|
|
1521
|
-
|
|
1644
|
+
FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
|
|
1645
|
+
ZSTDcrp_makeClean, zbuff), "");
|
|
1522
1646
|
assert(cctx->appliedParams.cParams.strategy == cdict_cParams->strategy);
|
|
1523
1647
|
}
|
|
1524
1648
|
|
|
1525
|
-
{
|
|
1526
|
-
const U32 cdictEnd = (U32)( cdict->matchState.window.nextSrc
|
|
1649
|
+
{ const U32 cdictEnd = (U32)( cdict->matchState.window.nextSrc
|
|
1527
1650
|
- cdict->matchState.window.base);
|
|
1528
1651
|
const U32 cdictLen = cdictEnd - cdict->matchState.window.dictLimit;
|
|
1529
1652
|
if (cdictLen == 0) {
|
|
@@ -1540,9 +1663,9 @@ static size_t ZSTD_resetCCtx_byAttachingCDict(
|
|
|
1540
1663
|
cctx->blockState.matchState.window.base + cdictEnd;
|
|
1541
1664
|
ZSTD_window_clear(&cctx->blockState.matchState.window);
|
|
1542
1665
|
}
|
|
1666
|
+
/* loadedDictEnd is expressed within the referential of the active context */
|
|
1543
1667
|
cctx->blockState.matchState.loadedDictEnd = cctx->blockState.matchState.window.dictLimit;
|
|
1544
|
-
|
|
1545
|
-
}
|
|
1668
|
+
} }
|
|
1546
1669
|
|
|
1547
1670
|
cctx->dictID = cdict->dictID;
|
|
1548
1671
|
|
|
@@ -1567,36 +1690,41 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx,
|
|
|
1567
1690
|
/* Copy only compression parameters related to tables. */
|
|
1568
1691
|
params.cParams = *cdict_cParams;
|
|
1569
1692
|
params.cParams.windowLog = windowLog;
|
|
1570
|
-
ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
|
|
1571
|
-
|
|
1693
|
+
FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
|
|
1694
|
+
ZSTDcrp_leaveDirty, zbuff), "");
|
|
1572
1695
|
assert(cctx->appliedParams.cParams.strategy == cdict_cParams->strategy);
|
|
1573
1696
|
assert(cctx->appliedParams.cParams.hashLog == cdict_cParams->hashLog);
|
|
1574
1697
|
assert(cctx->appliedParams.cParams.chainLog == cdict_cParams->chainLog);
|
|
1575
1698
|
}
|
|
1576
1699
|
|
|
1700
|
+
ZSTD_cwksp_mark_tables_dirty(&cctx->workspace);
|
|
1701
|
+
|
|
1577
1702
|
/* copy tables */
|
|
1578
1703
|
{ size_t const chainSize = (cdict_cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cdict_cParams->chainLog);
|
|
1579
1704
|
size_t const hSize = (size_t)1 << cdict_cParams->hashLog;
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
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));
|
|
1586
1712
|
}
|
|
1587
1713
|
|
|
1588
1714
|
/* Zero the hashTable3, since the cdict never fills it */
|
|
1589
|
-
{
|
|
1715
|
+
{ int const h3log = cctx->blockState.matchState.hashLog3;
|
|
1716
|
+
size_t const h3Size = h3log ? ((size_t)1 << h3log) : 0;
|
|
1590
1717
|
assert(cdict->matchState.hashLog3 == 0);
|
|
1591
1718
|
memset(cctx->blockState.matchState.hashTable3, 0, h3Size * sizeof(U32));
|
|
1592
1719
|
}
|
|
1593
1720
|
|
|
1721
|
+
ZSTD_cwksp_mark_tables_clean(&cctx->workspace);
|
|
1722
|
+
|
|
1594
1723
|
/* copy dictionary offsets */
|
|
1595
1724
|
{ ZSTD_matchState_t const* srcMatchState = &cdict->matchState;
|
|
1596
1725
|
ZSTD_matchState_t* dstMatchState = &cctx->blockState.matchState;
|
|
1597
1726
|
dstMatchState->window = srcMatchState->window;
|
|
1598
1727
|
dstMatchState->nextToUpdate = srcMatchState->nextToUpdate;
|
|
1599
|
-
dstMatchState->nextToUpdate3= srcMatchState->nextToUpdate3;
|
|
1600
1728
|
dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd;
|
|
1601
1729
|
}
|
|
1602
1730
|
|
|
@@ -1613,7 +1741,7 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx,
|
|
|
1613
1741
|
* in-place. We decide here which strategy to use. */
|
|
1614
1742
|
static size_t ZSTD_resetCCtx_usingCDict(ZSTD_CCtx* cctx,
|
|
1615
1743
|
const ZSTD_CDict* cdict,
|
|
1616
|
-
ZSTD_CCtx_params params,
|
|
1744
|
+
const ZSTD_CCtx_params* params,
|
|
1617
1745
|
U64 pledgedSrcSize,
|
|
1618
1746
|
ZSTD_buffered_policy_e zbuff)
|
|
1619
1747
|
{
|
|
@@ -1623,10 +1751,10 @@ static size_t ZSTD_resetCCtx_usingCDict(ZSTD_CCtx* cctx,
|
|
|
1623
1751
|
|
|
1624
1752
|
if (ZSTD_shouldAttachDict(cdict, params, pledgedSrcSize)) {
|
|
1625
1753
|
return ZSTD_resetCCtx_byAttachingCDict(
|
|
1626
|
-
cctx, cdict, params, pledgedSrcSize, zbuff);
|
|
1754
|
+
cctx, cdict, *params, pledgedSrcSize, zbuff);
|
|
1627
1755
|
} else {
|
|
1628
1756
|
return ZSTD_resetCCtx_byCopyingCDict(
|
|
1629
|
-
cctx, cdict, params, pledgedSrcSize, zbuff);
|
|
1757
|
+
cctx, cdict, *params, pledgedSrcSize, zbuff);
|
|
1630
1758
|
}
|
|
1631
1759
|
}
|
|
1632
1760
|
|
|
@@ -1644,7 +1772,8 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
|
|
|
1644
1772
|
ZSTD_buffered_policy_e zbuff)
|
|
1645
1773
|
{
|
|
1646
1774
|
DEBUGLOG(5, "ZSTD_copyCCtx_internal");
|
|
1647
|
-
|
|
1775
|
+
RETURN_ERROR_IF(srcCCtx->stage!=ZSTDcs_init, stage_wrong,
|
|
1776
|
+
"Can't copy a ctx that's not in init stage.");
|
|
1648
1777
|
|
|
1649
1778
|
memcpy(&dstCCtx->customMem, &srcCCtx->customMem, sizeof(ZSTD_customMem));
|
|
1650
1779
|
{ ZSTD_CCtx_params params = dstCCtx->requestedParams;
|
|
@@ -1652,7 +1781,7 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
|
|
|
1652
1781
|
params.cParams = srcCCtx->appliedParams.cParams;
|
|
1653
1782
|
params.fParams = fParams;
|
|
1654
1783
|
ZSTD_resetCCtx_internal(dstCCtx, params, pledgedSrcSize,
|
|
1655
|
-
|
|
1784
|
+
ZSTDcrp_leaveDirty, zbuff);
|
|
1656
1785
|
assert(dstCCtx->appliedParams.cParams.windowLog == srcCCtx->appliedParams.cParams.windowLog);
|
|
1657
1786
|
assert(dstCCtx->appliedParams.cParams.strategy == srcCCtx->appliedParams.cParams.strategy);
|
|
1658
1787
|
assert(dstCCtx->appliedParams.cParams.hashLog == srcCCtx->appliedParams.cParams.hashLog);
|
|
@@ -1660,23 +1789,33 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
|
|
|
1660
1789
|
assert(dstCCtx->blockState.matchState.hashLog3 == srcCCtx->blockState.matchState.hashLog3);
|
|
1661
1790
|
}
|
|
1662
1791
|
|
|
1792
|
+
ZSTD_cwksp_mark_tables_dirty(&dstCCtx->workspace);
|
|
1793
|
+
|
|
1663
1794
|
/* copy tables */
|
|
1664
1795
|
{ size_t const chainSize = (srcCCtx->appliedParams.cParams.strategy == ZSTD_fast) ? 0 : ((size_t)1 << srcCCtx->appliedParams.cParams.chainLog);
|
|
1665
1796
|
size_t const hSize = (size_t)1 << srcCCtx->appliedParams.cParams.hashLog;
|
|
1666
|
-
|
|
1667
|
-
size_t const
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
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));
|
|
1671
1809
|
}
|
|
1672
1810
|
|
|
1811
|
+
ZSTD_cwksp_mark_tables_clean(&dstCCtx->workspace);
|
|
1812
|
+
|
|
1673
1813
|
/* copy dictionary offsets */
|
|
1674
1814
|
{
|
|
1675
1815
|
const ZSTD_matchState_t* srcMatchState = &srcCCtx->blockState.matchState;
|
|
1676
1816
|
ZSTD_matchState_t* dstMatchState = &dstCCtx->blockState.matchState;
|
|
1677
1817
|
dstMatchState->window = srcMatchState->window;
|
|
1678
1818
|
dstMatchState->nextToUpdate = srcMatchState->nextToUpdate;
|
|
1679
|
-
dstMatchState->nextToUpdate3= srcMatchState->nextToUpdate3;
|
|
1680
1819
|
dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd;
|
|
1681
1820
|
}
|
|
1682
1821
|
dstCCtx->dictID = srcCCtx->dictID;
|
|
@@ -1721,6 +1860,20 @@ ZSTD_reduceTable_internal (U32* const table, U32 const size, U32 const reducerVa
|
|
|
1721
1860
|
int rowNb;
|
|
1722
1861
|
assert((size & (ZSTD_ROWSIZE-1)) == 0); /* multiple of ZSTD_ROWSIZE */
|
|
1723
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
|
+
|
|
1724
1877
|
for (rowNb=0 ; rowNb < nbRows ; rowNb++) {
|
|
1725
1878
|
int column;
|
|
1726
1879
|
for (column=0; column<ZSTD_ROWSIZE; column++) {
|
|
@@ -1746,16 +1899,15 @@ static void ZSTD_reduceTable_btlazy2(U32* const table, U32 const size, U32 const
|
|
|
1746
1899
|
|
|
1747
1900
|
/*! ZSTD_reduceIndex() :
|
|
1748
1901
|
* rescale all indexes to avoid future overflow (indexes are U32) */
|
|
1749
|
-
static void ZSTD_reduceIndex (
|
|
1902
|
+
static void ZSTD_reduceIndex (ZSTD_matchState_t* ms, ZSTD_CCtx_params const* params, const U32 reducerValue)
|
|
1750
1903
|
{
|
|
1751
|
-
|
|
1752
|
-
{ U32 const hSize = (U32)1 << zc->appliedParams.cParams.hashLog;
|
|
1904
|
+
{ U32 const hSize = (U32)1 << params->cParams.hashLog;
|
|
1753
1905
|
ZSTD_reduceTable(ms->hashTable, hSize, reducerValue);
|
|
1754
1906
|
}
|
|
1755
1907
|
|
|
1756
|
-
if (
|
|
1757
|
-
U32 const chainSize = (U32)1 <<
|
|
1758
|
-
if (
|
|
1908
|
+
if (params->cParams.strategy != ZSTD_fast) {
|
|
1909
|
+
U32 const chainSize = (U32)1 << params->cParams.chainLog;
|
|
1910
|
+
if (params->cParams.strategy == ZSTD_btlazy2)
|
|
1759
1911
|
ZSTD_reduceTable_btlazy2(ms->chainTable, chainSize, reducerValue);
|
|
1760
1912
|
else
|
|
1761
1913
|
ZSTD_reduceTable(ms->chainTable, chainSize, reducerValue);
|
|
@@ -1774,164 +1926,6 @@ static void ZSTD_reduceIndex (ZSTD_CCtx* zc, const U32 reducerValue)
|
|
|
1774
1926
|
|
|
1775
1927
|
/* See doc/zstd_compression_format.md for detailed format description */
|
|
1776
1928
|
|
|
1777
|
-
static size_t ZSTD_noCompressBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize, U32 lastBlock)
|
|
1778
|
-
{
|
|
1779
|
-
U32 const cBlockHeader24 = lastBlock + (((U32)bt_raw)<<1) + (U32)(srcSize << 3);
|
|
1780
|
-
if (srcSize + ZSTD_blockHeaderSize > dstCapacity) return ERROR(dstSize_tooSmall);
|
|
1781
|
-
MEM_writeLE24(dst, cBlockHeader24);
|
|
1782
|
-
memcpy((BYTE*)dst + ZSTD_blockHeaderSize, src, srcSize);
|
|
1783
|
-
return ZSTD_blockHeaderSize + srcSize;
|
|
1784
|
-
}
|
|
1785
|
-
|
|
1786
|
-
static size_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void* src, size_t srcSize)
|
|
1787
|
-
{
|
|
1788
|
-
BYTE* const ostart = (BYTE* const)dst;
|
|
1789
|
-
U32 const flSize = 1 + (srcSize>31) + (srcSize>4095);
|
|
1790
|
-
|
|
1791
|
-
if (srcSize + flSize > dstCapacity) return ERROR(dstSize_tooSmall);
|
|
1792
|
-
|
|
1793
|
-
switch(flSize)
|
|
1794
|
-
{
|
|
1795
|
-
case 1: /* 2 - 1 - 5 */
|
|
1796
|
-
ostart[0] = (BYTE)((U32)set_basic + (srcSize<<3));
|
|
1797
|
-
break;
|
|
1798
|
-
case 2: /* 2 - 2 - 12 */
|
|
1799
|
-
MEM_writeLE16(ostart, (U16)((U32)set_basic + (1<<2) + (srcSize<<4)));
|
|
1800
|
-
break;
|
|
1801
|
-
case 3: /* 2 - 2 - 20 */
|
|
1802
|
-
MEM_writeLE32(ostart, (U32)((U32)set_basic + (3<<2) + (srcSize<<4)));
|
|
1803
|
-
break;
|
|
1804
|
-
default: /* not necessary : flSize is {1,2,3} */
|
|
1805
|
-
assert(0);
|
|
1806
|
-
}
|
|
1807
|
-
|
|
1808
|
-
memcpy(ostart + flSize, src, srcSize);
|
|
1809
|
-
return srcSize + flSize;
|
|
1810
|
-
}
|
|
1811
|
-
|
|
1812
|
-
static size_t ZSTD_compressRleLiteralsBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize)
|
|
1813
|
-
{
|
|
1814
|
-
BYTE* const ostart = (BYTE* const)dst;
|
|
1815
|
-
U32 const flSize = 1 + (srcSize>31) + (srcSize>4095);
|
|
1816
|
-
|
|
1817
|
-
(void)dstCapacity; /* dstCapacity already guaranteed to be >=4, hence large enough */
|
|
1818
|
-
|
|
1819
|
-
switch(flSize)
|
|
1820
|
-
{
|
|
1821
|
-
case 1: /* 2 - 1 - 5 */
|
|
1822
|
-
ostart[0] = (BYTE)((U32)set_rle + (srcSize<<3));
|
|
1823
|
-
break;
|
|
1824
|
-
case 2: /* 2 - 2 - 12 */
|
|
1825
|
-
MEM_writeLE16(ostart, (U16)((U32)set_rle + (1<<2) + (srcSize<<4)));
|
|
1826
|
-
break;
|
|
1827
|
-
case 3: /* 2 - 2 - 20 */
|
|
1828
|
-
MEM_writeLE32(ostart, (U32)((U32)set_rle + (3<<2) + (srcSize<<4)));
|
|
1829
|
-
break;
|
|
1830
|
-
default: /* not necessary : flSize is {1,2,3} */
|
|
1831
|
-
assert(0);
|
|
1832
|
-
}
|
|
1833
|
-
|
|
1834
|
-
ostart[flSize] = *(const BYTE*)src;
|
|
1835
|
-
return flSize+1;
|
|
1836
|
-
}
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
/* ZSTD_minGain() :
|
|
1840
|
-
* minimum compression required
|
|
1841
|
-
* to generate a compress block or a compressed literals section.
|
|
1842
|
-
* note : use same formula for both situations */
|
|
1843
|
-
static size_t ZSTD_minGain(size_t srcSize, ZSTD_strategy strat)
|
|
1844
|
-
{
|
|
1845
|
-
U32 const minlog = (strat>=ZSTD_btultra) ? (U32)(strat) - 1 : 6;
|
|
1846
|
-
ZSTD_STATIC_ASSERT(ZSTD_btultra == 8);
|
|
1847
|
-
assert(ZSTD_cParam_withinBounds(ZSTD_c_strategy, strat));
|
|
1848
|
-
return (srcSize >> minlog) + 2;
|
|
1849
|
-
}
|
|
1850
|
-
|
|
1851
|
-
static size_t ZSTD_compressLiterals (ZSTD_hufCTables_t const* prevHuf,
|
|
1852
|
-
ZSTD_hufCTables_t* nextHuf,
|
|
1853
|
-
ZSTD_strategy strategy, int disableLiteralCompression,
|
|
1854
|
-
void* dst, size_t dstCapacity,
|
|
1855
|
-
const void* src, size_t srcSize,
|
|
1856
|
-
void* workspace, size_t wkspSize,
|
|
1857
|
-
const int bmi2)
|
|
1858
|
-
{
|
|
1859
|
-
size_t const minGain = ZSTD_minGain(srcSize, strategy);
|
|
1860
|
-
size_t const lhSize = 3 + (srcSize >= 1 KB) + (srcSize >= 16 KB);
|
|
1861
|
-
BYTE* const ostart = (BYTE*)dst;
|
|
1862
|
-
U32 singleStream = srcSize < 256;
|
|
1863
|
-
symbolEncodingType_e hType = set_compressed;
|
|
1864
|
-
size_t cLitSize;
|
|
1865
|
-
|
|
1866
|
-
DEBUGLOG(5,"ZSTD_compressLiterals (disableLiteralCompression=%i)",
|
|
1867
|
-
disableLiteralCompression);
|
|
1868
|
-
|
|
1869
|
-
/* Prepare nextEntropy assuming reusing the existing table */
|
|
1870
|
-
memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
|
|
1871
|
-
|
|
1872
|
-
if (disableLiteralCompression)
|
|
1873
|
-
return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
|
|
1874
|
-
|
|
1875
|
-
/* small ? don't even attempt compression (speed opt) */
|
|
1876
|
-
# define COMPRESS_LITERALS_SIZE_MIN 63
|
|
1877
|
-
{ size_t const minLitSize = (prevHuf->repeatMode == HUF_repeat_valid) ? 6 : COMPRESS_LITERALS_SIZE_MIN;
|
|
1878
|
-
if (srcSize <= minLitSize) return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
|
|
1879
|
-
}
|
|
1880
|
-
|
|
1881
|
-
if (dstCapacity < lhSize+1) return ERROR(dstSize_tooSmall); /* not enough space for compression */
|
|
1882
|
-
{ HUF_repeat repeat = prevHuf->repeatMode;
|
|
1883
|
-
int const preferRepeat = strategy < ZSTD_lazy ? srcSize <= 1024 : 0;
|
|
1884
|
-
if (repeat == HUF_repeat_valid && lhSize == 3) singleStream = 1;
|
|
1885
|
-
cLitSize = singleStream ? HUF_compress1X_repeat(ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 11,
|
|
1886
|
-
workspace, wkspSize, (HUF_CElt*)nextHuf->CTable, &repeat, preferRepeat, bmi2)
|
|
1887
|
-
: HUF_compress4X_repeat(ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 11,
|
|
1888
|
-
workspace, wkspSize, (HUF_CElt*)nextHuf->CTable, &repeat, preferRepeat, bmi2);
|
|
1889
|
-
if (repeat != HUF_repeat_none) {
|
|
1890
|
-
/* reused the existing table */
|
|
1891
|
-
hType = set_repeat;
|
|
1892
|
-
}
|
|
1893
|
-
}
|
|
1894
|
-
|
|
1895
|
-
if ((cLitSize==0) | (cLitSize >= srcSize - minGain) | ERR_isError(cLitSize)) {
|
|
1896
|
-
memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
|
|
1897
|
-
return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
|
|
1898
|
-
}
|
|
1899
|
-
if (cLitSize==1) {
|
|
1900
|
-
memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
|
|
1901
|
-
return ZSTD_compressRleLiteralsBlock(dst, dstCapacity, src, srcSize);
|
|
1902
|
-
}
|
|
1903
|
-
|
|
1904
|
-
if (hType == set_compressed) {
|
|
1905
|
-
/* using a newly constructed table */
|
|
1906
|
-
nextHuf->repeatMode = HUF_repeat_check;
|
|
1907
|
-
}
|
|
1908
|
-
|
|
1909
|
-
/* Build header */
|
|
1910
|
-
switch(lhSize)
|
|
1911
|
-
{
|
|
1912
|
-
case 3: /* 2 - 2 - 10 - 10 */
|
|
1913
|
-
{ U32 const lhc = hType + ((!singleStream) << 2) + ((U32)srcSize<<4) + ((U32)cLitSize<<14);
|
|
1914
|
-
MEM_writeLE24(ostart, lhc);
|
|
1915
|
-
break;
|
|
1916
|
-
}
|
|
1917
|
-
case 4: /* 2 - 2 - 14 - 14 */
|
|
1918
|
-
{ U32 const lhc = hType + (2 << 2) + ((U32)srcSize<<4) + ((U32)cLitSize<<18);
|
|
1919
|
-
MEM_writeLE32(ostart, lhc);
|
|
1920
|
-
break;
|
|
1921
|
-
}
|
|
1922
|
-
case 5: /* 2 - 2 - 18 - 18 */
|
|
1923
|
-
{ U32 const lhc = hType + (3 << 2) + ((U32)srcSize<<4) + ((U32)cLitSize<<22);
|
|
1924
|
-
MEM_writeLE32(ostart, lhc);
|
|
1925
|
-
ostart[4] = (BYTE)(cLitSize >> 10);
|
|
1926
|
-
break;
|
|
1927
|
-
}
|
|
1928
|
-
default: /* not possible : lhSize is {3,4,5} */
|
|
1929
|
-
assert(0);
|
|
1930
|
-
}
|
|
1931
|
-
return lhSize+cLitSize;
|
|
1932
|
-
}
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
1929
|
void ZSTD_seqToCodes(const seqStore_t* seqStorePtr)
|
|
1936
1930
|
{
|
|
1937
1931
|
const seqDef* const sequences = seqStorePtr->sequencesStart;
|
|
@@ -1944,428 +1938,24 @@ void ZSTD_seqToCodes(const seqStore_t* seqStorePtr)
|
|
|
1944
1938
|
for (u=0; u<nbSeq; u++) {
|
|
1945
1939
|
U32 const llv = sequences[u].litLength;
|
|
1946
1940
|
U32 const mlv = sequences[u].matchLength;
|
|
1947
|
-
llCodeTable[u] = (BYTE)ZSTD_LLcode(llv);
|
|
1948
|
-
ofCodeTable[u] = (BYTE)ZSTD_highbit32(sequences[u].offset);
|
|
1949
|
-
mlCodeTable[u] = (BYTE)ZSTD_MLcode(mlv);
|
|
1950
|
-
}
|
|
1951
|
-
if (seqStorePtr->longLengthID==1)
|
|
1952
|
-
llCodeTable[seqStorePtr->longLengthPos] = MaxLL;
|
|
1953
|
-
if (seqStorePtr->longLengthID==2)
|
|
1954
|
-
mlCodeTable[seqStorePtr->longLengthPos] = MaxML;
|
|
1955
|
-
}
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
/**
|
|
1959
|
-
* -log2(x / 256) lookup table for x in [0, 256).
|
|
1960
|
-
* If x == 0: Return 0
|
|
1961
|
-
* Else: Return floor(-log2(x / 256) * 256)
|
|
1962
|
-
*/
|
|
1963
|
-
static unsigned const kInverseProbabiltyLog256[256] = {
|
|
1964
|
-
0, 2048, 1792, 1642, 1536, 1453, 1386, 1329, 1280, 1236, 1197, 1162,
|
|
1965
|
-
1130, 1100, 1073, 1047, 1024, 1001, 980, 960, 941, 923, 906, 889,
|
|
1966
|
-
874, 859, 844, 830, 817, 804, 791, 779, 768, 756, 745, 734,
|
|
1967
|
-
724, 714, 704, 694, 685, 676, 667, 658, 650, 642, 633, 626,
|
|
1968
|
-
618, 610, 603, 595, 588, 581, 574, 567, 561, 554, 548, 542,
|
|
1969
|
-
535, 529, 523, 517, 512, 506, 500, 495, 489, 484, 478, 473,
|
|
1970
|
-
468, 463, 458, 453, 448, 443, 438, 434, 429, 424, 420, 415,
|
|
1971
|
-
411, 407, 402, 398, 394, 390, 386, 382, 377, 373, 370, 366,
|
|
1972
|
-
362, 358, 354, 350, 347, 343, 339, 336, 332, 329, 325, 322,
|
|
1973
|
-
318, 315, 311, 308, 305, 302, 298, 295, 292, 289, 286, 282,
|
|
1974
|
-
279, 276, 273, 270, 267, 264, 261, 258, 256, 253, 250, 247,
|
|
1975
|
-
244, 241, 239, 236, 233, 230, 228, 225, 222, 220, 217, 215,
|
|
1976
|
-
212, 209, 207, 204, 202, 199, 197, 194, 192, 190, 187, 185,
|
|
1977
|
-
182, 180, 178, 175, 173, 171, 168, 166, 164, 162, 159, 157,
|
|
1978
|
-
155, 153, 151, 149, 146, 144, 142, 140, 138, 136, 134, 132,
|
|
1979
|
-
130, 128, 126, 123, 121, 119, 117, 115, 114, 112, 110, 108,
|
|
1980
|
-
106, 104, 102, 100, 98, 96, 94, 93, 91, 89, 87, 85,
|
|
1981
|
-
83, 82, 80, 78, 76, 74, 73, 71, 69, 67, 66, 64,
|
|
1982
|
-
62, 61, 59, 57, 55, 54, 52, 50, 49, 47, 46, 44,
|
|
1983
|
-
42, 41, 39, 37, 36, 34, 33, 31, 30, 28, 26, 25,
|
|
1984
|
-
23, 22, 20, 19, 17, 16, 14, 13, 11, 10, 8, 7,
|
|
1985
|
-
5, 4, 2, 1,
|
|
1986
|
-
};
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
/**
|
|
1990
|
-
* Returns the cost in bits of encoding the distribution described by count
|
|
1991
|
-
* using the entropy bound.
|
|
1992
|
-
*/
|
|
1993
|
-
static size_t ZSTD_entropyCost(unsigned const* count, unsigned const max, size_t const total)
|
|
1994
|
-
{
|
|
1995
|
-
unsigned cost = 0;
|
|
1996
|
-
unsigned s;
|
|
1997
|
-
for (s = 0; s <= max; ++s) {
|
|
1998
|
-
unsigned norm = (unsigned)((256 * count[s]) / total);
|
|
1999
|
-
if (count[s] != 0 && norm == 0)
|
|
2000
|
-
norm = 1;
|
|
2001
|
-
assert(count[s] < total);
|
|
2002
|
-
cost += count[s] * kInverseProbabiltyLog256[norm];
|
|
2003
|
-
}
|
|
2004
|
-
return cost >> 8;
|
|
2005
|
-
}
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
/**
|
|
2009
|
-
* Returns the cost in bits of encoding the distribution in count using the
|
|
2010
|
-
* table described by norm. The max symbol support by norm is assumed >= max.
|
|
2011
|
-
* norm must be valid for every symbol with non-zero probability in count.
|
|
2012
|
-
*/
|
|
2013
|
-
static size_t ZSTD_crossEntropyCost(short const* norm, unsigned accuracyLog,
|
|
2014
|
-
unsigned const* count, unsigned const max)
|
|
2015
|
-
{
|
|
2016
|
-
unsigned const shift = 8 - accuracyLog;
|
|
2017
|
-
size_t cost = 0;
|
|
2018
|
-
unsigned s;
|
|
2019
|
-
assert(accuracyLog <= 8);
|
|
2020
|
-
for (s = 0; s <= max; ++s) {
|
|
2021
|
-
unsigned const normAcc = norm[s] != -1 ? norm[s] : 1;
|
|
2022
|
-
unsigned const norm256 = normAcc << shift;
|
|
2023
|
-
assert(norm256 > 0);
|
|
2024
|
-
assert(norm256 < 256);
|
|
2025
|
-
cost += count[s] * kInverseProbabiltyLog256[norm256];
|
|
2026
|
-
}
|
|
2027
|
-
return cost >> 8;
|
|
2028
|
-
}
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
static unsigned ZSTD_getFSEMaxSymbolValue(FSE_CTable const* ctable) {
|
|
2032
|
-
void const* ptr = ctable;
|
|
2033
|
-
U16 const* u16ptr = (U16 const*)ptr;
|
|
2034
|
-
U32 const maxSymbolValue = MEM_read16(u16ptr + 1);
|
|
2035
|
-
return maxSymbolValue;
|
|
2036
|
-
}
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
/**
|
|
2040
|
-
* Returns the cost in bits of encoding the distribution in count using ctable.
|
|
2041
|
-
* Returns an error if ctable cannot represent all the symbols in count.
|
|
2042
|
-
*/
|
|
2043
|
-
static size_t ZSTD_fseBitCost(
|
|
2044
|
-
FSE_CTable const* ctable,
|
|
2045
|
-
unsigned const* count,
|
|
2046
|
-
unsigned const max)
|
|
2047
|
-
{
|
|
2048
|
-
unsigned const kAccuracyLog = 8;
|
|
2049
|
-
size_t cost = 0;
|
|
2050
|
-
unsigned s;
|
|
2051
|
-
FSE_CState_t cstate;
|
|
2052
|
-
FSE_initCState(&cstate, ctable);
|
|
2053
|
-
if (ZSTD_getFSEMaxSymbolValue(ctable) < max) {
|
|
2054
|
-
DEBUGLOG(5, "Repeat FSE_CTable has maxSymbolValue %u < %u",
|
|
2055
|
-
ZSTD_getFSEMaxSymbolValue(ctable), max);
|
|
2056
|
-
return ERROR(GENERIC);
|
|
2057
|
-
}
|
|
2058
|
-
for (s = 0; s <= max; ++s) {
|
|
2059
|
-
unsigned const tableLog = cstate.stateLog;
|
|
2060
|
-
unsigned const badCost = (tableLog + 1) << kAccuracyLog;
|
|
2061
|
-
unsigned const bitCost = FSE_bitCost(cstate.symbolTT, tableLog, s, kAccuracyLog);
|
|
2062
|
-
if (count[s] == 0)
|
|
2063
|
-
continue;
|
|
2064
|
-
if (bitCost >= badCost) {
|
|
2065
|
-
DEBUGLOG(5, "Repeat FSE_CTable has Prob[%u] == 0", s);
|
|
2066
|
-
return ERROR(GENERIC);
|
|
2067
|
-
}
|
|
2068
|
-
cost += count[s] * bitCost;
|
|
2069
|
-
}
|
|
2070
|
-
return cost >> kAccuracyLog;
|
|
2071
|
-
}
|
|
2072
|
-
|
|
2073
|
-
/**
|
|
2074
|
-
* Returns the cost in bytes of encoding the normalized count header.
|
|
2075
|
-
* Returns an error if any of the helper functions return an error.
|
|
2076
|
-
*/
|
|
2077
|
-
static size_t ZSTD_NCountCost(unsigned const* count, unsigned const max,
|
|
2078
|
-
size_t const nbSeq, unsigned const FSELog)
|
|
2079
|
-
{
|
|
2080
|
-
BYTE wksp[FSE_NCOUNTBOUND];
|
|
2081
|
-
S16 norm[MaxSeq + 1];
|
|
2082
|
-
const U32 tableLog = FSE_optimalTableLog(FSELog, nbSeq, max);
|
|
2083
|
-
CHECK_F(FSE_normalizeCount(norm, tableLog, count, nbSeq, max));
|
|
2084
|
-
return FSE_writeNCount(wksp, sizeof(wksp), norm, max, tableLog);
|
|
2085
|
-
}
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
typedef enum {
|
|
2089
|
-
ZSTD_defaultDisallowed = 0,
|
|
2090
|
-
ZSTD_defaultAllowed = 1
|
|
2091
|
-
} ZSTD_defaultPolicy_e;
|
|
2092
|
-
|
|
2093
|
-
MEM_STATIC symbolEncodingType_e
|
|
2094
|
-
ZSTD_selectEncodingType(
|
|
2095
|
-
FSE_repeat* repeatMode, unsigned const* count, unsigned const max,
|
|
2096
|
-
size_t const mostFrequent, size_t nbSeq, unsigned const FSELog,
|
|
2097
|
-
FSE_CTable const* prevCTable,
|
|
2098
|
-
short const* defaultNorm, U32 defaultNormLog,
|
|
2099
|
-
ZSTD_defaultPolicy_e const isDefaultAllowed,
|
|
2100
|
-
ZSTD_strategy const strategy)
|
|
2101
|
-
{
|
|
2102
|
-
ZSTD_STATIC_ASSERT(ZSTD_defaultDisallowed == 0 && ZSTD_defaultAllowed != 0);
|
|
2103
|
-
if (mostFrequent == nbSeq) {
|
|
2104
|
-
*repeatMode = FSE_repeat_none;
|
|
2105
|
-
if (isDefaultAllowed && nbSeq <= 2) {
|
|
2106
|
-
/* Prefer set_basic over set_rle when there are 2 or less symbols,
|
|
2107
|
-
* since RLE uses 1 byte, but set_basic uses 5-6 bits per symbol.
|
|
2108
|
-
* If basic encoding isn't possible, always choose RLE.
|
|
2109
|
-
*/
|
|
2110
|
-
DEBUGLOG(5, "Selected set_basic");
|
|
2111
|
-
return set_basic;
|
|
2112
|
-
}
|
|
2113
|
-
DEBUGLOG(5, "Selected set_rle");
|
|
2114
|
-
return set_rle;
|
|
2115
|
-
}
|
|
2116
|
-
if (strategy < ZSTD_lazy) {
|
|
2117
|
-
if (isDefaultAllowed) {
|
|
2118
|
-
size_t const staticFse_nbSeq_max = 1000;
|
|
2119
|
-
size_t const mult = 10 - strategy;
|
|
2120
|
-
size_t const baseLog = 3;
|
|
2121
|
-
size_t const dynamicFse_nbSeq_min = (((size_t)1 << defaultNormLog) * mult) >> baseLog; /* 28-36 for offset, 56-72 for lengths */
|
|
2122
|
-
assert(defaultNormLog >= 5 && defaultNormLog <= 6); /* xx_DEFAULTNORMLOG */
|
|
2123
|
-
assert(mult <= 9 && mult >= 7);
|
|
2124
|
-
if ( (*repeatMode == FSE_repeat_valid)
|
|
2125
|
-
&& (nbSeq < staticFse_nbSeq_max) ) {
|
|
2126
|
-
DEBUGLOG(5, "Selected set_repeat");
|
|
2127
|
-
return set_repeat;
|
|
2128
|
-
}
|
|
2129
|
-
if ( (nbSeq < dynamicFse_nbSeq_min)
|
|
2130
|
-
|| (mostFrequent < (nbSeq >> (defaultNormLog-1))) ) {
|
|
2131
|
-
DEBUGLOG(5, "Selected set_basic");
|
|
2132
|
-
/* The format allows default tables to be repeated, but it isn't useful.
|
|
2133
|
-
* When using simple heuristics to select encoding type, we don't want
|
|
2134
|
-
* to confuse these tables with dictionaries. When running more careful
|
|
2135
|
-
* analysis, we don't need to waste time checking both repeating tables
|
|
2136
|
-
* and default tables.
|
|
2137
|
-
*/
|
|
2138
|
-
*repeatMode = FSE_repeat_none;
|
|
2139
|
-
return set_basic;
|
|
2140
|
-
}
|
|
2141
|
-
}
|
|
2142
|
-
} else {
|
|
2143
|
-
size_t const basicCost = isDefaultAllowed ? ZSTD_crossEntropyCost(defaultNorm, defaultNormLog, count, max) : ERROR(GENERIC);
|
|
2144
|
-
size_t const repeatCost = *repeatMode != FSE_repeat_none ? ZSTD_fseBitCost(prevCTable, count, max) : ERROR(GENERIC);
|
|
2145
|
-
size_t const NCountCost = ZSTD_NCountCost(count, max, nbSeq, FSELog);
|
|
2146
|
-
size_t const compressedCost = (NCountCost << 3) + ZSTD_entropyCost(count, max, nbSeq);
|
|
2147
|
-
|
|
2148
|
-
if (isDefaultAllowed) {
|
|
2149
|
-
assert(!ZSTD_isError(basicCost));
|
|
2150
|
-
assert(!(*repeatMode == FSE_repeat_valid && ZSTD_isError(repeatCost)));
|
|
2151
|
-
}
|
|
2152
|
-
assert(!ZSTD_isError(NCountCost));
|
|
2153
|
-
assert(compressedCost < ERROR(maxCode));
|
|
2154
|
-
DEBUGLOG(5, "Estimated bit costs: basic=%u\trepeat=%u\tcompressed=%u",
|
|
2155
|
-
(unsigned)basicCost, (unsigned)repeatCost, (unsigned)compressedCost);
|
|
2156
|
-
if (basicCost <= repeatCost && basicCost <= compressedCost) {
|
|
2157
|
-
DEBUGLOG(5, "Selected set_basic");
|
|
2158
|
-
assert(isDefaultAllowed);
|
|
2159
|
-
*repeatMode = FSE_repeat_none;
|
|
2160
|
-
return set_basic;
|
|
2161
|
-
}
|
|
2162
|
-
if (repeatCost <= compressedCost) {
|
|
2163
|
-
DEBUGLOG(5, "Selected set_repeat");
|
|
2164
|
-
assert(!ZSTD_isError(repeatCost));
|
|
2165
|
-
return set_repeat;
|
|
2166
|
-
}
|
|
2167
|
-
assert(compressedCost < basicCost && compressedCost < repeatCost);
|
|
2168
|
-
}
|
|
2169
|
-
DEBUGLOG(5, "Selected set_compressed");
|
|
2170
|
-
*repeatMode = FSE_repeat_check;
|
|
2171
|
-
return set_compressed;
|
|
2172
|
-
}
|
|
2173
|
-
|
|
2174
|
-
MEM_STATIC size_t
|
|
2175
|
-
ZSTD_buildCTable(void* dst, size_t dstCapacity,
|
|
2176
|
-
FSE_CTable* nextCTable, U32 FSELog, symbolEncodingType_e type,
|
|
2177
|
-
unsigned* count, U32 max,
|
|
2178
|
-
const BYTE* codeTable, size_t nbSeq,
|
|
2179
|
-
const S16* defaultNorm, U32 defaultNormLog, U32 defaultMax,
|
|
2180
|
-
const FSE_CTable* prevCTable, size_t prevCTableSize,
|
|
2181
|
-
void* workspace, size_t workspaceSize)
|
|
2182
|
-
{
|
|
2183
|
-
BYTE* op = (BYTE*)dst;
|
|
2184
|
-
const BYTE* const oend = op + dstCapacity;
|
|
2185
|
-
DEBUGLOG(6, "ZSTD_buildCTable (dstCapacity=%u)", (unsigned)dstCapacity);
|
|
2186
|
-
|
|
2187
|
-
switch (type) {
|
|
2188
|
-
case set_rle:
|
|
2189
|
-
CHECK_F(FSE_buildCTable_rle(nextCTable, (BYTE)max));
|
|
2190
|
-
if (dstCapacity==0) return ERROR(dstSize_tooSmall);
|
|
2191
|
-
*op = codeTable[0];
|
|
2192
|
-
return 1;
|
|
2193
|
-
case set_repeat:
|
|
2194
|
-
memcpy(nextCTable, prevCTable, prevCTableSize);
|
|
2195
|
-
return 0;
|
|
2196
|
-
case set_basic:
|
|
2197
|
-
CHECK_F(FSE_buildCTable_wksp(nextCTable, defaultNorm, defaultMax, defaultNormLog, workspace, workspaceSize)); /* note : could be pre-calculated */
|
|
2198
|
-
return 0;
|
|
2199
|
-
case set_compressed: {
|
|
2200
|
-
S16 norm[MaxSeq + 1];
|
|
2201
|
-
size_t nbSeq_1 = nbSeq;
|
|
2202
|
-
const U32 tableLog = FSE_optimalTableLog(FSELog, nbSeq, max);
|
|
2203
|
-
if (count[codeTable[nbSeq-1]] > 1) {
|
|
2204
|
-
count[codeTable[nbSeq-1]]--;
|
|
2205
|
-
nbSeq_1--;
|
|
2206
|
-
}
|
|
2207
|
-
assert(nbSeq_1 > 1);
|
|
2208
|
-
CHECK_F(FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max));
|
|
2209
|
-
{ size_t const NCountSize = FSE_writeNCount(op, oend - op, norm, max, tableLog); /* overflow protected */
|
|
2210
|
-
if (FSE_isError(NCountSize)) return NCountSize;
|
|
2211
|
-
CHECK_F(FSE_buildCTable_wksp(nextCTable, norm, max, tableLog, workspace, workspaceSize));
|
|
2212
|
-
return NCountSize;
|
|
2213
|
-
}
|
|
2214
|
-
}
|
|
2215
|
-
default: return assert(0), ERROR(GENERIC);
|
|
2216
|
-
}
|
|
2217
|
-
}
|
|
2218
|
-
|
|
2219
|
-
FORCE_INLINE_TEMPLATE size_t
|
|
2220
|
-
ZSTD_encodeSequences_body(
|
|
2221
|
-
void* dst, size_t dstCapacity,
|
|
2222
|
-
FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,
|
|
2223
|
-
FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,
|
|
2224
|
-
FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,
|
|
2225
|
-
seqDef const* sequences, size_t nbSeq, int longOffsets)
|
|
2226
|
-
{
|
|
2227
|
-
BIT_CStream_t blockStream;
|
|
2228
|
-
FSE_CState_t stateMatchLength;
|
|
2229
|
-
FSE_CState_t stateOffsetBits;
|
|
2230
|
-
FSE_CState_t stateLitLength;
|
|
2231
|
-
|
|
2232
|
-
CHECK_E(BIT_initCStream(&blockStream, dst, dstCapacity), dstSize_tooSmall); /* not enough space remaining */
|
|
2233
|
-
DEBUGLOG(6, "available space for bitstream : %i (dstCapacity=%u)",
|
|
2234
|
-
(int)(blockStream.endPtr - blockStream.startPtr),
|
|
2235
|
-
(unsigned)dstCapacity);
|
|
2236
|
-
|
|
2237
|
-
/* first symbols */
|
|
2238
|
-
FSE_initCState2(&stateMatchLength, CTable_MatchLength, mlCodeTable[nbSeq-1]);
|
|
2239
|
-
FSE_initCState2(&stateOffsetBits, CTable_OffsetBits, ofCodeTable[nbSeq-1]);
|
|
2240
|
-
FSE_initCState2(&stateLitLength, CTable_LitLength, llCodeTable[nbSeq-1]);
|
|
2241
|
-
BIT_addBits(&blockStream, sequences[nbSeq-1].litLength, LL_bits[llCodeTable[nbSeq-1]]);
|
|
2242
|
-
if (MEM_32bits()) BIT_flushBits(&blockStream);
|
|
2243
|
-
BIT_addBits(&blockStream, sequences[nbSeq-1].matchLength, ML_bits[mlCodeTable[nbSeq-1]]);
|
|
2244
|
-
if (MEM_32bits()) BIT_flushBits(&blockStream);
|
|
2245
|
-
if (longOffsets) {
|
|
2246
|
-
U32 const ofBits = ofCodeTable[nbSeq-1];
|
|
2247
|
-
int const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN-1);
|
|
2248
|
-
if (extraBits) {
|
|
2249
|
-
BIT_addBits(&blockStream, sequences[nbSeq-1].offset, extraBits);
|
|
2250
|
-
BIT_flushBits(&blockStream);
|
|
2251
|
-
}
|
|
2252
|
-
BIT_addBits(&blockStream, sequences[nbSeq-1].offset >> extraBits,
|
|
2253
|
-
ofBits - extraBits);
|
|
2254
|
-
} else {
|
|
2255
|
-
BIT_addBits(&blockStream, sequences[nbSeq-1].offset, ofCodeTable[nbSeq-1]);
|
|
2256
|
-
}
|
|
2257
|
-
BIT_flushBits(&blockStream);
|
|
2258
|
-
|
|
2259
|
-
{ size_t n;
|
|
2260
|
-
for (n=nbSeq-2 ; n<nbSeq ; n--) { /* intentional underflow */
|
|
2261
|
-
BYTE const llCode = llCodeTable[n];
|
|
2262
|
-
BYTE const ofCode = ofCodeTable[n];
|
|
2263
|
-
BYTE const mlCode = mlCodeTable[n];
|
|
2264
|
-
U32 const llBits = LL_bits[llCode];
|
|
2265
|
-
U32 const ofBits = ofCode;
|
|
2266
|
-
U32 const mlBits = ML_bits[mlCode];
|
|
2267
|
-
DEBUGLOG(6, "encoding: litlen:%2u - matchlen:%2u - offCode:%7u",
|
|
2268
|
-
(unsigned)sequences[n].litLength,
|
|
2269
|
-
(unsigned)sequences[n].matchLength + MINMATCH,
|
|
2270
|
-
(unsigned)sequences[n].offset);
|
|
2271
|
-
/* 32b*/ /* 64b*/
|
|
2272
|
-
/* (7)*/ /* (7)*/
|
|
2273
|
-
FSE_encodeSymbol(&blockStream, &stateOffsetBits, ofCode); /* 15 */ /* 15 */
|
|
2274
|
-
FSE_encodeSymbol(&blockStream, &stateMatchLength, mlCode); /* 24 */ /* 24 */
|
|
2275
|
-
if (MEM_32bits()) BIT_flushBits(&blockStream); /* (7)*/
|
|
2276
|
-
FSE_encodeSymbol(&blockStream, &stateLitLength, llCode); /* 16 */ /* 33 */
|
|
2277
|
-
if (MEM_32bits() || (ofBits+mlBits+llBits >= 64-7-(LLFSELog+MLFSELog+OffFSELog)))
|
|
2278
|
-
BIT_flushBits(&blockStream); /* (7)*/
|
|
2279
|
-
BIT_addBits(&blockStream, sequences[n].litLength, llBits);
|
|
2280
|
-
if (MEM_32bits() && ((llBits+mlBits)>24)) BIT_flushBits(&blockStream);
|
|
2281
|
-
BIT_addBits(&blockStream, sequences[n].matchLength, mlBits);
|
|
2282
|
-
if (MEM_32bits() || (ofBits+mlBits+llBits > 56)) BIT_flushBits(&blockStream);
|
|
2283
|
-
if (longOffsets) {
|
|
2284
|
-
int const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN-1);
|
|
2285
|
-
if (extraBits) {
|
|
2286
|
-
BIT_addBits(&blockStream, sequences[n].offset, extraBits);
|
|
2287
|
-
BIT_flushBits(&blockStream); /* (7)*/
|
|
2288
|
-
}
|
|
2289
|
-
BIT_addBits(&blockStream, sequences[n].offset >> extraBits,
|
|
2290
|
-
ofBits - extraBits); /* 31 */
|
|
2291
|
-
} else {
|
|
2292
|
-
BIT_addBits(&blockStream, sequences[n].offset, ofBits); /* 31 */
|
|
2293
|
-
}
|
|
2294
|
-
BIT_flushBits(&blockStream); /* (7)*/
|
|
2295
|
-
DEBUGLOG(7, "remaining space : %i", (int)(blockStream.endPtr - blockStream.ptr));
|
|
2296
|
-
} }
|
|
2297
|
-
|
|
2298
|
-
DEBUGLOG(6, "ZSTD_encodeSequences: flushing ML state with %u bits", stateMatchLength.stateLog);
|
|
2299
|
-
FSE_flushCState(&blockStream, &stateMatchLength);
|
|
2300
|
-
DEBUGLOG(6, "ZSTD_encodeSequences: flushing Off state with %u bits", stateOffsetBits.stateLog);
|
|
2301
|
-
FSE_flushCState(&blockStream, &stateOffsetBits);
|
|
2302
|
-
DEBUGLOG(6, "ZSTD_encodeSequences: flushing LL state with %u bits", stateLitLength.stateLog);
|
|
2303
|
-
FSE_flushCState(&blockStream, &stateLitLength);
|
|
2304
|
-
|
|
2305
|
-
{ size_t const streamSize = BIT_closeCStream(&blockStream);
|
|
2306
|
-
if (streamSize==0) return ERROR(dstSize_tooSmall); /* not enough space */
|
|
2307
|
-
return streamSize;
|
|
1941
|
+
llCodeTable[u] = (BYTE)ZSTD_LLcode(llv);
|
|
1942
|
+
ofCodeTable[u] = (BYTE)ZSTD_highbit32(sequences[u].offset);
|
|
1943
|
+
mlCodeTable[u] = (BYTE)ZSTD_MLcode(mlv);
|
|
2308
1944
|
}
|
|
1945
|
+
if (seqStorePtr->longLengthID==1)
|
|
1946
|
+
llCodeTable[seqStorePtr->longLengthPos] = MaxLL;
|
|
1947
|
+
if (seqStorePtr->longLengthID==2)
|
|
1948
|
+
mlCodeTable[seqStorePtr->longLengthPos] = MaxML;
|
|
2309
1949
|
}
|
|
2310
1950
|
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,
|
|
2317
|
-
seqDef const* sequences, size_t nbSeq, int longOffsets)
|
|
2318
|
-
{
|
|
2319
|
-
return ZSTD_encodeSequences_body(dst, dstCapacity,
|
|
2320
|
-
CTable_MatchLength, mlCodeTable,
|
|
2321
|
-
CTable_OffsetBits, ofCodeTable,
|
|
2322
|
-
CTable_LitLength, llCodeTable,
|
|
2323
|
-
sequences, nbSeq, longOffsets);
|
|
2324
|
-
}
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
#if DYNAMIC_BMI2
|
|
2328
|
-
|
|
2329
|
-
static TARGET_ATTRIBUTE("bmi2") size_t
|
|
2330
|
-
ZSTD_encodeSequences_bmi2(
|
|
2331
|
-
void* dst, size_t dstCapacity,
|
|
2332
|
-
FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,
|
|
2333
|
-
FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,
|
|
2334
|
-
FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,
|
|
2335
|
-
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)
|
|
2336
1956
|
{
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
CTable_OffsetBits, ofCodeTable,
|
|
2340
|
-
CTable_LitLength, llCodeTable,
|
|
2341
|
-
sequences, nbSeq, longOffsets);
|
|
2342
|
-
}
|
|
2343
|
-
|
|
2344
|
-
#endif
|
|
2345
|
-
|
|
2346
|
-
static size_t ZSTD_encodeSequences(
|
|
2347
|
-
void* dst, size_t dstCapacity,
|
|
2348
|
-
FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,
|
|
2349
|
-
FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,
|
|
2350
|
-
FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,
|
|
2351
|
-
seqDef const* sequences, size_t nbSeq, int longOffsets, int bmi2)
|
|
2352
|
-
{
|
|
2353
|
-
DEBUGLOG(5, "ZSTD_encodeSequences: dstCapacity = %u", (unsigned)dstCapacity);
|
|
2354
|
-
#if DYNAMIC_BMI2
|
|
2355
|
-
if (bmi2) {
|
|
2356
|
-
return ZSTD_encodeSequences_bmi2(dst, dstCapacity,
|
|
2357
|
-
CTable_MatchLength, mlCodeTable,
|
|
2358
|
-
CTable_OffsetBits, ofCodeTable,
|
|
2359
|
-
CTable_LitLength, llCodeTable,
|
|
2360
|
-
sequences, nbSeq, longOffsets);
|
|
2361
|
-
}
|
|
2362
|
-
#endif
|
|
2363
|
-
(void)bmi2;
|
|
2364
|
-
return ZSTD_encodeSequences_default(dst, dstCapacity,
|
|
2365
|
-
CTable_MatchLength, mlCodeTable,
|
|
2366
|
-
CTable_OffsetBits, ofCodeTable,
|
|
2367
|
-
CTable_LitLength, llCodeTable,
|
|
2368
|
-
sequences, nbSeq, longOffsets);
|
|
1957
|
+
DEBUGLOG(5, "ZSTD_useTargetCBlockSize (targetCBlockSize=%zu)", cctxParams->targetCBlockSize);
|
|
1958
|
+
return (cctxParams->targetCBlockSize != 0);
|
|
2369
1959
|
}
|
|
2370
1960
|
|
|
2371
1961
|
/* ZSTD_compressSequences_internal():
|
|
@@ -2376,7 +1966,7 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
|
|
|
2376
1966
|
ZSTD_entropyCTables_t* nextEntropy,
|
|
2377
1967
|
const ZSTD_CCtx_params* cctxParams,
|
|
2378
1968
|
void* dst, size_t dstCapacity,
|
|
2379
|
-
void*
|
|
1969
|
+
void* entropyWorkspace, size_t entropyWkspSize,
|
|
2380
1970
|
const int bmi2)
|
|
2381
1971
|
{
|
|
2382
1972
|
const int longOffsets = cctxParams->cParams.windowLog > STREAM_ACCUMULATOR_MIN;
|
|
@@ -2393,52 +1983,59 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
|
|
|
2393
1983
|
BYTE* const ostart = (BYTE*)dst;
|
|
2394
1984
|
BYTE* const oend = ostart + dstCapacity;
|
|
2395
1985
|
BYTE* op = ostart;
|
|
2396
|
-
size_t const nbSeq = seqStorePtr->sequences - seqStorePtr->sequencesStart;
|
|
1986
|
+
size_t const nbSeq = (size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
|
|
2397
1987
|
BYTE* seqHead;
|
|
2398
1988
|
BYTE* lastNCount = NULL;
|
|
2399
1989
|
|
|
1990
|
+
DEBUGLOG(5, "ZSTD_compressSequences_internal (nbSeq=%zu)", nbSeq);
|
|
2400
1991
|
ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<<MAX(MLFSELog,LLFSELog)));
|
|
2401
|
-
DEBUGLOG(5, "ZSTD_compressSequences_internal");
|
|
2402
1992
|
|
|
2403
1993
|
/* Compress literals */
|
|
2404
1994
|
{ const BYTE* const literals = seqStorePtr->litStart;
|
|
2405
|
-
size_t const litSize = seqStorePtr->lit - literals;
|
|
2406
|
-
int const disableLiteralCompression = (cctxParams->cParams.strategy == ZSTD_fast) && (cctxParams->cParams.targetLength > 0);
|
|
1995
|
+
size_t const litSize = (size_t)(seqStorePtr->lit - literals);
|
|
2407
1996
|
size_t const cSize = ZSTD_compressLiterals(
|
|
2408
1997
|
&prevEntropy->huf, &nextEntropy->huf,
|
|
2409
|
-
cctxParams->cParams.strategy,
|
|
1998
|
+
cctxParams->cParams.strategy,
|
|
1999
|
+
ZSTD_disableLiteralsCompression(cctxParams),
|
|
2410
2000
|
op, dstCapacity,
|
|
2411
2001
|
literals, litSize,
|
|
2412
|
-
|
|
2002
|
+
entropyWorkspace, entropyWkspSize,
|
|
2413
2003
|
bmi2);
|
|
2414
|
-
|
|
2415
|
-
return cSize;
|
|
2004
|
+
FORWARD_IF_ERROR(cSize, "ZSTD_compressLiterals failed");
|
|
2416
2005
|
assert(cSize <= dstCapacity);
|
|
2417
2006
|
op += cSize;
|
|
2418
2007
|
}
|
|
2419
2008
|
|
|
2420
2009
|
/* Sequences Header */
|
|
2421
|
-
|
|
2422
|
-
|
|
2010
|
+
RETURN_ERROR_IF((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead*/,
|
|
2011
|
+
dstSize_tooSmall, "Can't fit seq hdr in output buf!");
|
|
2012
|
+
if (nbSeq < 128) {
|
|
2423
2013
|
*op++ = (BYTE)nbSeq;
|
|
2424
|
-
else if (nbSeq < LONGNBSEQ)
|
|
2425
|
-
op[0] = (BYTE)((nbSeq>>8) + 0x80)
|
|
2426
|
-
|
|
2427
|
-
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);
|
|
2428
2024
|
if (nbSeq==0) {
|
|
2429
2025
|
/* Copy the old tables over as if we repeated them */
|
|
2430
2026
|
memcpy(&nextEntropy->fse, &prevEntropy->fse, sizeof(prevEntropy->fse));
|
|
2431
|
-
return op - ostart;
|
|
2027
|
+
return (size_t)(op - ostart);
|
|
2432
2028
|
}
|
|
2433
2029
|
|
|
2434
2030
|
/* seqHead : flags for FSE encoding type */
|
|
2435
2031
|
seqHead = op++;
|
|
2032
|
+
assert(op <= oend);
|
|
2436
2033
|
|
|
2437
2034
|
/* convert length/distances into codes */
|
|
2438
2035
|
ZSTD_seqToCodes(seqStorePtr);
|
|
2439
2036
|
/* build CTable for Literal Lengths */
|
|
2440
2037
|
{ unsigned max = MaxLL;
|
|
2441
|
-
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 */
|
|
2442
2039
|
DEBUGLOG(5, "Building LL table");
|
|
2443
2040
|
nextEntropy->fse.litlength_repeatMode = prevEntropy->fse.litlength_repeatMode;
|
|
2444
2041
|
LLtype = ZSTD_selectEncodingType(&nextEntropy->fse.litlength_repeatMode,
|
|
@@ -2448,18 +2045,24 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
|
|
|
2448
2045
|
ZSTD_defaultAllowed, strategy);
|
|
2449
2046
|
assert(set_basic < set_compressed && set_rle < set_compressed);
|
|
2450
2047
|
assert(!(LLtype < set_compressed && nextEntropy->fse.litlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */
|
|
2451
|
-
{ size_t const countSize = ZSTD_buildCTable(
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
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");
|
|
2456
2057
|
if (LLtype == set_compressed)
|
|
2457
2058
|
lastNCount = op;
|
|
2458
2059
|
op += countSize;
|
|
2060
|
+
assert(op <= oend);
|
|
2459
2061
|
} }
|
|
2460
2062
|
/* build CTable for Offsets */
|
|
2461
2063
|
{ unsigned max = MaxOff;
|
|
2462
|
-
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 */
|
|
2463
2066
|
/* We can only use the basic table if max <= DefaultMaxOff, otherwise the offsets are too large */
|
|
2464
2067
|
ZSTD_defaultPolicy_e const defaultPolicy = (max <= DefaultMaxOff) ? ZSTD_defaultAllowed : ZSTD_defaultDisallowed;
|
|
2465
2068
|
DEBUGLOG(5, "Building OF table");
|
|
@@ -2470,18 +2073,24 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
|
|
|
2470
2073
|
OF_defaultNorm, OF_defaultNormLog,
|
|
2471
2074
|
defaultPolicy, strategy);
|
|
2472
2075
|
assert(!(Offtype < set_compressed && nextEntropy->fse.offcode_repeatMode != FSE_repeat_none)); /* We don't copy tables */
|
|
2473
|
-
{ size_t const countSize = ZSTD_buildCTable(
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
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");
|
|
2478
2085
|
if (Offtype == set_compressed)
|
|
2479
2086
|
lastNCount = op;
|
|
2480
2087
|
op += countSize;
|
|
2088
|
+
assert(op <= oend);
|
|
2481
2089
|
} }
|
|
2482
2090
|
/* build CTable for MatchLengths */
|
|
2483
2091
|
{ unsigned max = MaxML;
|
|
2484
|
-
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 */
|
|
2485
2094
|
DEBUGLOG(5, "Building ML table (remaining space : %i)", (int)(oend-op));
|
|
2486
2095
|
nextEntropy->fse.matchlength_repeatMode = prevEntropy->fse.matchlength_repeatMode;
|
|
2487
2096
|
MLtype = ZSTD_selectEncodingType(&nextEntropy->fse.matchlength_repeatMode,
|
|
@@ -2490,29 +2099,35 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
|
|
|
2490
2099
|
ML_defaultNorm, ML_defaultNormLog,
|
|
2491
2100
|
ZSTD_defaultAllowed, strategy);
|
|
2492
2101
|
assert(!(MLtype < set_compressed && nextEntropy->fse.matchlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */
|
|
2493
|
-
{ size_t const countSize = ZSTD_buildCTable(
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
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");
|
|
2498
2111
|
if (MLtype == set_compressed)
|
|
2499
2112
|
lastNCount = op;
|
|
2500
2113
|
op += countSize;
|
|
2114
|
+
assert(op <= oend);
|
|
2501
2115
|
} }
|
|
2502
2116
|
|
|
2503
2117
|
*seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2));
|
|
2504
2118
|
|
|
2505
2119
|
{ size_t const bitstreamSize = ZSTD_encodeSequences(
|
|
2506
|
-
op, oend - op,
|
|
2120
|
+
op, (size_t)(oend - op),
|
|
2507
2121
|
CTable_MatchLength, mlCodeTable,
|
|
2508
2122
|
CTable_OffsetBits, ofCodeTable,
|
|
2509
2123
|
CTable_LitLength, llCodeTable,
|
|
2510
2124
|
sequences, nbSeq,
|
|
2511
2125
|
longOffsets, bmi2);
|
|
2512
|
-
|
|
2126
|
+
FORWARD_IF_ERROR(bitstreamSize, "ZSTD_encodeSequences failed");
|
|
2513
2127
|
op += bitstreamSize;
|
|
2128
|
+
assert(op <= oend);
|
|
2514
2129
|
/* zstd versions <= 1.3.4 mistakenly report corruption when
|
|
2515
|
-
* FSE_readNCount()
|
|
2130
|
+
* FSE_readNCount() receives a buffer < 4 bytes.
|
|
2516
2131
|
* Fixed by https://github.com/facebook/zstd/pull/1146.
|
|
2517
2132
|
* This can happen when the last set_compressed table present is 2
|
|
2518
2133
|
* bytes and the bitstream is only one byte.
|
|
@@ -2529,7 +2144,7 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
|
|
|
2529
2144
|
}
|
|
2530
2145
|
|
|
2531
2146
|
DEBUGLOG(5, "compressed block size : %u", (unsigned)(op - ostart));
|
|
2532
|
-
return op - ostart;
|
|
2147
|
+
return (size_t)(op - ostart);
|
|
2533
2148
|
}
|
|
2534
2149
|
|
|
2535
2150
|
MEM_STATIC size_t
|
|
@@ -2539,20 +2154,20 @@ ZSTD_compressSequences(seqStore_t* seqStorePtr,
|
|
|
2539
2154
|
const ZSTD_CCtx_params* cctxParams,
|
|
2540
2155
|
void* dst, size_t dstCapacity,
|
|
2541
2156
|
size_t srcSize,
|
|
2542
|
-
void*
|
|
2157
|
+
void* entropyWorkspace, size_t entropyWkspSize,
|
|
2543
2158
|
int bmi2)
|
|
2544
2159
|
{
|
|
2545
2160
|
size_t const cSize = ZSTD_compressSequences_internal(
|
|
2546
2161
|
seqStorePtr, prevEntropy, nextEntropy, cctxParams,
|
|
2547
2162
|
dst, dstCapacity,
|
|
2548
|
-
|
|
2163
|
+
entropyWorkspace, entropyWkspSize, bmi2);
|
|
2549
2164
|
if (cSize == 0) return 0;
|
|
2550
2165
|
/* When srcSize <= dstCapacity, there is enough space to write a raw uncompressed block.
|
|
2551
2166
|
* Since we ran out of space, block must be not compressible, so fall back to raw uncompressed block.
|
|
2552
2167
|
*/
|
|
2553
2168
|
if ((cSize == ERROR(dstSize_tooSmall)) & (srcSize <= dstCapacity))
|
|
2554
2169
|
return 0; /* block not compressed */
|
|
2555
|
-
|
|
2170
|
+
FORWARD_IF_ERROR(cSize, "ZSTD_compressSequences_internal failed");
|
|
2556
2171
|
|
|
2557
2172
|
/* Check compressibility */
|
|
2558
2173
|
{ size_t const maxCSize = srcSize - ZSTD_minGain(srcSize, cctxParams->cParams.strategy);
|
|
@@ -2622,27 +2237,24 @@ void ZSTD_resetSeqStore(seqStore_t* ssPtr)
|
|
|
2622
2237
|
ssPtr->longLengthID = 0;
|
|
2623
2238
|
}
|
|
2624
2239
|
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
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)
|
|
2628
2243
|
{
|
|
2629
2244
|
ZSTD_matchState_t* const ms = &zc->blockState.matchState;
|
|
2630
|
-
|
|
2631
|
-
DEBUGLOG(5, "ZSTD_compressBlock_internal (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u)",
|
|
2632
|
-
(unsigned)dstCapacity, (unsigned)ms->window.dictLimit, (unsigned)ms->nextToUpdate);
|
|
2245
|
+
DEBUGLOG(5, "ZSTD_buildSeqStore (srcSize=%zu)", srcSize);
|
|
2633
2246
|
assert(srcSize <= ZSTD_BLOCKSIZE_MAX);
|
|
2634
|
-
|
|
2635
2247
|
/* Assert that we have correctly flushed the ctx params into the ms's copy */
|
|
2636
2248
|
ZSTD_assertEqualCParams(zc->appliedParams.cParams, ms->cParams);
|
|
2637
|
-
|
|
2638
2249
|
if (srcSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1) {
|
|
2639
2250
|
ZSTD_ldm_skipSequences(&zc->externSeqStore, srcSize, zc->appliedParams.cParams.minMatch);
|
|
2640
|
-
|
|
2641
|
-
goto out; /* don't even attempt compression below a certain srcSize */
|
|
2251
|
+
return ZSTDbss_noCompress; /* don't even attempt compression below a certain srcSize */
|
|
2642
2252
|
}
|
|
2643
2253
|
ZSTD_resetSeqStore(&(zc->seqStore));
|
|
2644
|
-
|
|
2645
|
-
|
|
2254
|
+
/* required for optimal parser to read stats from dictionary */
|
|
2255
|
+
ms->opt.symbolCosts = &zc->blockState.prevCBlock->entropy;
|
|
2256
|
+
/* tell the optimal parser how we expect to compress literals */
|
|
2257
|
+
ms->opt.literalCompressionMode = zc->appliedParams.literalCompressionMode;
|
|
2646
2258
|
/* a gap between an attached dict and the current window is not safe,
|
|
2647
2259
|
* they must remain adjacent,
|
|
2648
2260
|
* and when that stops being the case, the dict must be unset */
|
|
@@ -2679,9 +2291,9 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
|
|
|
2679
2291
|
ldmSeqStore.seq = zc->ldmSequences;
|
|
2680
2292
|
ldmSeqStore.capacity = zc->maxNbLdmSequences;
|
|
2681
2293
|
/* Updates ldmSeqStore.size */
|
|
2682
|
-
|
|
2294
|
+
FORWARD_IF_ERROR(ZSTD_ldm_generateSequences(&zc->ldmState, &ldmSeqStore,
|
|
2683
2295
|
&zc->appliedParams.ldmParams,
|
|
2684
|
-
src, srcSize));
|
|
2296
|
+
src, srcSize), "");
|
|
2685
2297
|
/* Updates ldmSeqStore.pos */
|
|
2686
2298
|
lastLLSize =
|
|
2687
2299
|
ZSTD_ldm_blockCompress(&ldmSeqStore,
|
|
@@ -2696,6 +2308,134 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
|
|
|
2696
2308
|
{ const BYTE* const lastLiterals = (const BYTE*)src + srcSize - lastLLSize;
|
|
2697
2309
|
ZSTD_storeLastLiterals(&zc->seqStore, lastLiterals, lastLLSize);
|
|
2698
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
|
+
}
|
|
2699
2439
|
|
|
2700
2440
|
/* encode sequences and literals */
|
|
2701
2441
|
cSize = ZSTD_compressSequences(&zc->seqStore,
|
|
@@ -2706,12 +2446,22 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
|
|
|
2706
2446
|
zc->entropyWorkspace, HUF_WORKSPACE_SIZE /* statically allocated in resetCCtx */,
|
|
2707
2447
|
zc->bmi2);
|
|
2708
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
|
+
|
|
2709
2462
|
out:
|
|
2710
|
-
if (!ZSTD_isError(cSize) && cSize
|
|
2711
|
-
|
|
2712
|
-
ZSTD_compressedBlockState_t* const tmp = zc->blockState.prevCBlock;
|
|
2713
|
-
zc->blockState.prevCBlock = zc->blockState.nextCBlock;
|
|
2714
|
-
zc->blockState.nextCBlock = tmp;
|
|
2463
|
+
if (!ZSTD_isError(cSize) && cSize > 1) {
|
|
2464
|
+
ZSTD_confirmRepcodesAndEntropyTables(zc);
|
|
2715
2465
|
}
|
|
2716
2466
|
/* We check that dictionaries have offset codes available for the first
|
|
2717
2467
|
* block. After the first block, the offcode table might not have large
|
|
@@ -2723,6 +2473,104 @@ out:
|
|
|
2723
2473
|
return cSize;
|
|
2724
2474
|
}
|
|
2725
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
|
+
}
|
|
2726
2574
|
|
|
2727
2575
|
/*! ZSTD_compress_frameChunk() :
|
|
2728
2576
|
* Compress a chunk of data into one or multiple blocks.
|
|
@@ -2742,7 +2590,8 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
|
|
|
2742
2590
|
BYTE* const ostart = (BYTE*)dst;
|
|
2743
2591
|
BYTE* op = ostart;
|
|
2744
2592
|
U32 const maxDist = (U32)1 << cctx->appliedParams.cParams.windowLog;
|
|
2745
|
-
|
|
2593
|
+
|
|
2594
|
+
assert(cctx->appliedParams.cParams.windowLog <= ZSTD_WINDOWLOG_MAX);
|
|
2746
2595
|
|
|
2747
2596
|
DEBUGLOG(5, "ZSTD_compress_frameChunk (blockSize=%u)", (unsigned)blockSize);
|
|
2748
2597
|
if (cctx->appliedParams.fParams.checksumFlag && srcSize)
|
|
@@ -2752,78 +2601,84 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
|
|
|
2752
2601
|
ZSTD_matchState_t* const ms = &cctx->blockState.matchState;
|
|
2753
2602
|
U32 const lastBlock = lastFrameChunk & (blockSize >= remaining);
|
|
2754
2603
|
|
|
2755
|
-
|
|
2756
|
-
|
|
2604
|
+
RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize + MIN_CBLOCK_SIZE,
|
|
2605
|
+
dstSize_tooSmall,
|
|
2606
|
+
"not enough space to store compressed block");
|
|
2757
2607
|
if (remaining < blockSize) blockSize = remaining;
|
|
2758
2608
|
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30);
|
|
2763
|
-
ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30);
|
|
2764
|
-
ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31);
|
|
2765
|
-
ZSTD_reduceIndex(cctx, correction);
|
|
2766
|
-
if (ms->nextToUpdate < correction) ms->nextToUpdate = 0;
|
|
2767
|
-
else ms->nextToUpdate -= correction;
|
|
2768
|
-
ms->loadedDictEnd = 0;
|
|
2769
|
-
ms->dictMatchState = NULL;
|
|
2770
|
-
}
|
|
2771
|
-
ZSTD_window_enforceMaxDist(&ms->window, ip + blockSize, maxDist, &ms->loadedDictEnd, &ms->dictMatchState);
|
|
2772
|
-
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);
|
|
2773
2612
|
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
ip, blockSize);
|
|
2777
|
-
if (ZSTD_isError(cSize)) return cSize;
|
|
2613
|
+
/* Ensure hash/chain table insertion resumes no sooner than lowlimit */
|
|
2614
|
+
if (ms->nextToUpdate < ms->window.lowLimit) ms->nextToUpdate = ms->window.lowLimit;
|
|
2778
2615
|
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
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);
|
|
2782
2622
|
} else {
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
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
|
+
}
|
|
2786
2638
|
}
|
|
2787
2639
|
|
|
2640
|
+
|
|
2788
2641
|
ip += blockSize;
|
|
2789
2642
|
assert(remaining >= blockSize);
|
|
2790
2643
|
remaining -= blockSize;
|
|
2791
2644
|
op += cSize;
|
|
2792
2645
|
assert(dstCapacity >= cSize);
|
|
2793
2646
|
dstCapacity -= cSize;
|
|
2647
|
+
cctx->isFirstBlock = 0;
|
|
2794
2648
|
DEBUGLOG(5, "ZSTD_compress_frameChunk: adding a block of size %u",
|
|
2795
2649
|
(unsigned)cSize);
|
|
2796
2650
|
} }
|
|
2797
2651
|
|
|
2798
2652
|
if (lastFrameChunk && (op>ostart)) cctx->stage = ZSTDcs_ending;
|
|
2799
|
-
return op-ostart;
|
|
2653
|
+
return (size_t)(op-ostart);
|
|
2800
2654
|
}
|
|
2801
2655
|
|
|
2802
2656
|
|
|
2803
2657
|
static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
|
|
2804
|
-
ZSTD_CCtx_params params, U64 pledgedSrcSize, U32 dictID)
|
|
2658
|
+
const ZSTD_CCtx_params* params, U64 pledgedSrcSize, U32 dictID)
|
|
2805
2659
|
{ BYTE* const op = (BYTE*)dst;
|
|
2806
2660
|
U32 const dictIDSizeCodeLength = (dictID>0) + (dictID>=256) + (dictID>=65536); /* 0-3 */
|
|
2807
|
-
U32 const dictIDSizeCode = params
|
|
2808
|
-
U32 const checksumFlag = params
|
|
2809
|
-
U32 const windowSize = (U32)1 << params
|
|
2810
|
-
U32 const singleSegment = params
|
|
2811
|
-
BYTE const windowLogByte = (BYTE)((params
|
|
2812
|
-
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 ?
|
|
2813
2667
|
(pledgedSrcSize>=256) + (pledgedSrcSize>=65536+256) + (pledgedSrcSize>=0xFFFFFFFFU) : 0; /* 0-3 */
|
|
2814
|
-
BYTE const
|
|
2668
|
+
BYTE const frameHeaderDescriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag<<2) + (singleSegment<<5) + (fcsCode<<6) );
|
|
2815
2669
|
size_t pos=0;
|
|
2816
2670
|
|
|
2817
|
-
assert(!(params
|
|
2818
|
-
|
|
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.");
|
|
2819
2674
|
DEBUGLOG(4, "ZSTD_writeFrameHeader : dictIDFlag : %u ; dictID : %u ; dictIDSizeCode : %u",
|
|
2820
|
-
!params
|
|
2675
|
+
!params->fParams.noDictIDFlag, (unsigned)dictID, (unsigned)dictIDSizeCode);
|
|
2821
2676
|
|
|
2822
|
-
if (params
|
|
2677
|
+
if (params->format == ZSTD_f_zstd1) {
|
|
2823
2678
|
MEM_writeLE32(dst, ZSTD_MAGICNUMBER);
|
|
2824
2679
|
pos = 4;
|
|
2825
2680
|
}
|
|
2826
|
-
op[pos++] =
|
|
2681
|
+
op[pos++] = frameHeaderDescriptionByte;
|
|
2827
2682
|
if (!singleSegment) op[pos++] = windowLogByte;
|
|
2828
2683
|
switch(dictIDSizeCode)
|
|
2829
2684
|
{
|
|
@@ -2847,11 +2702,12 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
|
|
|
2847
2702
|
/* ZSTD_writeLastEmptyBlock() :
|
|
2848
2703
|
* output an empty Block with end-of-frame mark to complete a frame
|
|
2849
2704
|
* @return : size of data written into `dst` (== ZSTD_blockHeaderSize (defined in zstd_internal.h))
|
|
2850
|
-
* or an error code if `
|
|
2705
|
+
* or an error code if `dstCapacity` is too small (<ZSTD_blockHeaderSize)
|
|
2851
2706
|
*/
|
|
2852
2707
|
size_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity)
|
|
2853
2708
|
{
|
|
2854
|
-
|
|
2709
|
+
RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize, dstSize_tooSmall,
|
|
2710
|
+
"dst buf is too small to write frame trailer empty block.");
|
|
2855
2711
|
{ U32 const cBlockHeader24 = 1 /*lastBlock*/ + (((U32)bt_raw)<<1); /* 0 size */
|
|
2856
2712
|
MEM_writeLE24(dst, cBlockHeader24);
|
|
2857
2713
|
return ZSTD_blockHeaderSize;
|
|
@@ -2860,10 +2716,11 @@ size_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity)
|
|
|
2860
2716
|
|
|
2861
2717
|
size_t ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSeq)
|
|
2862
2718
|
{
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2719
|
+
RETURN_ERROR_IF(cctx->stage != ZSTDcs_init, stage_wrong,
|
|
2720
|
+
"wrong cctx stage");
|
|
2721
|
+
RETURN_ERROR_IF(cctx->appliedParams.ldmParams.enableLdm,
|
|
2722
|
+
parameter_unsupported,
|
|
2723
|
+
"incompatible with ldm");
|
|
2867
2724
|
cctx->externSeqStore.seq = seq;
|
|
2868
2725
|
cctx->externSeqStore.size = nbSeq;
|
|
2869
2726
|
cctx->externSeqStore.capacity = nbSeq;
|
|
@@ -2882,12 +2739,14 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
|
|
|
2882
2739
|
|
|
2883
2740
|
DEBUGLOG(5, "ZSTD_compressContinue_internal, stage: %u, srcSize: %u",
|
|
2884
2741
|
cctx->stage, (unsigned)srcSize);
|
|
2885
|
-
|
|
2742
|
+
RETURN_ERROR_IF(cctx->stage==ZSTDcs_created, stage_wrong,
|
|
2743
|
+
"missing init (ZSTD_compressBegin)");
|
|
2886
2744
|
|
|
2887
2745
|
if (frame && (cctx->stage==ZSTDcs_init)) {
|
|
2888
|
-
fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, cctx->appliedParams,
|
|
2746
|
+
fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, &cctx->appliedParams,
|
|
2889
2747
|
cctx->pledgedSrcSizePlusOne-1, cctx->dictID);
|
|
2890
|
-
|
|
2748
|
+
FORWARD_IF_ERROR(fhSize, "ZSTD_writeFrameHeader failed");
|
|
2749
|
+
assert(fhSize <= dstCapacity);
|
|
2891
2750
|
dstCapacity -= fhSize;
|
|
2892
2751
|
dst = (char*)dst + fhSize;
|
|
2893
2752
|
cctx->stage = ZSTDcs_ongoing;
|
|
@@ -2904,35 +2763,27 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
|
|
|
2904
2763
|
|
|
2905
2764
|
if (!frame) {
|
|
2906
2765
|
/* overflow check and correction for block mode */
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30);
|
|
2911
|
-
ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30);
|
|
2912
|
-
ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31);
|
|
2913
|
-
ZSTD_reduceIndex(cctx, correction);
|
|
2914
|
-
if (ms->nextToUpdate < correction) ms->nextToUpdate = 0;
|
|
2915
|
-
else ms->nextToUpdate -= correction;
|
|
2916
|
-
ms->loadedDictEnd = 0;
|
|
2917
|
-
ms->dictMatchState = NULL;
|
|
2918
|
-
}
|
|
2766
|
+
ZSTD_overflowCorrectIfNeeded(
|
|
2767
|
+
ms, &cctx->workspace, &cctx->appliedParams,
|
|
2768
|
+
src, (BYTE const*)src + srcSize);
|
|
2919
2769
|
}
|
|
2920
2770
|
|
|
2921
2771
|
DEBUGLOG(5, "ZSTD_compressContinue_internal (blockSize=%u)", (unsigned)cctx->blockSize);
|
|
2922
2772
|
{ size_t const cSize = frame ?
|
|
2923
2773
|
ZSTD_compress_frameChunk (cctx, dst, dstCapacity, src, srcSize, lastFrameChunk) :
|
|
2924
|
-
ZSTD_compressBlock_internal (cctx, dst, dstCapacity, src, srcSize);
|
|
2925
|
-
|
|
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");
|
|
2926
2776
|
cctx->consumedSrcSize += srcSize;
|
|
2927
2777
|
cctx->producedCSize += (cSize + fhSize);
|
|
2928
2778
|
assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0));
|
|
2929
2779
|
if (cctx->pledgedSrcSizePlusOne != 0) { /* control src size */
|
|
2930
2780
|
ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN == (unsigned long long)-1);
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2781
|
+
RETURN_ERROR_IF(
|
|
2782
|
+
cctx->consumedSrcSize+1 > cctx->pledgedSrcSizePlusOne,
|
|
2783
|
+
srcSize_wrong,
|
|
2784
|
+
"error : pledgedSrcSize = %u, while realSrcSize >= %u",
|
|
2785
|
+
(unsigned)cctx->pledgedSrcSizePlusOne-1,
|
|
2786
|
+
(unsigned)cctx->consumedSrcSize);
|
|
2936
2787
|
}
|
|
2937
2788
|
return cSize + fhSize;
|
|
2938
2789
|
}
|
|
@@ -2956,8 +2807,9 @@ size_t ZSTD_getBlockSize(const ZSTD_CCtx* cctx)
|
|
|
2956
2807
|
|
|
2957
2808
|
size_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
|
|
2958
2809
|
{
|
|
2959
|
-
|
|
2960
|
-
|
|
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"); }
|
|
2961
2813
|
|
|
2962
2814
|
return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 0 /* frame mode */, 0 /* last chunk */);
|
|
2963
2815
|
}
|
|
@@ -2966,47 +2818,67 @@ size_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const
|
|
|
2966
2818
|
* @return : 0, or an error code
|
|
2967
2819
|
*/
|
|
2968
2820
|
static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms,
|
|
2821
|
+
ldmState_t* ls,
|
|
2822
|
+
ZSTD_cwksp* ws,
|
|
2969
2823
|
ZSTD_CCtx_params const* params,
|
|
2970
2824
|
const void* src, size_t srcSize,
|
|
2971
2825
|
ZSTD_dictTableLoadMethod_e dtlm)
|
|
2972
2826
|
{
|
|
2973
|
-
const BYTE*
|
|
2827
|
+
const BYTE* ip = (const BYTE*) src;
|
|
2974
2828
|
const BYTE* const iend = ip + srcSize;
|
|
2975
2829
|
|
|
2976
2830
|
ZSTD_window_update(&ms->window, src, srcSize);
|
|
2977
2831
|
ms->loadedDictEnd = params->forceWindow ? 0 : (U32)(iend - ms->window.base);
|
|
2978
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
|
+
|
|
2979
2838
|
/* Assert that we the ms params match the params we're being given */
|
|
2980
2839
|
ZSTD_assertEqualCParams(params->cParams, ms->cParams);
|
|
2981
2840
|
|
|
2982
2841
|
if (srcSize <= HASH_READ_SIZE) return 0;
|
|
2983
2842
|
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
break;
|
|
2989
|
-
case ZSTD_dfast:
|
|
2990
|
-
ZSTD_fillDoubleHashTable(ms, iend, dtlm);
|
|
2991
|
-
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;
|
|
2992
2847
|
|
|
2993
|
-
|
|
2994
|
-
case ZSTD_lazy:
|
|
2995
|
-
case ZSTD_lazy2:
|
|
2996
|
-
if (srcSize >= HASH_READ_SIZE)
|
|
2997
|
-
ZSTD_insertAndFindFirstIndex(ms, iend-HASH_READ_SIZE);
|
|
2998
|
-
break;
|
|
2848
|
+
ZSTD_overflowCorrectIfNeeded(ms, ws, params, ip, ichunk);
|
|
2999
2849
|
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
case ZSTD_btultra:
|
|
3003
|
-
case ZSTD_btultra2:
|
|
3004
|
-
if (srcSize >= HASH_READ_SIZE)
|
|
3005
|
-
ZSTD_updateTree(ms, iend-HASH_READ_SIZE, iend);
|
|
3006
|
-
break;
|
|
2850
|
+
if (params->ldmParams.enableLdm && ls != NULL)
|
|
2851
|
+
ZSTD_ldm_fillHashTable(ls, (const BYTE*)src, (const BYTE*)src + srcSize, ¶ms->ldmParams);
|
|
3007
2852
|
|
|
3008
|
-
|
|
3009
|
-
|
|
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;
|
|
3010
2882
|
}
|
|
3011
2883
|
|
|
3012
2884
|
ms->nextToUpdate = (U32)(iend - ms->window.base);
|
|
@@ -3020,98 +2892,123 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms,
|
|
|
3020
2892
|
NOTE: This behavior is not standard and could be improved in the future. */
|
|
3021
2893
|
static size_t ZSTD_checkDictNCount(short* normalizedCounter, unsigned dictMaxSymbolValue, unsigned maxSymbolValue) {
|
|
3022
2894
|
U32 s;
|
|
3023
|
-
|
|
2895
|
+
RETURN_ERROR_IF(dictMaxSymbolValue < maxSymbolValue, dictionary_corrupted, "dict fse tables don't have all symbols");
|
|
3024
2896
|
for (s = 0; s <= maxSymbolValue; ++s) {
|
|
3025
|
-
|
|
2897
|
+
RETURN_ERROR_IF(normalizedCounter[s] == 0, dictionary_corrupted, "dict fse tables don't have all symbols");
|
|
3026
2898
|
}
|
|
3027
2899
|
return 0;
|
|
3028
2900
|
}
|
|
3029
2901
|
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
*
|
|
3033
|
-
* https://github.com/facebook/zstd/blob/master/doc/zstd_compression_format.md#dictionary-format
|
|
3034
|
-
*/
|
|
3035
|
-
/*! ZSTD_loadZstdDictionary() :
|
|
3036
|
-
* @return : dictID, or an error code
|
|
3037
|
-
* assumptions : magic number supposed already checked
|
|
3038
|
-
* dictSize supposed > 8
|
|
3039
|
-
*/
|
|
3040
|
-
static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs,
|
|
3041
|
-
ZSTD_matchState_t* ms,
|
|
3042
|
-
ZSTD_CCtx_params const* params,
|
|
3043
|
-
const void* dict, size_t dictSize,
|
|
3044
|
-
ZSTD_dictTableLoadMethod_e dtlm,
|
|
3045
|
-
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)
|
|
3046
2905
|
{
|
|
3047
|
-
const BYTE* dictPtr = (const BYTE*)dict;
|
|
2906
|
+
const BYTE* dictPtr = (const BYTE*)dict; /* skip magic num and dict ID */
|
|
3048
2907
|
const BYTE* const dictEnd = dictPtr + dictSize;
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
size_t dictID;
|
|
2908
|
+
dictPtr += 8;
|
|
2909
|
+
bs->entropy.huf.repeatMode = HUF_repeat_check;
|
|
3052
2910
|
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
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);
|
|
3056
2915
|
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
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;
|
|
3060
2920
|
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
if (HUF_isError(hufHeaderSize)) return ERROR(dictionary_corrupted);
|
|
3064
|
-
if (maxSymbolValue < 255) return ERROR(dictionary_corrupted);
|
|
2921
|
+
RETURN_ERROR_IF(HUF_isError(hufHeaderSize), dictionary_corrupted, "");
|
|
2922
|
+
RETURN_ERROR_IF(maxSymbolValue < 255, dictionary_corrupted, "");
|
|
3065
2923
|
dictPtr += hufHeaderSize;
|
|
3066
2924
|
}
|
|
3067
2925
|
|
|
3068
2926
|
{ unsigned offcodeLog;
|
|
3069
|
-
size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount,
|
|
3070
|
-
|
|
3071
|
-
|
|
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, "");
|
|
3072
2930
|
/* Defer checking offcodeMaxValue because we need to know the size of the dictionary content */
|
|
3073
2931
|
/* fill all offset symbols to avoid garbage at end of table */
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
2932
|
+
RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(
|
|
2933
|
+
bs->entropy.fse.offcodeCTable,
|
|
2934
|
+
offcodeNCount, MaxOff, offcodeLog,
|
|
2935
|
+
workspace, HUF_WORKSPACE_SIZE)),
|
|
2936
|
+
dictionary_corrupted, "");
|
|
3078
2937
|
dictPtr += offcodeHeaderSize;
|
|
3079
2938
|
}
|
|
3080
2939
|
|
|
3081
2940
|
{ short matchlengthNCount[MaxML+1];
|
|
3082
2941
|
unsigned matchlengthMaxValue = MaxML, matchlengthLog;
|
|
3083
2942
|
size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
|
|
3084
|
-
|
|
3085
|
-
|
|
2943
|
+
RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted, "");
|
|
2944
|
+
RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted, "");
|
|
3086
2945
|
/* Every match length code must have non-zero probability */
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
2946
|
+
FORWARD_IF_ERROR( ZSTD_checkDictNCount(matchlengthNCount, matchlengthMaxValue, MaxML), "");
|
|
2947
|
+
RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(
|
|
2948
|
+
bs->entropy.fse.matchlengthCTable,
|
|
2949
|
+
matchlengthNCount, matchlengthMaxValue, matchlengthLog,
|
|
2950
|
+
workspace, HUF_WORKSPACE_SIZE)),
|
|
2951
|
+
dictionary_corrupted, "");
|
|
3092
2952
|
dictPtr += matchlengthHeaderSize;
|
|
3093
2953
|
}
|
|
3094
2954
|
|
|
3095
2955
|
{ short litlengthNCount[MaxLL+1];
|
|
3096
2956
|
unsigned litlengthMaxValue = MaxLL, litlengthLog;
|
|
3097
2957
|
size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
|
|
3098
|
-
|
|
3099
|
-
|
|
2958
|
+
RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted, "");
|
|
2959
|
+
RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted, "");
|
|
3100
2960
|
/* Every literal length code must have non-zero probability */
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
2961
|
+
FORWARD_IF_ERROR( ZSTD_checkDictNCount(litlengthNCount, litlengthMaxValue, MaxLL), "");
|
|
2962
|
+
RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(
|
|
2963
|
+
bs->entropy.fse.litlengthCTable,
|
|
2964
|
+
litlengthNCount, litlengthMaxValue, litlengthLog,
|
|
2965
|
+
workspace, HUF_WORKSPACE_SIZE)),
|
|
2966
|
+
dictionary_corrupted, "");
|
|
3106
2967
|
dictPtr += litlengthHeaderSize;
|
|
3107
2968
|
}
|
|
3108
2969
|
|
|
3109
|
-
|
|
2970
|
+
RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted, "");
|
|
3110
2971
|
bs->rep[0] = MEM_readLE32(dictPtr+0);
|
|
3111
2972
|
bs->rep[1] = MEM_readLE32(dictPtr+4);
|
|
3112
2973
|
bs->rep[2] = MEM_readLE32(dictPtr+8);
|
|
3113
2974
|
dictPtr += 12;
|
|
3114
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
|
+
|
|
3115
3012
|
{ size_t const dictContentSize = (size_t)(dictEnd - dictPtr);
|
|
3116
3013
|
U32 offcodeMax = MaxOff;
|
|
3117
3014
|
if (dictContentSize <= ((U32)-1) - 128 KB) {
|
|
@@ -3119,19 +3016,19 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs,
|
|
|
3119
3016
|
offcodeMax = ZSTD_highbit32(maxOffset); /* Calculate minimum offset code required to represent maxOffset */
|
|
3120
3017
|
}
|
|
3121
3018
|
/* All offset values <= dictContentSize + 128 KB must be representable */
|
|
3122
|
-
|
|
3019
|
+
FORWARD_IF_ERROR(ZSTD_checkDictNCount(offcodeNCount, offcodeMaxValue, MIN(offcodeMax, MaxOff)), "");
|
|
3123
3020
|
/* All repCodes must be <= dictContentSize and != 0*/
|
|
3124
3021
|
{ U32 u;
|
|
3125
3022
|
for (u=0; u<3; u++) {
|
|
3126
|
-
|
|
3127
|
-
|
|
3023
|
+
RETURN_ERROR_IF(bs->rep[u] == 0, dictionary_corrupted, "");
|
|
3024
|
+
RETURN_ERROR_IF(bs->rep[u] > dictContentSize, dictionary_corrupted, "");
|
|
3128
3025
|
} }
|
|
3129
3026
|
|
|
3130
|
-
bs->entropy.huf.repeatMode = HUF_repeat_valid;
|
|
3131
3027
|
bs->entropy.fse.offcode_repeatMode = FSE_repeat_valid;
|
|
3132
3028
|
bs->entropy.fse.matchlength_repeatMode = FSE_repeat_valid;
|
|
3133
3029
|
bs->entropy.fse.litlength_repeatMode = FSE_repeat_valid;
|
|
3134
|
-
|
|
3030
|
+
FORWARD_IF_ERROR(ZSTD_loadDictionaryContent(
|
|
3031
|
+
ms, NULL, ws, params, dictPtr, dictContentSize, dtlm), "");
|
|
3135
3032
|
return dictID;
|
|
3136
3033
|
}
|
|
3137
3034
|
}
|
|
@@ -3141,6 +3038,8 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs,
|
|
|
3141
3038
|
static size_t
|
|
3142
3039
|
ZSTD_compress_insertDictionary(ZSTD_compressedBlockState_t* bs,
|
|
3143
3040
|
ZSTD_matchState_t* ms,
|
|
3041
|
+
ldmState_t* ls,
|
|
3042
|
+
ZSTD_cwksp* ws,
|
|
3144
3043
|
const ZSTD_CCtx_params* params,
|
|
3145
3044
|
const void* dict, size_t dictSize,
|
|
3146
3045
|
ZSTD_dictContentType_e dictContentType,
|
|
@@ -3148,28 +3047,35 @@ ZSTD_compress_insertDictionary(ZSTD_compressedBlockState_t* bs,
|
|
|
3148
3047
|
void* workspace)
|
|
3149
3048
|
{
|
|
3150
3049
|
DEBUGLOG(4, "ZSTD_compress_insertDictionary (dictSize=%u)", (U32)dictSize);
|
|
3151
|
-
if ((dict==NULL) || (dictSize
|
|
3050
|
+
if ((dict==NULL) || (dictSize<8)) {
|
|
3051
|
+
RETURN_ERROR_IF(dictContentType == ZSTD_dct_fullDict, dictionary_wrong, "");
|
|
3052
|
+
return 0;
|
|
3053
|
+
}
|
|
3152
3054
|
|
|
3153
3055
|
ZSTD_reset_compressedBlockState(bs);
|
|
3154
3056
|
|
|
3155
3057
|
/* dict restricted modes */
|
|
3156
3058
|
if (dictContentType == ZSTD_dct_rawContent)
|
|
3157
|
-
return ZSTD_loadDictionaryContent(ms, params, dict, dictSize, dtlm);
|
|
3059
|
+
return ZSTD_loadDictionaryContent(ms, ls, ws, params, dict, dictSize, dtlm);
|
|
3158
3060
|
|
|
3159
3061
|
if (MEM_readLE32(dict) != ZSTD_MAGIC_DICTIONARY) {
|
|
3160
3062
|
if (dictContentType == ZSTD_dct_auto) {
|
|
3161
3063
|
DEBUGLOG(4, "raw content dictionary detected");
|
|
3162
|
-
return ZSTD_loadDictionaryContent(
|
|
3064
|
+
return ZSTD_loadDictionaryContent(
|
|
3065
|
+
ms, ls, ws, params, dict, dictSize, dtlm);
|
|
3163
3066
|
}
|
|
3164
|
-
|
|
3165
|
-
return ERROR(dictionary_wrong);
|
|
3067
|
+
RETURN_ERROR_IF(dictContentType == ZSTD_dct_fullDict, dictionary_wrong, "");
|
|
3166
3068
|
assert(0); /* impossible */
|
|
3167
3069
|
}
|
|
3168
3070
|
|
|
3169
3071
|
/* dict as full zstd dictionary */
|
|
3170
|
-
return ZSTD_loadZstdDictionary(
|
|
3072
|
+
return ZSTD_loadZstdDictionary(
|
|
3073
|
+
bs, ms, ws, params, dict, dictSize, dtlm, workspace);
|
|
3171
3074
|
}
|
|
3172
3075
|
|
|
3076
|
+
#define ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF (128 KB)
|
|
3077
|
+
#define ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER (6)
|
|
3078
|
+
|
|
3173
3079
|
/*! ZSTD_compressBegin_internal() :
|
|
3174
3080
|
* @return : 0, or an error code */
|
|
3175
3081
|
static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
|
|
@@ -3177,26 +3083,37 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
|
|
|
3177
3083
|
ZSTD_dictContentType_e dictContentType,
|
|
3178
3084
|
ZSTD_dictTableLoadMethod_e dtlm,
|
|
3179
3085
|
const ZSTD_CDict* cdict,
|
|
3180
|
-
ZSTD_CCtx_params params, U64 pledgedSrcSize,
|
|
3086
|
+
const ZSTD_CCtx_params* params, U64 pledgedSrcSize,
|
|
3181
3087
|
ZSTD_buffered_policy_e zbuff)
|
|
3182
3088
|
{
|
|
3183
|
-
DEBUGLOG(4, "ZSTD_compressBegin_internal: wlog=%u", params
|
|
3089
|
+
DEBUGLOG(4, "ZSTD_compressBegin_internal: wlog=%u", params->cParams.windowLog);
|
|
3184
3090
|
/* params are supposed to be fully validated at this point */
|
|
3185
|
-
assert(!ZSTD_isError(ZSTD_checkCParams(params
|
|
3091
|
+
assert(!ZSTD_isError(ZSTD_checkCParams(params->cParams)));
|
|
3186
3092
|
assert(!((dict) && (cdict))); /* either dict or cdict, not both */
|
|
3187
|
-
|
|
3188
|
-
|
|
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) ) {
|
|
3189
3100
|
return ZSTD_resetCCtx_usingCDict(cctx, cdict, params, pledgedSrcSize, zbuff);
|
|
3190
3101
|
}
|
|
3191
3102
|
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
{
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
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);
|
|
3200
3117
|
cctx->dictID = (U32)dictID;
|
|
3201
3118
|
}
|
|
3202
3119
|
return 0;
|
|
@@ -3207,12 +3124,12 @@ size_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx,
|
|
|
3207
3124
|
ZSTD_dictContentType_e dictContentType,
|
|
3208
3125
|
ZSTD_dictTableLoadMethod_e dtlm,
|
|
3209
3126
|
const ZSTD_CDict* cdict,
|
|
3210
|
-
ZSTD_CCtx_params params,
|
|
3127
|
+
const ZSTD_CCtx_params* params,
|
|
3211
3128
|
unsigned long long pledgedSrcSize)
|
|
3212
3129
|
{
|
|
3213
|
-
DEBUGLOG(4, "ZSTD_compressBegin_advanced_internal: wlog=%u", params
|
|
3130
|
+
DEBUGLOG(4, "ZSTD_compressBegin_advanced_internal: wlog=%u", params->cParams.windowLog);
|
|
3214
3131
|
/* compression parameters verification and optimization */
|
|
3215
|
-
|
|
3132
|
+
FORWARD_IF_ERROR( ZSTD_checkCParams(params->cParams) , "");
|
|
3216
3133
|
return ZSTD_compressBegin_internal(cctx,
|
|
3217
3134
|
dict, dictSize, dictContentType, dtlm,
|
|
3218
3135
|
cdict,
|
|
@@ -3227,21 +3144,21 @@ size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx,
|
|
|
3227
3144
|
ZSTD_parameters params, unsigned long long pledgedSrcSize)
|
|
3228
3145
|
{
|
|
3229
3146
|
ZSTD_CCtx_params const cctxParams =
|
|
3230
|
-
ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
|
|
3147
|
+
ZSTD_assignParamsToCCtxParams(&cctx->requestedParams, ¶ms);
|
|
3231
3148
|
return ZSTD_compressBegin_advanced_internal(cctx,
|
|
3232
3149
|
dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast,
|
|
3233
3150
|
NULL /*cdict*/,
|
|
3234
|
-
cctxParams, pledgedSrcSize);
|
|
3151
|
+
&cctxParams, pledgedSrcSize);
|
|
3235
3152
|
}
|
|
3236
3153
|
|
|
3237
3154
|
size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel)
|
|
3238
3155
|
{
|
|
3239
|
-
ZSTD_parameters const params =
|
|
3156
|
+
ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize);
|
|
3240
3157
|
ZSTD_CCtx_params const cctxParams =
|
|
3241
|
-
ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
|
|
3158
|
+
ZSTD_assignParamsToCCtxParams(&cctx->requestedParams, ¶ms);
|
|
3242
3159
|
DEBUGLOG(4, "ZSTD_compressBegin_usingDict (dictSize=%u)", (unsigned)dictSize);
|
|
3243
3160
|
return ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, NULL,
|
|
3244
|
-
cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, ZSTDb_not_buffered);
|
|
3161
|
+
&cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, ZSTDb_not_buffered);
|
|
3245
3162
|
}
|
|
3246
3163
|
|
|
3247
3164
|
size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel)
|
|
@@ -3260,12 +3177,12 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
|
|
|
3260
3177
|
size_t fhSize = 0;
|
|
3261
3178
|
|
|
3262
3179
|
DEBUGLOG(4, "ZSTD_writeEpilogue");
|
|
3263
|
-
|
|
3180
|
+
RETURN_ERROR_IF(cctx->stage == ZSTDcs_created, stage_wrong, "init missing");
|
|
3264
3181
|
|
|
3265
3182
|
/* special case : empty frame */
|
|
3266
3183
|
if (cctx->stage == ZSTDcs_init) {
|
|
3267
|
-
fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, cctx->appliedParams, 0, 0);
|
|
3268
|
-
|
|
3184
|
+
fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, &cctx->appliedParams, 0, 0);
|
|
3185
|
+
FORWARD_IF_ERROR(fhSize, "ZSTD_writeFrameHeader failed");
|
|
3269
3186
|
dstCapacity -= fhSize;
|
|
3270
3187
|
op += fhSize;
|
|
3271
3188
|
cctx->stage = ZSTDcs_ongoing;
|
|
@@ -3274,7 +3191,7 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
|
|
|
3274
3191
|
if (cctx->stage != ZSTDcs_ending) {
|
|
3275
3192
|
/* write one last empty block, make it the "last" block */
|
|
3276
3193
|
U32 const cBlockHeader24 = 1 /* last block */ + (((U32)bt_raw)<<1) + 0;
|
|
3277
|
-
|
|
3194
|
+
RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, "no room for epilogue");
|
|
3278
3195
|
MEM_writeLE32(op, cBlockHeader24);
|
|
3279
3196
|
op += ZSTD_blockHeaderSize;
|
|
3280
3197
|
dstCapacity -= ZSTD_blockHeaderSize;
|
|
@@ -3282,7 +3199,7 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
|
|
|
3282
3199
|
|
|
3283
3200
|
if (cctx->appliedParams.fParams.checksumFlag) {
|
|
3284
3201
|
U32 const checksum = (U32) XXH64_digest(&cctx->xxhState);
|
|
3285
|
-
|
|
3202
|
+
RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, "no room for checksum");
|
|
3286
3203
|
DEBUGLOG(4, "ZSTD_writeEpilogue: write checksum : %08X", (unsigned)checksum);
|
|
3287
3204
|
MEM_writeLE32(op, checksum);
|
|
3288
3205
|
op += 4;
|
|
@@ -3300,18 +3217,20 @@ size_t ZSTD_compressEnd (ZSTD_CCtx* cctx,
|
|
|
3300
3217
|
size_t const cSize = ZSTD_compressContinue_internal(cctx,
|
|
3301
3218
|
dst, dstCapacity, src, srcSize,
|
|
3302
3219
|
1 /* frame mode */, 1 /* last chunk */);
|
|
3303
|
-
|
|
3220
|
+
FORWARD_IF_ERROR(cSize, "ZSTD_compressContinue_internal failed");
|
|
3304
3221
|
endResult = ZSTD_writeEpilogue(cctx, (char*)dst + cSize, dstCapacity-cSize);
|
|
3305
|
-
|
|
3222
|
+
FORWARD_IF_ERROR(endResult, "ZSTD_writeEpilogue failed");
|
|
3306
3223
|
assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0));
|
|
3307
3224
|
if (cctx->pledgedSrcSizePlusOne != 0) { /* control src size */
|
|
3308
3225
|
ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN == (unsigned long long)-1);
|
|
3309
3226
|
DEBUGLOG(4, "end of frame : controlling src size");
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3227
|
+
RETURN_ERROR_IF(
|
|
3228
|
+
cctx->pledgedSrcSizePlusOne != cctx->consumedSrcSize+1,
|
|
3229
|
+
srcSize_wrong,
|
|
3230
|
+
"error : pledgedSrcSize = %u, while realSrcSize = %u",
|
|
3231
|
+
(unsigned)cctx->pledgedSrcSizePlusOne-1,
|
|
3232
|
+
(unsigned)cctx->consumedSrcSize);
|
|
3233
|
+
}
|
|
3315
3234
|
return cSize + endResult;
|
|
3316
3235
|
}
|
|
3317
3236
|
|
|
@@ -3320,16 +3239,16 @@ static size_t ZSTD_compress_internal (ZSTD_CCtx* cctx,
|
|
|
3320
3239
|
void* dst, size_t dstCapacity,
|
|
3321
3240
|
const void* src, size_t srcSize,
|
|
3322
3241
|
const void* dict,size_t dictSize,
|
|
3323
|
-
|
|
3242
|
+
const ZSTD_parameters* params)
|
|
3324
3243
|
{
|
|
3325
3244
|
ZSTD_CCtx_params const cctxParams =
|
|
3326
|
-
ZSTD_assignParamsToCCtxParams(cctx->requestedParams, params);
|
|
3245
|
+
ZSTD_assignParamsToCCtxParams(&cctx->requestedParams, params);
|
|
3327
3246
|
DEBUGLOG(4, "ZSTD_compress_internal");
|
|
3328
3247
|
return ZSTD_compress_advanced_internal(cctx,
|
|
3329
3248
|
dst, dstCapacity,
|
|
3330
3249
|
src, srcSize,
|
|
3331
3250
|
dict, dictSize,
|
|
3332
|
-
cctxParams);
|
|
3251
|
+
&cctxParams);
|
|
3333
3252
|
}
|
|
3334
3253
|
|
|
3335
3254
|
size_t ZSTD_compress_advanced (ZSTD_CCtx* cctx,
|
|
@@ -3339,12 +3258,12 @@ size_t ZSTD_compress_advanced (ZSTD_CCtx* cctx,
|
|
|
3339
3258
|
ZSTD_parameters params)
|
|
3340
3259
|
{
|
|
3341
3260
|
DEBUGLOG(4, "ZSTD_compress_advanced");
|
|
3342
|
-
|
|
3261
|
+
FORWARD_IF_ERROR(ZSTD_checkCParams(params.cParams), "");
|
|
3343
3262
|
return ZSTD_compress_internal(cctx,
|
|
3344
3263
|
dst, dstCapacity,
|
|
3345
3264
|
src, srcSize,
|
|
3346
3265
|
dict, dictSize,
|
|
3347
|
-
params);
|
|
3266
|
+
¶ms);
|
|
3348
3267
|
}
|
|
3349
3268
|
|
|
3350
3269
|
/* Internal */
|
|
@@ -3353,12 +3272,12 @@ size_t ZSTD_compress_advanced_internal(
|
|
|
3353
3272
|
void* dst, size_t dstCapacity,
|
|
3354
3273
|
const void* src, size_t srcSize,
|
|
3355
3274
|
const void* dict,size_t dictSize,
|
|
3356
|
-
ZSTD_CCtx_params params)
|
|
3275
|
+
const ZSTD_CCtx_params* params)
|
|
3357
3276
|
{
|
|
3358
3277
|
DEBUGLOG(4, "ZSTD_compress_advanced_internal (srcSize:%u)", (unsigned)srcSize);
|
|
3359
|
-
|
|
3278
|
+
FORWARD_IF_ERROR( ZSTD_compressBegin_internal(cctx,
|
|
3360
3279
|
dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, NULL,
|
|
3361
|
-
params, srcSize, ZSTDb_not_buffered) );
|
|
3280
|
+
params, srcSize, ZSTDb_not_buffered) , "");
|
|
3362
3281
|
return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize);
|
|
3363
3282
|
}
|
|
3364
3283
|
|
|
@@ -3368,10 +3287,11 @@ size_t ZSTD_compress_usingDict(ZSTD_CCtx* cctx,
|
|
|
3368
3287
|
const void* dict, size_t dictSize,
|
|
3369
3288
|
int compressionLevel)
|
|
3370
3289
|
{
|
|
3371
|
-
ZSTD_parameters const params =
|
|
3372
|
-
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);
|
|
3373
3293
|
assert(params.fParams.contentSizeFlag == 1);
|
|
3374
|
-
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);
|
|
3375
3295
|
}
|
|
3376
3296
|
|
|
3377
3297
|
size_t ZSTD_compressCCtx(ZSTD_CCtx* cctx,
|
|
@@ -3406,13 +3326,16 @@ size_t ZSTD_estimateCDictSize_advanced(
|
|
|
3406
3326
|
ZSTD_dictLoadMethod_e dictLoadMethod)
|
|
3407
3327
|
{
|
|
3408
3328
|
DEBUGLOG(5, "sizeof(ZSTD_CDict) : %u", (unsigned)sizeof(ZSTD_CDict));
|
|
3409
|
-
return sizeof(ZSTD_CDict)
|
|
3410
|
-
|
|
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 *))));
|
|
3411
3334
|
}
|
|
3412
3335
|
|
|
3413
3336
|
size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel)
|
|
3414
3337
|
{
|
|
3415
|
-
ZSTD_compressionParameters const cParams =
|
|
3338
|
+
ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize);
|
|
3416
3339
|
return ZSTD_estimateCDictSize_advanced(dictSize, cParams, ZSTD_dlm_byCopy);
|
|
3417
3340
|
}
|
|
3418
3341
|
|
|
@@ -3420,7 +3343,9 @@ size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict)
|
|
|
3420
3343
|
{
|
|
3421
3344
|
if (cdict==NULL) return 0; /* support sizeof on NULL */
|
|
3422
3345
|
DEBUGLOG(5, "sizeof(*cdict) : %u", (unsigned)sizeof(*cdict));
|
|
3423
|
-
|
|
3346
|
+
/* cdict may be in the workspace */
|
|
3347
|
+
return (cdict->workspace.workspace == cdict ? 0 : sizeof(*cdict))
|
|
3348
|
+
+ ZSTD_cwksp_sizeof(&cdict->workspace);
|
|
3424
3349
|
}
|
|
3425
3350
|
|
|
3426
3351
|
static size_t ZSTD_initCDict_internal(
|
|
@@ -3434,28 +3359,29 @@ static size_t ZSTD_initCDict_internal(
|
|
|
3434
3359
|
assert(!ZSTD_checkCParams(cParams));
|
|
3435
3360
|
cdict->matchState.cParams = cParams;
|
|
3436
3361
|
if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dictBuffer) || (!dictSize)) {
|
|
3437
|
-
cdict->dictBuffer = NULL;
|
|
3438
3362
|
cdict->dictContent = dictBuffer;
|
|
3439
3363
|
} else {
|
|
3440
|
-
|
|
3441
|
-
|
|
3364
|
+
void *internalBuffer = ZSTD_cwksp_reserve_object(&cdict->workspace, ZSTD_cwksp_align(dictSize, sizeof(void*)));
|
|
3365
|
+
RETURN_ERROR_IF(!internalBuffer, memory_allocation, "NULL pointer!");
|
|
3442
3366
|
cdict->dictContent = internalBuffer;
|
|
3443
|
-
if (!internalBuffer) return ERROR(memory_allocation);
|
|
3444
3367
|
memcpy(internalBuffer, dictBuffer, dictSize);
|
|
3445
3368
|
}
|
|
3446
3369
|
cdict->dictContentSize = dictSize;
|
|
3447
3370
|
|
|
3371
|
+
cdict->entropyWorkspace = (U32*)ZSTD_cwksp_reserve_object(&cdict->workspace, HUF_WORKSPACE_SIZE);
|
|
3372
|
+
|
|
3373
|
+
|
|
3448
3374
|
/* Reset the state to no dictionary */
|
|
3449
3375
|
ZSTD_reset_compressedBlockState(&cdict->cBlockState);
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
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), "");
|
|
3457
3383
|
/* (Maybe) load the dictionary
|
|
3458
|
-
* Skips loading the dictionary if it is
|
|
3384
|
+
* Skips loading the dictionary if it is < 8 bytes.
|
|
3459
3385
|
*/
|
|
3460
3386
|
{ ZSTD_CCtx_params params;
|
|
3461
3387
|
memset(¶ms, 0, sizeof(params));
|
|
@@ -3463,10 +3389,10 @@ static size_t ZSTD_initCDict_internal(
|
|
|
3463
3389
|
params.fParams.contentSizeFlag = 1;
|
|
3464
3390
|
params.cParams = cParams;
|
|
3465
3391
|
{ size_t const dictID = ZSTD_compress_insertDictionary(
|
|
3466
|
-
&cdict->cBlockState, &cdict->matchState, &
|
|
3467
|
-
cdict->dictContent, cdict->dictContentSize,
|
|
3468
|
-
dictContentType, ZSTD_dtlm_full, cdict->
|
|
3469
|
-
|
|
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");
|
|
3470
3396
|
assert(dictID <= (size_t)(U32)-1);
|
|
3471
3397
|
cdict->dictID = (U32)dictID;
|
|
3472
3398
|
}
|
|
@@ -3483,18 +3409,29 @@ ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize,
|
|
|
3483
3409
|
DEBUGLOG(3, "ZSTD_createCDict_advanced, mode %u", (unsigned)dictContentType);
|
|
3484
3410
|
if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
|
|
3485
3411
|
|
|
3486
|
-
{
|
|
3487
|
-
|
|
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*))));
|
|
3488
3418
|
void* const workspace = ZSTD_malloc(workspaceSize, customMem);
|
|
3419
|
+
ZSTD_cwksp ws;
|
|
3420
|
+
ZSTD_CDict* cdict;
|
|
3489
3421
|
|
|
3490
|
-
if (!
|
|
3491
|
-
ZSTD_free(cdict, customMem);
|
|
3422
|
+
if (!workspace) {
|
|
3492
3423
|
ZSTD_free(workspace, customMem);
|
|
3493
3424
|
return NULL;
|
|
3494
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);
|
|
3495
3432
|
cdict->customMem = customMem;
|
|
3496
|
-
cdict->
|
|
3497
|
-
|
|
3433
|
+
cdict->compressionLevel = 0; /* signals advanced API usage */
|
|
3434
|
+
|
|
3498
3435
|
if (ZSTD_isError( ZSTD_initCDict_internal(cdict,
|
|
3499
3436
|
dictBuffer, dictSize,
|
|
3500
3437
|
dictLoadMethod, dictContentType,
|
|
@@ -3509,15 +3446,18 @@ ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize,
|
|
|
3509
3446
|
|
|
3510
3447
|
ZSTD_CDict* ZSTD_createCDict(const void* dict, size_t dictSize, int compressionLevel)
|
|
3511
3448
|
{
|
|
3512
|
-
ZSTD_compressionParameters cParams =
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
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;
|
|
3516
3456
|
}
|
|
3517
3457
|
|
|
3518
3458
|
ZSTD_CDict* ZSTD_createCDict_byReference(const void* dict, size_t dictSize, int compressionLevel)
|
|
3519
3459
|
{
|
|
3520
|
-
ZSTD_compressionParameters cParams =
|
|
3460
|
+
ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize);
|
|
3521
3461
|
return ZSTD_createCDict_advanced(dict, dictSize,
|
|
3522
3462
|
ZSTD_dlm_byRef, ZSTD_dct_auto,
|
|
3523
3463
|
cParams, ZSTD_defaultCMem);
|
|
@@ -3527,9 +3467,11 @@ size_t ZSTD_freeCDict(ZSTD_CDict* cdict)
|
|
|
3527
3467
|
{
|
|
3528
3468
|
if (cdict==NULL) return 0; /* support free on NULL */
|
|
3529
3469
|
{ ZSTD_customMem const cMem = cdict->customMem;
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
|
|
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
|
+
}
|
|
3533
3475
|
return 0;
|
|
3534
3476
|
}
|
|
3535
3477
|
}
|
|
@@ -3555,28 +3497,30 @@ const ZSTD_CDict* ZSTD_initStaticCDict(
|
|
|
3555
3497
|
ZSTD_compressionParameters cParams)
|
|
3556
3498
|
{
|
|
3557
3499
|
size_t const matchStateSize = ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 0);
|
|
3558
|
-
size_t const neededSize = sizeof(ZSTD_CDict)
|
|
3559
|
-
+
|
|
3560
|
-
|
|
3561
|
-
|
|
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
|
+
|
|
3562
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
|
+
|
|
3563
3517
|
DEBUGLOG(4, "(workspaceSize < neededSize) : (%u < %u) => %u",
|
|
3564
3518
|
(unsigned)workspaceSize, (unsigned)neededSize, (unsigned)(workspaceSize < neededSize));
|
|
3565
3519
|
if (workspaceSize < neededSize) return NULL;
|
|
3566
3520
|
|
|
3567
|
-
if (dictLoadMethod == ZSTD_dlm_byCopy) {
|
|
3568
|
-
memcpy(cdict+1, dict, dictSize);
|
|
3569
|
-
dict = cdict+1;
|
|
3570
|
-
ptr = (char*)workspace + sizeof(ZSTD_CDict) + dictSize;
|
|
3571
|
-
} else {
|
|
3572
|
-
ptr = cdict+1;
|
|
3573
|
-
}
|
|
3574
|
-
cdict->workspace = ptr;
|
|
3575
|
-
cdict->workspaceSize = HUF_WORKSPACE_SIZE + matchStateSize;
|
|
3576
|
-
|
|
3577
3521
|
if (ZSTD_isError( ZSTD_initCDict_internal(cdict,
|
|
3578
3522
|
dict, dictSize,
|
|
3579
|
-
|
|
3523
|
+
dictLoadMethod, dictContentType,
|
|
3580
3524
|
cParams) ))
|
|
3581
3525
|
return NULL;
|
|
3582
3526
|
|
|
@@ -3596,9 +3540,17 @@ size_t ZSTD_compressBegin_usingCDict_advanced(
|
|
|
3596
3540
|
ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize)
|
|
3597
3541
|
{
|
|
3598
3542
|
DEBUGLOG(4, "ZSTD_compressBegin_usingCDict_advanced");
|
|
3599
|
-
|
|
3543
|
+
RETURN_ERROR_IF(cdict==NULL, dictionary_wrong, "NULL pointer!");
|
|
3600
3544
|
{ ZSTD_CCtx_params params = cctx->requestedParams;
|
|
3601
|
-
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);
|
|
3602
3554
|
/* Increase window log to fit the entire dictionary and source if the
|
|
3603
3555
|
* source size is known. Limit the increase to 19, which is the
|
|
3604
3556
|
* window log for compression level 1 with the largest source size.
|
|
@@ -3612,7 +3564,7 @@ size_t ZSTD_compressBegin_usingCDict_advanced(
|
|
|
3612
3564
|
return ZSTD_compressBegin_internal(cctx,
|
|
3613
3565
|
NULL, 0, ZSTD_dct_auto, ZSTD_dtlm_fast,
|
|
3614
3566
|
cdict,
|
|
3615
|
-
params, pledgedSrcSize,
|
|
3567
|
+
¶ms, pledgedSrcSize,
|
|
3616
3568
|
ZSTDb_not_buffered);
|
|
3617
3569
|
}
|
|
3618
3570
|
}
|
|
@@ -3632,7 +3584,7 @@ size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx,
|
|
|
3632
3584
|
const void* src, size_t srcSize,
|
|
3633
3585
|
const ZSTD_CDict* cdict, ZSTD_frameParameters fParams)
|
|
3634
3586
|
{
|
|
3635
|
-
|
|
3587
|
+
FORWARD_IF_ERROR(ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, srcSize), ""); /* will check if cdict != NULL */
|
|
3636
3588
|
return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize);
|
|
3637
3589
|
}
|
|
3638
3590
|
|
|
@@ -3700,11 +3652,11 @@ static size_t ZSTD_resetCStream_internal(ZSTD_CStream* cctx,
|
|
|
3700
3652
|
assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
|
|
3701
3653
|
assert(!((dict) && (cdict))); /* either dict or cdict, not both */
|
|
3702
3654
|
|
|
3703
|
-
|
|
3655
|
+
FORWARD_IF_ERROR( ZSTD_compressBegin_internal(cctx,
|
|
3704
3656
|
dict, dictSize, dictContentType, ZSTD_dtlm_fast,
|
|
3705
3657
|
cdict,
|
|
3706
|
-
params, pledgedSrcSize,
|
|
3707
|
-
ZSTDb_buffered) );
|
|
3658
|
+
¶ms, pledgedSrcSize,
|
|
3659
|
+
ZSTDb_buffered) , "");
|
|
3708
3660
|
|
|
3709
3661
|
cctx->inToCompress = 0;
|
|
3710
3662
|
cctx->inBuffPos = 0;
|
|
@@ -3718,13 +3670,17 @@ static size_t ZSTD_resetCStream_internal(ZSTD_CStream* cctx,
|
|
|
3718
3670
|
|
|
3719
3671
|
/* ZSTD_resetCStream():
|
|
3720
3672
|
* pledgedSrcSize == 0 means "unknown" */
|
|
3721
|
-
size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long
|
|
3673
|
+
size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pss)
|
|
3722
3674
|
{
|
|
3723
|
-
|
|
3675
|
+
/* temporary : 0 interpreted as "unknown" during transition period.
|
|
3676
|
+
* Users willing to specify "unknown" **must** use ZSTD_CONTENTSIZE_UNKNOWN.
|
|
3677
|
+
* 0 will be interpreted as "empty" in the future.
|
|
3678
|
+
*/
|
|
3679
|
+
U64 const pledgedSrcSize = (pss==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss;
|
|
3724
3680
|
DEBUGLOG(4, "ZSTD_resetCStream: pledgedSrcSize = %u", (unsigned)pledgedSrcSize);
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
return
|
|
3681
|
+
FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
|
|
3682
|
+
FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , "");
|
|
3683
|
+
return 0;
|
|
3728
3684
|
}
|
|
3729
3685
|
|
|
3730
3686
|
/*! ZSTD_initCStream_internal() :
|
|
@@ -3733,35 +3689,22 @@ size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize)
|
|
|
3733
3689
|
* Assumption 2 : either dict, or cdict, is defined, not both */
|
|
3734
3690
|
size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
|
|
3735
3691
|
const void* dict, size_t dictSize, const ZSTD_CDict* cdict,
|
|
3736
|
-
ZSTD_CCtx_params params,
|
|
3692
|
+
const ZSTD_CCtx_params* params,
|
|
3693
|
+
unsigned long long pledgedSrcSize)
|
|
3737
3694
|
{
|
|
3738
3695
|
DEBUGLOG(4, "ZSTD_initCStream_internal");
|
|
3739
|
-
|
|
3740
|
-
|
|
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;
|
|
3741
3700
|
assert(!((dict) && (cdict))); /* either dict or cdict, not both */
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
DEBUGLOG(4, "loading dictionary of size %u", (unsigned)dictSize);
|
|
3745
|
-
if (zcs->staticSize) { /* static CCtx : never uses malloc */
|
|
3746
|
-
/* incompatible with internal cdict creation */
|
|
3747
|
-
return ERROR(memory_allocation);
|
|
3748
|
-
}
|
|
3749
|
-
ZSTD_freeCDict(zcs->cdictLocal);
|
|
3750
|
-
zcs->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize,
|
|
3751
|
-
ZSTD_dlm_byCopy, ZSTD_dct_auto,
|
|
3752
|
-
params.cParams, zcs->customMem);
|
|
3753
|
-
zcs->cdict = zcs->cdictLocal;
|
|
3754
|
-
if (zcs->cdictLocal == NULL) return ERROR(memory_allocation);
|
|
3701
|
+
if (dict) {
|
|
3702
|
+
FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) , "");
|
|
3755
3703
|
} else {
|
|
3756
|
-
if
|
|
3757
|
-
|
|
3758
|
-
}
|
|
3759
|
-
ZSTD_freeCDict(zcs->cdictLocal);
|
|
3760
|
-
zcs->cdictLocal = NULL;
|
|
3761
|
-
zcs->cdict = cdict;
|
|
3704
|
+
/* Dictionary is cleared if !cdict */
|
|
3705
|
+
FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) , "");
|
|
3762
3706
|
}
|
|
3763
|
-
|
|
3764
|
-
return ZSTD_resetCStream_internal(zcs, NULL, 0, ZSTD_dct_auto, zcs->cdict, params, pledgedSrcSize);
|
|
3707
|
+
return 0;
|
|
3765
3708
|
}
|
|
3766
3709
|
|
|
3767
3710
|
/* ZSTD_initCStream_usingCDict_advanced() :
|
|
@@ -3772,58 +3715,76 @@ size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs,
|
|
|
3772
3715
|
unsigned long long pledgedSrcSize)
|
|
3773
3716
|
{
|
|
3774
3717
|
DEBUGLOG(4, "ZSTD_initCStream_usingCDict_advanced");
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
NULL, 0, cdict,
|
|
3781
|
-
params, pledgedSrcSize);
|
|
3782
|
-
}
|
|
3718
|
+
FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
|
|
3719
|
+
FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , "");
|
|
3720
|
+
zcs->requestedParams.fParams = fParams;
|
|
3721
|
+
FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) , "");
|
|
3722
|
+
return 0;
|
|
3783
3723
|
}
|
|
3784
3724
|
|
|
3785
3725
|
/* note : cdict must outlive compression session */
|
|
3786
3726
|
size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict)
|
|
3787
3727
|
{
|
|
3788
|
-
ZSTD_frameParameters const fParams = { 0 /* contentSizeFlag */, 0 /* checksum */, 0 /* hideDictID */ };
|
|
3789
3728
|
DEBUGLOG(4, "ZSTD_initCStream_usingCDict");
|
|
3790
|
-
|
|
3729
|
+
FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
|
|
3730
|
+
FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) , "");
|
|
3731
|
+
return 0;
|
|
3791
3732
|
}
|
|
3792
3733
|
|
|
3793
3734
|
|
|
3794
3735
|
/* ZSTD_initCStream_advanced() :
|
|
3795
3736
|
* pledgedSrcSize must be exact.
|
|
3796
3737
|
* if srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN.
|
|
3797
|
-
* dict is loaded with default parameters
|
|
3738
|
+
* dict is loaded with default parameters ZSTD_dct_auto and ZSTD_dlm_byCopy. */
|
|
3798
3739
|
size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,
|
|
3799
3740
|
const void* dict, size_t dictSize,
|
|
3800
|
-
ZSTD_parameters params, unsigned long long
|
|
3741
|
+
ZSTD_parameters params, unsigned long long pss)
|
|
3801
3742
|
{
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3743
|
+
/* for compatibility with older programs relying on this behavior.
|
|
3744
|
+
* Users should now specify ZSTD_CONTENTSIZE_UNKNOWN.
|
|
3745
|
+
* This line will be removed in the future.
|
|
3746
|
+
*/
|
|
3747
|
+
U64 const pledgedSrcSize = (pss==0 && params.fParams.contentSizeFlag==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss;
|
|
3748
|
+
DEBUGLOG(4, "ZSTD_initCStream_advanced");
|
|
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) , "");
|
|
3754
|
+
return 0;
|
|
3808
3755
|
}
|
|
3809
3756
|
|
|
3810
3757
|
size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel)
|
|
3811
3758
|
{
|
|
3812
|
-
|
|
3813
|
-
|
|
3759
|
+
DEBUGLOG(4, "ZSTD_initCStream_usingDict");
|
|
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) , "");
|
|
3763
|
+
return 0;
|
|
3814
3764
|
}
|
|
3815
3765
|
|
|
3816
3766
|
size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pss)
|
|
3817
3767
|
{
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
|
|
3768
|
+
/* temporary : 0 interpreted as "unknown" during transition period.
|
|
3769
|
+
* Users willing to specify "unknown" **must** use ZSTD_CONTENTSIZE_UNKNOWN.
|
|
3770
|
+
* 0 will be interpreted as "empty" in the future.
|
|
3771
|
+
*/
|
|
3772
|
+
U64 const pledgedSrcSize = (pss==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss;
|
|
3773
|
+
DEBUGLOG(4, "ZSTD_initCStream_srcSize");
|
|
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) , "");
|
|
3778
|
+
return 0;
|
|
3821
3779
|
}
|
|
3822
3780
|
|
|
3823
3781
|
size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel)
|
|
3824
3782
|
{
|
|
3825
3783
|
DEBUGLOG(4, "ZSTD_initCStream");
|
|
3826
|
-
|
|
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) , "");
|
|
3787
|
+
return 0;
|
|
3827
3788
|
}
|
|
3828
3789
|
|
|
3829
3790
|
/*====== Compression ======*/
|
|
@@ -3835,29 +3796,21 @@ static size_t ZSTD_nextInputSizeHint(const ZSTD_CCtx* cctx)
|
|
|
3835
3796
|
return hintInSize;
|
|
3836
3797
|
}
|
|
3837
3798
|
|
|
3838
|
-
static size_t ZSTD_limitCopy(void* dst, size_t dstCapacity,
|
|
3839
|
-
const void* src, size_t srcSize)
|
|
3840
|
-
{
|
|
3841
|
-
size_t const length = MIN(dstCapacity, srcSize);
|
|
3842
|
-
if (length) memcpy(dst, src, length);
|
|
3843
|
-
return length;
|
|
3844
|
-
}
|
|
3845
|
-
|
|
3846
3799
|
/** ZSTD_compressStream_generic():
|
|
3847
3800
|
* internal function for all *compressStream*() variants
|
|
3848
3801
|
* non-static, because can be called from zstdmt_compress.c
|
|
3849
3802
|
* @return : hint size for next input */
|
|
3850
|
-
size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
|
|
3803
|
+
static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
|
|
3804
|
+
ZSTD_outBuffer* output,
|
|
3805
|
+
ZSTD_inBuffer* input,
|
|
3806
|
+
ZSTD_EndDirective const flushMode)
|
|
3854
3807
|
{
|
|
3855
3808
|
const char* const istart = (const char*)input->src;
|
|
3856
|
-
const char* const iend = istart + input->size;
|
|
3857
|
-
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;
|
|
3858
3811
|
char* const ostart = (char*)output->dst;
|
|
3859
|
-
char* const oend = ostart + output->size;
|
|
3860
|
-
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;
|
|
3861
3814
|
U32 someMoreWork = 1;
|
|
3862
3815
|
|
|
3863
3816
|
/* check expectations */
|
|
@@ -3873,8 +3826,7 @@ size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
|
|
|
3873
3826
|
switch(zcs->streamStage)
|
|
3874
3827
|
{
|
|
3875
3828
|
case zcss_init:
|
|
3876
|
-
|
|
3877
|
-
return ERROR(init_missing);
|
|
3829
|
+
RETURN_ERROR(init_missing, "call ZSTD_initCStream() first!");
|
|
3878
3830
|
|
|
3879
3831
|
case zcss_load:
|
|
3880
3832
|
if ( (flushMode == ZSTD_e_end)
|
|
@@ -3884,7 +3836,7 @@ size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
|
|
|
3884
3836
|
size_t const cSize = ZSTD_compressEnd(zcs,
|
|
3885
3837
|
op, oend-op, ip, iend-ip);
|
|
3886
3838
|
DEBUGLOG(4, "ZSTD_compressEnd : cSize=%u", (unsigned)cSize);
|
|
3887
|
-
|
|
3839
|
+
FORWARD_IF_ERROR(cSize, "ZSTD_compressEnd failed");
|
|
3888
3840
|
ip = iend;
|
|
3889
3841
|
op += cSize;
|
|
3890
3842
|
zcs->frameEnded = 1;
|
|
@@ -3897,7 +3849,8 @@ size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
|
|
|
3897
3849
|
zcs->inBuff + zcs->inBuffPos, toLoad,
|
|
3898
3850
|
ip, iend-ip);
|
|
3899
3851
|
zcs->inBuffPos += loaded;
|
|
3900
|
-
|
|
3852
|
+
if (loaded != 0)
|
|
3853
|
+
ip += loaded;
|
|
3901
3854
|
if ( (flushMode == ZSTD_e_continue)
|
|
3902
3855
|
&& (zcs->inBuffPos < zcs->inBuffTarget) ) {
|
|
3903
3856
|
/* not enough input to fill full block : stop here */
|
|
@@ -3925,7 +3878,7 @@ size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
|
|
|
3925
3878
|
zcs->inBuff + zcs->inToCompress, iSize) :
|
|
3926
3879
|
ZSTD_compressContinue(zcs, cDst, oSize,
|
|
3927
3880
|
zcs->inBuff + zcs->inToCompress, iSize);
|
|
3928
|
-
|
|
3881
|
+
FORWARD_IF_ERROR(cSize, "%s", lastBlock ? "ZSTD_compressEnd failed" : "ZSTD_compressContinue failed");
|
|
3929
3882
|
zcs->frameEnded = lastBlock;
|
|
3930
3883
|
/* prepare next block */
|
|
3931
3884
|
zcs->inBuffTarget = zcs->inBuffPos + zcs->blockSize;
|
|
@@ -3953,11 +3906,12 @@ size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
|
|
|
3953
3906
|
case zcss_flush:
|
|
3954
3907
|
DEBUGLOG(5, "flush stage");
|
|
3955
3908
|
{ size_t const toFlush = zcs->outBuffContentSize - zcs->outBuffFlushedSize;
|
|
3956
|
-
size_t const flushed = ZSTD_limitCopy(op, oend-op,
|
|
3909
|
+
size_t const flushed = ZSTD_limitCopy(op, (size_t)(oend-op),
|
|
3957
3910
|
zcs->outBuff + zcs->outBuffFlushedSize, toFlush);
|
|
3958
3911
|
DEBUGLOG(5, "toFlush: %u into %u ==> flushed: %u",
|
|
3959
3912
|
(unsigned)toFlush, (unsigned)(oend-op), (unsigned)flushed);
|
|
3960
|
-
|
|
3913
|
+
if (flushed)
|
|
3914
|
+
op += flushed;
|
|
3961
3915
|
zcs->outBuffFlushedSize += flushed;
|
|
3962
3916
|
if (toFlush!=flushed) {
|
|
3963
3917
|
/* flush not fully completed, presumably because dst is too small */
|
|
@@ -4001,7 +3955,7 @@ static size_t ZSTD_nextInputSizeHint_MTorST(const ZSTD_CCtx* cctx)
|
|
|
4001
3955
|
|
|
4002
3956
|
size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
|
|
4003
3957
|
{
|
|
4004
|
-
|
|
3958
|
+
FORWARD_IF_ERROR( ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue) , "");
|
|
4005
3959
|
return ZSTD_nextInputSizeHint_MTorST(zcs);
|
|
4006
3960
|
}
|
|
4007
3961
|
|
|
@@ -4013,14 +3967,15 @@ size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
|
|
|
4013
3967
|
{
|
|
4014
3968
|
DEBUGLOG(5, "ZSTD_compressStream2, endOp=%u ", (unsigned)endOp);
|
|
4015
3969
|
/* check conditions */
|
|
4016
|
-
|
|
4017
|
-
|
|
3970
|
+
RETURN_ERROR_IF(output->pos > output->size, GENERIC, "invalid buffer");
|
|
3971
|
+
RETURN_ERROR_IF(input->pos > input->size, GENERIC, "invalid buffer");
|
|
4018
3972
|
assert(cctx!=NULL);
|
|
4019
3973
|
|
|
4020
3974
|
/* transparent initialization stage */
|
|
4021
3975
|
if (cctx->streamStage == zcss_init) {
|
|
4022
3976
|
ZSTD_CCtx_params params = cctx->requestedParams;
|
|
4023
3977
|
ZSTD_prefixDict const prefixDict = cctx->prefixDict;
|
|
3978
|
+
FORWARD_IF_ERROR( ZSTD_initLocalDict(cctx) , ""); /* Init the local dict if present. */
|
|
4024
3979
|
memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); /* single usage */
|
|
4025
3980
|
assert(prefixDict.dict==NULL || cctx->cdict==NULL); /* only one can be set */
|
|
4026
3981
|
DEBUGLOG(4, "ZSTD_compressStream2 : transparent init stage");
|
|
@@ -4038,23 +3993,23 @@ size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
|
|
|
4038
3993
|
if (cctx->mtctx == NULL) {
|
|
4039
3994
|
DEBUGLOG(4, "ZSTD_compressStream2: creating new mtctx for nbWorkers=%u",
|
|
4040
3995
|
params.nbWorkers);
|
|
4041
|
-
cctx->mtctx = ZSTDMT_createCCtx_advanced(params.nbWorkers, cctx->customMem);
|
|
4042
|
-
|
|
3996
|
+
cctx->mtctx = ZSTDMT_createCCtx_advanced((U32)params.nbWorkers, cctx->customMem);
|
|
3997
|
+
RETURN_ERROR_IF(cctx->mtctx == NULL, memory_allocation, "NULL pointer!");
|
|
4043
3998
|
}
|
|
4044
3999
|
/* mt compression */
|
|
4045
4000
|
DEBUGLOG(4, "call ZSTDMT_initCStream_internal as nbWorkers=%u", params.nbWorkers);
|
|
4046
|
-
|
|
4001
|
+
FORWARD_IF_ERROR( ZSTDMT_initCStream_internal(
|
|
4047
4002
|
cctx->mtctx,
|
|
4048
|
-
prefixDict.dict, prefixDict.dictSize,
|
|
4049
|
-
cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) );
|
|
4003
|
+
prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType,
|
|
4004
|
+
cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) , "");
|
|
4050
4005
|
cctx->streamStage = zcss_load;
|
|
4051
4006
|
cctx->appliedParams.nbWorkers = params.nbWorkers;
|
|
4052
4007
|
} else
|
|
4053
4008
|
#endif
|
|
4054
|
-
{
|
|
4009
|
+
{ FORWARD_IF_ERROR( ZSTD_resetCStream_internal(cctx,
|
|
4055
4010
|
prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType,
|
|
4056
4011
|
cctx->cdict,
|
|
4057
|
-
params, cctx->pledgedSrcSizePlusOne-1) );
|
|
4012
|
+
params, cctx->pledgedSrcSizePlusOne-1) , "");
|
|
4058
4013
|
assert(cctx->streamStage == zcss_load);
|
|
4059
4014
|
assert(cctx->appliedParams.nbWorkers == 0);
|
|
4060
4015
|
} }
|
|
@@ -4063,20 +4018,30 @@ size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
|
|
|
4063
4018
|
/* compression stage */
|
|
4064
4019
|
#ifdef ZSTD_MULTITHREAD
|
|
4065
4020
|
if (cctx->appliedParams.nbWorkers > 0) {
|
|
4021
|
+
int const forceMaxProgress = (endOp == ZSTD_e_flush || endOp == ZSTD_e_end);
|
|
4022
|
+
size_t flushMin;
|
|
4023
|
+
assert(forceMaxProgress || endOp == ZSTD_e_continue /* Protection for a new flush type */);
|
|
4066
4024
|
if (cctx->cParamsChanged) {
|
|
4067
4025
|
ZSTDMT_updateCParams_whileCompressing(cctx->mtctx, &cctx->requestedParams);
|
|
4068
4026
|
cctx->cParamsChanged = 0;
|
|
4069
4027
|
}
|
|
4070
|
-
{
|
|
4028
|
+
do {
|
|
4029
|
+
flushMin = ZSTDMT_compressStream_generic(cctx->mtctx, output, input, endOp);
|
|
4071
4030
|
if ( ZSTD_isError(flushMin)
|
|
4072
4031
|
|| (endOp == ZSTD_e_end && flushMin == 0) ) { /* compression completed */
|
|
4073
4032
|
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);
|
|
4074
4033
|
}
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
|
|
4034
|
+
FORWARD_IF_ERROR(flushMin, "ZSTDMT_compressStream_generic failed");
|
|
4035
|
+
} while (forceMaxProgress && flushMin != 0 && output->pos < output->size);
|
|
4036
|
+
DEBUGLOG(5, "completed ZSTD_compressStream2 delegating to ZSTDMT_compressStream_generic");
|
|
4037
|
+
/* Either we don't require maximum forward progress, we've finished the
|
|
4038
|
+
* flush, or we are out of output space.
|
|
4039
|
+
*/
|
|
4040
|
+
assert(!forceMaxProgress || flushMin == 0 || output->pos == output->size);
|
|
4041
|
+
return flushMin;
|
|
4042
|
+
}
|
|
4078
4043
|
#endif
|
|
4079
|
-
|
|
4044
|
+
FORWARD_IF_ERROR( ZSTD_compressStream_generic(cctx, output, input, endOp) , "");
|
|
4080
4045
|
DEBUGLOG(5, "completed ZSTD_compressStream2");
|
|
4081
4046
|
return cctx->outBuffContentSize - cctx->outBuffFlushedSize; /* remaining to flush */
|
|
4082
4047
|
}
|
|
@@ -4100,6 +4065,7 @@ size_t ZSTD_compress2(ZSTD_CCtx* cctx,
|
|
|
4100
4065
|
void* dst, size_t dstCapacity,
|
|
4101
4066
|
const void* src, size_t srcSize)
|
|
4102
4067
|
{
|
|
4068
|
+
DEBUGLOG(4, "ZSTD_compress2 (srcSize=%u)", (unsigned)srcSize);
|
|
4103
4069
|
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);
|
|
4104
4070
|
{ size_t oPos = 0;
|
|
4105
4071
|
size_t iPos = 0;
|
|
@@ -4107,10 +4073,10 @@ size_t ZSTD_compress2(ZSTD_CCtx* cctx,
|
|
|
4107
4073
|
dst, dstCapacity, &oPos,
|
|
4108
4074
|
src, srcSize, &iPos,
|
|
4109
4075
|
ZSTD_e_end);
|
|
4110
|
-
|
|
4076
|
+
FORWARD_IF_ERROR(result, "ZSTD_compressStream2_simpleArgs failed");
|
|
4111
4077
|
if (result != 0) { /* compression not completed, due to lack of output space */
|
|
4112
4078
|
assert(oPos == dstCapacity);
|
|
4113
|
-
|
|
4079
|
+
RETURN_ERROR(dstSize_tooSmall, "");
|
|
4114
4080
|
}
|
|
4115
4081
|
assert(iPos == srcSize); /* all input is expected consumed */
|
|
4116
4082
|
return oPos;
|
|
@@ -4132,11 +4098,11 @@ size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output)
|
|
|
4132
4098
|
{
|
|
4133
4099
|
ZSTD_inBuffer input = { NULL, 0, 0 };
|
|
4134
4100
|
size_t const remainingToFlush = ZSTD_compressStream2(zcs, output, &input, ZSTD_e_end);
|
|
4135
|
-
|
|
4101
|
+
FORWARD_IF_ERROR( remainingToFlush , "ZSTD_compressStream2 failed");
|
|
4136
4102
|
if (zcs->appliedParams.nbWorkers > 0) return remainingToFlush; /* minimal estimation */
|
|
4137
4103
|
/* single thread mode : attempt to calculate remaining to flush more precisely */
|
|
4138
4104
|
{ size_t const lastBlockSize = zcs->frameEnded ? 0 : ZSTD_BLOCKHEADERSIZE;
|
|
4139
|
-
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);
|
|
4140
4106
|
size_t const toFlush = remainingToFlush + lastBlockSize + checksumSize;
|
|
4141
4107
|
DEBUGLOG(4, "ZSTD_endStream : remaining to flush : %u", (unsigned)toFlush);
|
|
4142
4108
|
return toFlush;
|
|
@@ -4151,13 +4117,13 @@ int ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; }
|
|
|
4151
4117
|
int ZSTD_minCLevel(void) { return (int)-ZSTD_TARGETLENGTH_MAX; }
|
|
4152
4118
|
|
|
4153
4119
|
static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = {
|
|
4154
|
-
{ /* "default" -
|
|
4120
|
+
{ /* "default" - for any srcSize > 256 KB */
|
|
4155
4121
|
/* W, C, H, S, L, TL, strat */
|
|
4156
4122
|
{ 19, 12, 13, 1, 6, 1, ZSTD_fast }, /* base for negative levels */
|
|
4157
4123
|
{ 19, 13, 14, 1, 7, 0, ZSTD_fast }, /* level 1 */
|
|
4158
4124
|
{ 20, 15, 16, 1, 6, 0, ZSTD_fast }, /* level 2 */
|
|
4159
|
-
{ 21, 16, 17, 1, 5,
|
|
4160
|
-
{ 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 */
|
|
4161
4127
|
{ 21, 18, 19, 2, 5, 2, ZSTD_greedy }, /* level 5 */
|
|
4162
4128
|
{ 21, 19, 19, 3, 5, 4, ZSTD_greedy }, /* level 6 */
|
|
4163
4129
|
{ 21, 19, 19, 3, 5, 8, ZSTD_lazy }, /* level 7 */
|
|
@@ -4181,8 +4147,8 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
|
|
|
4181
4147
|
/* W, C, H, S, L, T, strat */
|
|
4182
4148
|
{ 18, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */
|
|
4183
4149
|
{ 18, 13, 14, 1, 6, 0, ZSTD_fast }, /* level 1 */
|
|
4184
|
-
{ 18, 14, 14, 1, 5,
|
|
4185
|
-
{ 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 */
|
|
4186
4152
|
{ 18, 16, 17, 2, 5, 2, ZSTD_greedy }, /* level 4.*/
|
|
4187
4153
|
{ 18, 18, 18, 3, 5, 2, ZSTD_greedy }, /* level 5.*/
|
|
4188
4154
|
{ 18, 18, 19, 3, 5, 4, ZSTD_lazy }, /* level 6.*/
|
|
@@ -4208,8 +4174,8 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
|
|
|
4208
4174
|
{ 17, 12, 12, 1, 5, 1, ZSTD_fast }, /* base for negative levels */
|
|
4209
4175
|
{ 17, 12, 13, 1, 6, 0, ZSTD_fast }, /* level 1 */
|
|
4210
4176
|
{ 17, 13, 15, 1, 5, 0, ZSTD_fast }, /* level 2 */
|
|
4211
|
-
{ 17, 15, 16, 2, 5,
|
|
4212
|
-
{ 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 */
|
|
4213
4179
|
{ 17, 16, 17, 3, 4, 2, ZSTD_greedy }, /* level 5 */
|
|
4214
4180
|
{ 17, 17, 17, 3, 4, 4, ZSTD_lazy }, /* level 6 */
|
|
4215
4181
|
{ 17, 17, 17, 3, 4, 8, ZSTD_lazy2 }, /* level 7 */
|
|
@@ -4234,7 +4200,7 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
|
|
|
4234
4200
|
{ 14, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */
|
|
4235
4201
|
{ 14, 14, 15, 1, 5, 0, ZSTD_fast }, /* level 1 */
|
|
4236
4202
|
{ 14, 14, 15, 1, 4, 0, ZSTD_fast }, /* level 2 */
|
|
4237
|
-
{ 14, 14, 15, 2, 4,
|
|
4203
|
+
{ 14, 14, 15, 2, 4, 0, ZSTD_dfast }, /* level 3 */
|
|
4238
4204
|
{ 14, 14, 14, 4, 4, 2, ZSTD_greedy }, /* level 4 */
|
|
4239
4205
|
{ 14, 14, 14, 3, 4, 4, ZSTD_lazy }, /* level 5.*/
|
|
4240
4206
|
{ 14, 14, 14, 4, 4, 8, ZSTD_lazy2 }, /* level 6 */
|
|
@@ -4257,34 +4223,56 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
|
|
|
4257
4223
|
},
|
|
4258
4224
|
};
|
|
4259
4225
|
|
|
4260
|
-
/*!
|
|
4261
|
-
*
|
|
4262
|
-
*
|
|
4263
|
-
|
|
4226
|
+
/*! ZSTD_getCParams_internal() :
|
|
4227
|
+
* @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize.
|
|
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)
|
|
4264
4231
|
{
|
|
4265
|
-
|
|
4266
|
-
|
|
4267
|
-
|
|
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;
|
|
4235
|
+
U32 const tableID = (rSize <= 256 KB) + (rSize <= 128 KB) + (rSize <= 16 KB);
|
|
4268
4236
|
int row = compressionLevel;
|
|
4269
|
-
DEBUGLOG(5, "
|
|
4237
|
+
DEBUGLOG(5, "ZSTD_getCParams_internal (cLevel=%i)", compressionLevel);
|
|
4270
4238
|
if (compressionLevel == 0) row = ZSTD_CLEVEL_DEFAULT; /* 0 == default */
|
|
4271
4239
|
if (compressionLevel < 0) row = 0; /* entry 0 is baseline for fast mode */
|
|
4272
4240
|
if (compressionLevel > ZSTD_MAX_CLEVEL) row = ZSTD_MAX_CLEVEL;
|
|
4273
4241
|
{ ZSTD_compressionParameters cp = ZSTD_defaultCParameters[tableID][row];
|
|
4274
4242
|
if (compressionLevel < 0) cp.targetLength = (unsigned)(-compressionLevel); /* acceleration factor */
|
|
4243
|
+
/* refine parameters based on srcSize & dictSize */
|
|
4275
4244
|
return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize);
|
|
4276
4245
|
}
|
|
4277
4246
|
}
|
|
4278
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
|
+
|
|
4279
4257
|
/*! ZSTD_getParams() :
|
|
4280
|
-
*
|
|
4281
|
-
*
|
|
4282
|
-
|
|
4258
|
+
* same idea as ZSTD_getCParams()
|
|
4259
|
+
* @return a `ZSTD_parameters` structure (instead of `ZSTD_compressionParameters`).
|
|
4260
|
+
* Fields of `ZSTD_frameParameters` are set to default values */
|
|
4261
|
+
static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) {
|
|
4283
4262
|
ZSTD_parameters params;
|
|
4284
|
-
ZSTD_compressionParameters const cParams =
|
|
4263
|
+
ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize);
|
|
4285
4264
|
DEBUGLOG(5, "ZSTD_getParams (cLevel=%i)", compressionLevel);
|
|
4286
4265
|
memset(¶ms, 0, sizeof(params));
|
|
4287
4266
|
params.cParams = cParams;
|
|
4288
4267
|
params.fParams.contentSizeFlag = 1;
|
|
4289
4268
|
return params;
|
|
4290
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
|
+
}
|