extzstd 0.1.1 → 0.2
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 +5 -5
- data/HISTORY.ja.md +18 -0
- data/README.md +15 -50
- data/contrib/zstd/CONTRIBUTING.md +1 -1
- data/contrib/zstd/COPYING +339 -0
- data/contrib/zstd/Makefile +82 -51
- data/contrib/zstd/NEWS +92 -5
- data/contrib/zstd/README.md +50 -41
- data/contrib/zstd/appveyor.yml +164 -102
- data/contrib/zstd/circle.yml +10 -22
- data/contrib/zstd/lib/BUCK +31 -10
- data/contrib/zstd/lib/Makefile +57 -31
- data/contrib/zstd/lib/README.md +68 -37
- data/contrib/zstd/lib/common/bitstream.h +130 -76
- data/contrib/zstd/lib/common/compiler.h +86 -0
- data/contrib/zstd/lib/common/error_private.c +15 -11
- data/contrib/zstd/lib/common/error_private.h +8 -8
- data/contrib/zstd/lib/common/fse.h +19 -9
- data/contrib/zstd/lib/common/fse_decompress.c +3 -22
- data/contrib/zstd/lib/common/huf.h +68 -26
- data/contrib/zstd/lib/common/mem.h +23 -35
- data/contrib/zstd/lib/common/pool.c +123 -63
- data/contrib/zstd/lib/common/pool.h +19 -10
- data/contrib/zstd/lib/common/threading.c +11 -16
- data/contrib/zstd/lib/common/threading.h +52 -33
- data/contrib/zstd/lib/common/xxhash.c +28 -22
- data/contrib/zstd/lib/common/zstd_common.c +40 -27
- data/contrib/zstd/lib/common/zstd_errors.h +43 -34
- data/contrib/zstd/lib/common/zstd_internal.h +131 -123
- data/contrib/zstd/lib/compress/fse_compress.c +17 -33
- data/contrib/zstd/lib/compress/huf_compress.c +15 -9
- data/contrib/zstd/lib/compress/zstd_compress.c +2096 -2363
- data/contrib/zstd/lib/compress/zstd_compress_internal.h +462 -0
- data/contrib/zstd/lib/compress/zstd_double_fast.c +309 -0
- data/contrib/zstd/lib/compress/zstd_double_fast.h +29 -0
- data/contrib/zstd/lib/compress/zstd_fast.c +243 -0
- data/contrib/zstd/lib/compress/zstd_fast.h +31 -0
- data/contrib/zstd/lib/compress/zstd_lazy.c +765 -0
- data/contrib/zstd/lib/compress/zstd_lazy.h +39 -0
- data/contrib/zstd/lib/compress/zstd_ldm.c +707 -0
- data/contrib/zstd/lib/compress/zstd_ldm.h +68 -0
- data/contrib/zstd/lib/compress/zstd_opt.c +785 -0
- data/contrib/zstd/lib/compress/zstd_opt.h +19 -908
- data/contrib/zstd/lib/compress/zstdmt_compress.c +737 -327
- data/contrib/zstd/lib/compress/zstdmt_compress.h +88 -26
- data/contrib/zstd/lib/decompress/huf_decompress.c +158 -50
- data/contrib/zstd/lib/decompress/zstd_decompress.c +884 -699
- data/contrib/zstd/lib/deprecated/zbuff.h +5 -4
- data/contrib/zstd/lib/deprecated/zbuff_common.c +5 -5
- data/contrib/zstd/lib/deprecated/zbuff_compress.c +6 -4
- data/contrib/zstd/lib/deprecated/zbuff_decompress.c +5 -4
- data/contrib/zstd/lib/dictBuilder/cover.c +93 -77
- data/contrib/zstd/lib/dictBuilder/zdict.c +107 -92
- data/contrib/zstd/lib/dictBuilder/zdict.h +112 -102
- data/contrib/zstd/lib/legacy/zstd_legacy.h +9 -4
- data/contrib/zstd/lib/legacy/zstd_v01.c +7 -6
- data/contrib/zstd/lib/legacy/zstd_v01.h +5 -4
- data/contrib/zstd/lib/legacy/zstd_v02.c +27 -99
- data/contrib/zstd/lib/legacy/zstd_v02.h +5 -4
- data/contrib/zstd/lib/legacy/zstd_v03.c +26 -98
- data/contrib/zstd/lib/legacy/zstd_v03.h +5 -4
- data/contrib/zstd/lib/legacy/zstd_v04.c +22 -91
- data/contrib/zstd/lib/legacy/zstd_v04.h +5 -4
- data/contrib/zstd/lib/legacy/zstd_v05.c +23 -99
- data/contrib/zstd/lib/legacy/zstd_v05.h +5 -4
- data/contrib/zstd/lib/legacy/zstd_v06.c +22 -96
- data/contrib/zstd/lib/legacy/zstd_v06.h +5 -4
- data/contrib/zstd/lib/legacy/zstd_v07.c +19 -95
- data/contrib/zstd/lib/legacy/zstd_v07.h +5 -4
- data/contrib/zstd/lib/zstd.h +895 -271
- data/ext/extconf.rb +11 -2
- data/ext/extzstd.c +45 -128
- data/ext/extzstd.h +74 -31
- data/ext/extzstd_stream.c +401 -142
- data/ext/zstd_common.c +5 -0
- data/ext/zstd_compress.c +8 -0
- data/ext/zstd_decompress.c +1 -0
- data/ext/zstd_dictbuilder.c +2 -0
- data/lib/extzstd/version.rb +1 -1
- data/lib/extzstd.rb +48 -1
- data/test/test_basic.rb +9 -1
- metadata +17 -7
- data/HISTORY.ja +0 -10
- data/contrib/zstd/LICENSE-examples +0 -11
- data/contrib/zstd/PATENTS +0 -33
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
/*
|
|
2
2
|
* Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
|
|
3
3
|
* All rights reserved.
|
|
4
4
|
*
|
|
5
|
-
* This source code is licensed under the BSD-style license found in the
|
|
6
|
-
* LICENSE file in the root directory of this source tree
|
|
7
|
-
*
|
|
5
|
+
* This source code is licensed under both the BSD-style license (found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
|
7
|
+
* in the COPYING file in the root directory of this source tree).
|
|
8
|
+
* You may select, at your option, one of the above-listed licenses.
|
|
8
9
|
*/
|
|
9
10
|
|
|
10
11
|
|
|
@@ -34,7 +35,7 @@
|
|
|
34
35
|
* Frames requiring more memory will be rejected.
|
|
35
36
|
*/
|
|
36
37
|
#ifndef ZSTD_MAXWINDOWSIZE_DEFAULT
|
|
37
|
-
# define ZSTD_MAXWINDOWSIZE_DEFAULT ((1 <<
|
|
38
|
+
# define ZSTD_MAXWINDOWSIZE_DEFAULT (((U32)1 << ZSTD_WINDOWLOG_DEFAULTMAX) + 1)
|
|
38
39
|
#endif
|
|
39
40
|
|
|
40
41
|
|
|
@@ -54,17 +55,8 @@
|
|
|
54
55
|
#endif
|
|
55
56
|
|
|
56
57
|
|
|
57
|
-
#if defined(_MSC_VER)
|
|
58
|
-
# include <mmintrin.h> /* https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx */
|
|
59
|
-
# define ZSTD_PREFETCH(ptr) _mm_prefetch((const char*)ptr, _MM_HINT_T0)
|
|
60
|
-
#elif defined(__GNUC__)
|
|
61
|
-
# define ZSTD_PREFETCH(ptr) __builtin_prefetch(ptr, 0, 0)
|
|
62
|
-
#else
|
|
63
|
-
# define ZSTD_PREFETCH(ptr) /* disabled */
|
|
64
|
-
#endif
|
|
65
|
-
|
|
66
58
|
/*-*************************************
|
|
67
|
-
*
|
|
59
|
+
* Errors
|
|
68
60
|
***************************************/
|
|
69
61
|
#define ZSTD_isError ERR_isError /* for inlining */
|
|
70
62
|
#define FSE_isError ERR_isError
|
|
@@ -85,13 +77,17 @@ typedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader,
|
|
|
85
77
|
ZSTDds_decompressLastBlock, ZSTDds_checkChecksum,
|
|
86
78
|
ZSTDds_decodeSkippableHeader, ZSTDds_skipFrame } ZSTD_dStage;
|
|
87
79
|
|
|
80
|
+
typedef enum { zdss_init=0, zdss_loadHeader,
|
|
81
|
+
zdss_read, zdss_load, zdss_flush } ZSTD_dStreamStage;
|
|
82
|
+
|
|
88
83
|
typedef struct {
|
|
89
84
|
FSE_DTable LLTable[FSE_DTABLE_SIZE_U32(LLFSELog)];
|
|
90
85
|
FSE_DTable OFTable[FSE_DTABLE_SIZE_U32(OffFSELog)];
|
|
91
86
|
FSE_DTable MLTable[FSE_DTABLE_SIZE_U32(MLFSELog)];
|
|
92
87
|
HUF_DTable hufTable[HUF_DTABLE_SIZE(HufLog)]; /* can accommodate HUF_decompress4X */
|
|
88
|
+
U32 workspace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
|
|
93
89
|
U32 rep[ZSTD_REP_NUM];
|
|
94
|
-
}
|
|
90
|
+
} ZSTD_entropyDTables_t;
|
|
95
91
|
|
|
96
92
|
struct ZSTD_DCtx_s
|
|
97
93
|
{
|
|
@@ -99,109 +95,142 @@ struct ZSTD_DCtx_s
|
|
|
99
95
|
const FSE_DTable* MLTptr;
|
|
100
96
|
const FSE_DTable* OFTptr;
|
|
101
97
|
const HUF_DTable* HUFptr;
|
|
102
|
-
|
|
98
|
+
ZSTD_entropyDTables_t entropy;
|
|
103
99
|
const void* previousDstEnd; /* detect continuity */
|
|
104
100
|
const void* base; /* start of current segment */
|
|
105
101
|
const void* vBase; /* virtual start of previous segment if it was just before current one */
|
|
106
102
|
const void* dictEnd; /* end of previous segment */
|
|
107
103
|
size_t expected;
|
|
108
|
-
|
|
109
|
-
|
|
104
|
+
ZSTD_frameHeader fParams;
|
|
105
|
+
U64 decodedSize;
|
|
106
|
+
blockType_e bType; /* used in ZSTD_decompressContinue(), store blockType between block header decoding and block decompression stages */
|
|
110
107
|
ZSTD_dStage stage;
|
|
111
108
|
U32 litEntropy;
|
|
112
109
|
U32 fseEntropy;
|
|
113
110
|
XXH64_state_t xxhState;
|
|
114
111
|
size_t headerSize;
|
|
115
112
|
U32 dictID;
|
|
113
|
+
ZSTD_format_e format;
|
|
116
114
|
const BYTE* litPtr;
|
|
117
115
|
ZSTD_customMem customMem;
|
|
118
116
|
size_t litSize;
|
|
119
117
|
size_t rleSize;
|
|
120
|
-
|
|
118
|
+
size_t staticSize;
|
|
119
|
+
|
|
120
|
+
/* streaming */
|
|
121
|
+
ZSTD_DDict* ddictLocal;
|
|
122
|
+
const ZSTD_DDict* ddict;
|
|
123
|
+
ZSTD_dStreamStage streamStage;
|
|
124
|
+
char* inBuff;
|
|
125
|
+
size_t inBuffSize;
|
|
126
|
+
size_t inPos;
|
|
127
|
+
size_t maxWindowSize;
|
|
128
|
+
char* outBuff;
|
|
129
|
+
size_t outBuffSize;
|
|
130
|
+
size_t outStart;
|
|
131
|
+
size_t outEnd;
|
|
132
|
+
size_t lhSize;
|
|
133
|
+
void* legacyContext;
|
|
134
|
+
U32 previousLegacyVersion;
|
|
135
|
+
U32 legacyVersion;
|
|
136
|
+
U32 hostageByte;
|
|
137
|
+
|
|
138
|
+
/* workspace */
|
|
139
|
+
BYTE litBuffer[ZSTD_BLOCKSIZE_MAX + WILDCOPY_OVERLENGTH];
|
|
121
140
|
BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX];
|
|
122
141
|
}; /* typedef'd to ZSTD_DCtx within "zstd.h" */
|
|
123
142
|
|
|
124
|
-
size_t ZSTD_sizeof_DCtx (const ZSTD_DCtx* dctx)
|
|
143
|
+
size_t ZSTD_sizeof_DCtx (const ZSTD_DCtx* dctx)
|
|
144
|
+
{
|
|
145
|
+
if (dctx==NULL) return 0; /* support sizeof NULL */
|
|
146
|
+
return sizeof(*dctx)
|
|
147
|
+
+ ZSTD_sizeof_DDict(dctx->ddictLocal)
|
|
148
|
+
+ dctx->inBuffSize + dctx->outBuffSize;
|
|
149
|
+
}
|
|
125
150
|
|
|
126
151
|
size_t ZSTD_estimateDCtxSize(void) { return sizeof(ZSTD_DCtx); }
|
|
127
152
|
|
|
128
|
-
|
|
153
|
+
|
|
154
|
+
static size_t ZSTD_startingInputLength(ZSTD_format_e format)
|
|
129
155
|
{
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
dctx->litEntropy = dctx->fseEntropy = 0;
|
|
138
|
-
dctx->dictID = 0;
|
|
139
|
-
MEM_STATIC_ASSERT(sizeof(dctx->entropy.rep) == sizeof(repStartValue));
|
|
140
|
-
memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */
|
|
141
|
-
dctx->LLTptr = dctx->entropy.LLTable;
|
|
142
|
-
dctx->MLTptr = dctx->entropy.MLTable;
|
|
143
|
-
dctx->OFTptr = dctx->entropy.OFTable;
|
|
144
|
-
dctx->HUFptr = dctx->entropy.hufTable;
|
|
145
|
-
return 0;
|
|
156
|
+
size_t const startingInputLength = (format==ZSTD_f_zstd1_magicless) ?
|
|
157
|
+
ZSTD_frameHeaderSize_prefix - ZSTD_frameIdSize :
|
|
158
|
+
ZSTD_frameHeaderSize_prefix;
|
|
159
|
+
ZSTD_STATIC_ASSERT(ZSTD_FRAMEHEADERSIZE_PREFIX >= ZSTD_FRAMEIDSIZE);
|
|
160
|
+
/* only supports formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless */
|
|
161
|
+
assert( (format == ZSTD_f_zstd1) || (format == ZSTD_f_zstd1_magicless) );
|
|
162
|
+
return startingInputLength;
|
|
146
163
|
}
|
|
147
164
|
|
|
148
|
-
ZSTD_DCtx*
|
|
165
|
+
static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
|
|
166
|
+
{
|
|
167
|
+
dctx->format = ZSTD_f_zstd1; /* ZSTD_decompressBegin() invokes ZSTD_startingInputLength() with argument dctx->format */
|
|
168
|
+
dctx->staticSize = 0;
|
|
169
|
+
dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
|
|
170
|
+
dctx->ddict = NULL;
|
|
171
|
+
dctx->ddictLocal = NULL;
|
|
172
|
+
dctx->inBuff = NULL;
|
|
173
|
+
dctx->inBuffSize = 0;
|
|
174
|
+
dctx->outBuffSize = 0;
|
|
175
|
+
dctx->streamStage = zdss_init;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
|
|
149
179
|
{
|
|
150
|
-
ZSTD_DCtx* dctx;
|
|
180
|
+
ZSTD_DCtx* const dctx = (ZSTD_DCtx*) workspace;
|
|
151
181
|
|
|
152
|
-
if (
|
|
153
|
-
if (
|
|
182
|
+
if ((size_t)workspace & 7) return NULL; /* 8-aligned */
|
|
183
|
+
if (workspaceSize < sizeof(ZSTD_DCtx)) return NULL; /* minimum size */
|
|
154
184
|
|
|
155
|
-
dctx
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
ZSTD_decompressBegin(dctx);
|
|
185
|
+
ZSTD_initDCtx_internal(dctx);
|
|
186
|
+
dctx->staticSize = workspaceSize;
|
|
187
|
+
dctx->inBuff = (char*)(dctx+1);
|
|
159
188
|
return dctx;
|
|
160
189
|
}
|
|
161
190
|
|
|
191
|
+
ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
|
|
192
|
+
{
|
|
193
|
+
if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
|
|
194
|
+
|
|
195
|
+
{ ZSTD_DCtx* const dctx = (ZSTD_DCtx*)ZSTD_malloc(sizeof(*dctx), customMem);
|
|
196
|
+
if (!dctx) return NULL;
|
|
197
|
+
dctx->customMem = customMem;
|
|
198
|
+
dctx->legacyContext = NULL;
|
|
199
|
+
dctx->previousLegacyVersion = 0;
|
|
200
|
+
ZSTD_initDCtx_internal(dctx);
|
|
201
|
+
return dctx;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
162
205
|
ZSTD_DCtx* ZSTD_createDCtx(void)
|
|
163
206
|
{
|
|
164
|
-
return ZSTD_createDCtx_advanced(
|
|
207
|
+
return ZSTD_createDCtx_advanced(ZSTD_defaultCMem);
|
|
165
208
|
}
|
|
166
209
|
|
|
167
210
|
size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
|
|
168
211
|
{
|
|
169
212
|
if (dctx==NULL) return 0; /* support free on NULL */
|
|
170
|
-
|
|
171
|
-
|
|
213
|
+
if (dctx->staticSize) return ERROR(memory_allocation); /* not compatible with static DCtx */
|
|
214
|
+
{ ZSTD_customMem const cMem = dctx->customMem;
|
|
215
|
+
ZSTD_freeDDict(dctx->ddictLocal);
|
|
216
|
+
dctx->ddictLocal = NULL;
|
|
217
|
+
ZSTD_free(dctx->inBuff, cMem);
|
|
218
|
+
dctx->inBuff = NULL;
|
|
219
|
+
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
|
|
220
|
+
if (dctx->legacyContext)
|
|
221
|
+
ZSTD_freeLegacyStreamContext(dctx->legacyContext, dctx->previousLegacyVersion);
|
|
222
|
+
#endif
|
|
223
|
+
ZSTD_free(dctx, cMem);
|
|
224
|
+
return 0;
|
|
225
|
+
}
|
|
172
226
|
}
|
|
173
227
|
|
|
228
|
+
/* no longer useful */
|
|
174
229
|
void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
|
|
175
230
|
{
|
|
176
|
-
size_t const
|
|
177
|
-
memcpy(dstDCtx, srcDCtx,
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
#if 0
|
|
181
|
-
/* deprecated */
|
|
182
|
-
static void ZSTD_refDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
|
|
183
|
-
{
|
|
184
|
-
ZSTD_decompressBegin(dstDCtx); /* init */
|
|
185
|
-
if (srcDCtx) { /* support refDCtx on NULL */
|
|
186
|
-
dstDCtx->dictEnd = srcDCtx->dictEnd;
|
|
187
|
-
dstDCtx->vBase = srcDCtx->vBase;
|
|
188
|
-
dstDCtx->base = srcDCtx->base;
|
|
189
|
-
dstDCtx->previousDstEnd = srcDCtx->previousDstEnd;
|
|
190
|
-
dstDCtx->dictID = srcDCtx->dictID;
|
|
191
|
-
dstDCtx->litEntropy = srcDCtx->litEntropy;
|
|
192
|
-
dstDCtx->fseEntropy = srcDCtx->fseEntropy;
|
|
193
|
-
dstDCtx->LLTptr = srcDCtx->entropy.LLTable;
|
|
194
|
-
dstDCtx->MLTptr = srcDCtx->entropy.MLTable;
|
|
195
|
-
dstDCtx->OFTptr = srcDCtx->entropy.OFTable;
|
|
196
|
-
dstDCtx->HUFptr = srcDCtx->entropy.hufTable;
|
|
197
|
-
dstDCtx->entropy.rep[0] = srcDCtx->entropy.rep[0];
|
|
198
|
-
dstDCtx->entropy.rep[1] = srcDCtx->entropy.rep[1];
|
|
199
|
-
dstDCtx->entropy.rep[2] = srcDCtx->entropy.rep[2];
|
|
200
|
-
}
|
|
231
|
+
size_t const toCopy = (size_t)((char*)(&dstDCtx->inBuff) - (char*)dstDCtx);
|
|
232
|
+
memcpy(dstDCtx, srcDCtx, toCopy); /* no need to copy workspace */
|
|
201
233
|
}
|
|
202
|
-
#endif
|
|
203
|
-
|
|
204
|
-
static void ZSTD_refDDict(ZSTD_DCtx* dstDCtx, const ZSTD_DDict* ddict);
|
|
205
234
|
|
|
206
235
|
|
|
207
236
|
/*-*************************************************************
|
|
@@ -215,7 +244,7 @@ static void ZSTD_refDDict(ZSTD_DCtx* dstDCtx, const ZSTD_DDict* ddict);
|
|
|
215
244
|
* Note 3 : Skippable Frame Identifiers are considered valid. */
|
|
216
245
|
unsigned ZSTD_isFrame(const void* buffer, size_t size)
|
|
217
246
|
{
|
|
218
|
-
if (size <
|
|
247
|
+
if (size < ZSTD_frameIdSize) return 0;
|
|
219
248
|
{ U32 const magic = MEM_readLE32(buffer);
|
|
220
249
|
if (magic == ZSTD_MAGICNUMBER) return 1;
|
|
221
250
|
if ((magic & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) return 1;
|
|
@@ -226,70 +255,91 @@ unsigned ZSTD_isFrame(const void* buffer, size_t size)
|
|
|
226
255
|
return 0;
|
|
227
256
|
}
|
|
228
257
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
*
|
|
232
|
-
*
|
|
233
|
-
|
|
258
|
+
/** ZSTD_frameHeaderSize_internal() :
|
|
259
|
+
* srcSize must be large enough to reach header size fields.
|
|
260
|
+
* note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless
|
|
261
|
+
* @return : size of the Frame Header
|
|
262
|
+
* or an error code, which can be tested with ZSTD_isError() */
|
|
263
|
+
static size_t ZSTD_frameHeaderSize_internal(const void* src, size_t srcSize, ZSTD_format_e format)
|
|
234
264
|
{
|
|
235
|
-
|
|
236
|
-
|
|
265
|
+
size_t const minInputSize = ZSTD_startingInputLength(format);
|
|
266
|
+
if (srcSize < minInputSize) return ERROR(srcSize_wrong);
|
|
267
|
+
|
|
268
|
+
{ BYTE const fhd = ((const BYTE*)src)[minInputSize-1];
|
|
237
269
|
U32 const dictID= fhd & 3;
|
|
238
270
|
U32 const singleSegment = (fhd >> 5) & 1;
|
|
239
271
|
U32 const fcsId = fhd >> 6;
|
|
240
|
-
return
|
|
241
|
-
|
|
272
|
+
return minInputSize + !singleSegment
|
|
273
|
+
+ ZSTD_did_fieldSize[dictID] + ZSTD_fcs_fieldSize[fcsId]
|
|
274
|
+
+ (singleSegment && !fcsId);
|
|
242
275
|
}
|
|
243
276
|
}
|
|
244
277
|
|
|
278
|
+
/** ZSTD_frameHeaderSize() :
|
|
279
|
+
* srcSize must be >= ZSTD_frameHeaderSize_prefix.
|
|
280
|
+
* @return : size of the Frame Header */
|
|
281
|
+
size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize)
|
|
282
|
+
{
|
|
283
|
+
return ZSTD_frameHeaderSize_internal(src, srcSize, ZSTD_f_zstd1);
|
|
284
|
+
}
|
|
285
|
+
|
|
245
286
|
|
|
246
|
-
/**
|
|
247
|
-
*
|
|
248
|
-
*
|
|
249
|
-
*
|
|
250
|
-
*
|
|
251
|
-
|
|
287
|
+
/** ZSTD_getFrameHeader_internal() :
|
|
288
|
+
* decode Frame Header, or require larger `srcSize`.
|
|
289
|
+
* note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless
|
|
290
|
+
* @return : 0, `zfhPtr` is correctly filled,
|
|
291
|
+
* >0, `srcSize` is too small, value is wanted `srcSize` amount,
|
|
292
|
+
* or an error code, which can be tested using ZSTD_isError() */
|
|
293
|
+
static size_t ZSTD_getFrameHeader_internal(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format)
|
|
252
294
|
{
|
|
253
295
|
const BYTE* ip = (const BYTE*)src;
|
|
296
|
+
size_t const minInputSize = ZSTD_startingInputLength(format);
|
|
254
297
|
|
|
255
|
-
if (srcSize <
|
|
256
|
-
|
|
298
|
+
if (srcSize < minInputSize) return minInputSize;
|
|
299
|
+
|
|
300
|
+
if ( (format != ZSTD_f_zstd1_magicless)
|
|
301
|
+
&& (MEM_readLE32(src) != ZSTD_MAGICNUMBER) ) {
|
|
257
302
|
if ((MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
303
|
+
/* skippable frame */
|
|
304
|
+
if (srcSize < ZSTD_skippableHeaderSize)
|
|
305
|
+
return ZSTD_skippableHeaderSize; /* magic number + frame length */
|
|
306
|
+
memset(zfhPtr, 0, sizeof(*zfhPtr));
|
|
307
|
+
zfhPtr->frameContentSize = MEM_readLE32((const char *)src + ZSTD_frameIdSize);
|
|
308
|
+
zfhPtr->frameType = ZSTD_skippableFrame;
|
|
262
309
|
return 0;
|
|
263
310
|
}
|
|
264
311
|
return ERROR(prefix_unknown);
|
|
265
312
|
}
|
|
266
313
|
|
|
267
314
|
/* ensure there is enough `srcSize` to fully read/decode frame header */
|
|
268
|
-
{
|
|
269
|
-
|
|
315
|
+
{ size_t const fhsize = ZSTD_frameHeaderSize_internal(src, srcSize, format);
|
|
316
|
+
if (srcSize < fhsize) return fhsize;
|
|
317
|
+
zfhPtr->headerSize = (U32)fhsize;
|
|
318
|
+
}
|
|
270
319
|
|
|
271
|
-
{ BYTE const fhdByte = ip[
|
|
272
|
-
size_t pos =
|
|
320
|
+
{ BYTE const fhdByte = ip[minInputSize-1];
|
|
321
|
+
size_t pos = minInputSize;
|
|
273
322
|
U32 const dictIDSizeCode = fhdByte&3;
|
|
274
323
|
U32 const checksumFlag = (fhdByte>>2)&1;
|
|
275
324
|
U32 const singleSegment = (fhdByte>>5)&1;
|
|
276
325
|
U32 const fcsID = fhdByte>>6;
|
|
277
|
-
|
|
278
|
-
U32 windowSize = 0;
|
|
326
|
+
U64 windowSize = 0;
|
|
279
327
|
U32 dictID = 0;
|
|
280
|
-
U64 frameContentSize =
|
|
281
|
-
if ((fhdByte & 0x08) != 0)
|
|
328
|
+
U64 frameContentSize = ZSTD_CONTENTSIZE_UNKNOWN;
|
|
329
|
+
if ((fhdByte & 0x08) != 0)
|
|
330
|
+
return ERROR(frameParameter_unsupported); /* reserved bits, must be zero */
|
|
331
|
+
|
|
282
332
|
if (!singleSegment) {
|
|
283
333
|
BYTE const wlByte = ip[pos++];
|
|
284
334
|
U32 const windowLog = (wlByte >> 3) + ZSTD_WINDOWLOG_ABSOLUTEMIN;
|
|
285
|
-
if (windowLog > ZSTD_WINDOWLOG_MAX)
|
|
286
|
-
|
|
335
|
+
if (windowLog > ZSTD_WINDOWLOG_MAX)
|
|
336
|
+
return ERROR(frameParameter_windowTooLarge);
|
|
337
|
+
windowSize = (1ULL << windowLog);
|
|
287
338
|
windowSize += (windowSize >> 3) * (wlByte&7);
|
|
288
339
|
}
|
|
289
|
-
|
|
290
340
|
switch(dictIDSizeCode)
|
|
291
341
|
{
|
|
292
|
-
default:
|
|
342
|
+
default: assert(0); /* impossible */
|
|
293
343
|
case 0 : break;
|
|
294
344
|
case 1 : dictID = ip[pos]; pos++; break;
|
|
295
345
|
case 2 : dictID = MEM_readLE16(ip+pos); pos+=2; break;
|
|
@@ -297,27 +347,41 @@ size_t ZSTD_getFrameParams(ZSTD_frameParams* fparamsPtr, const void* src, size_t
|
|
|
297
347
|
}
|
|
298
348
|
switch(fcsID)
|
|
299
349
|
{
|
|
300
|
-
default:
|
|
350
|
+
default: assert(0); /* impossible */
|
|
301
351
|
case 0 : if (singleSegment) frameContentSize = ip[pos]; break;
|
|
302
352
|
case 1 : frameContentSize = MEM_readLE16(ip+pos)+256; break;
|
|
303
353
|
case 2 : frameContentSize = MEM_readLE32(ip+pos); break;
|
|
304
354
|
case 3 : frameContentSize = MEM_readLE64(ip+pos); break;
|
|
305
355
|
}
|
|
306
|
-
if (
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
356
|
+
if (singleSegment) windowSize = frameContentSize;
|
|
357
|
+
|
|
358
|
+
zfhPtr->frameType = ZSTD_frame;
|
|
359
|
+
zfhPtr->frameContentSize = frameContentSize;
|
|
360
|
+
zfhPtr->windowSize = windowSize;
|
|
361
|
+
zfhPtr->blockSizeMax = (unsigned) MIN(windowSize, ZSTD_BLOCKSIZE_MAX);
|
|
362
|
+
zfhPtr->dictID = dictID;
|
|
363
|
+
zfhPtr->checksumFlag = checksumFlag;
|
|
312
364
|
}
|
|
313
365
|
return 0;
|
|
314
366
|
}
|
|
315
367
|
|
|
368
|
+
/** ZSTD_getFrameHeader() :
|
|
369
|
+
* decode Frame Header, or require larger `srcSize`.
|
|
370
|
+
* note : this function does not consume input, it only reads it.
|
|
371
|
+
* @return : 0, `zfhPtr` is correctly filled,
|
|
372
|
+
* >0, `srcSize` is too small, value is wanted `srcSize` amount,
|
|
373
|
+
* or an error code, which can be tested using ZSTD_isError() */
|
|
374
|
+
size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize)
|
|
375
|
+
{
|
|
376
|
+
return ZSTD_getFrameHeader_internal(zfhPtr, src, srcSize, ZSTD_f_zstd1);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
|
|
316
380
|
/** ZSTD_getFrameContentSize() :
|
|
317
|
-
*
|
|
318
|
-
*
|
|
319
|
-
*
|
|
320
|
-
*
|
|
381
|
+
* compatible with legacy mode
|
|
382
|
+
* @return : decompressed size of the single frame pointed to be `src` if known, otherwise
|
|
383
|
+
* - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined
|
|
384
|
+
* - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small) */
|
|
321
385
|
unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize)
|
|
322
386
|
{
|
|
323
387
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
|
|
@@ -326,18 +390,14 @@ unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize)
|
|
|
326
390
|
return ret == 0 ? ZSTD_CONTENTSIZE_UNKNOWN : ret;
|
|
327
391
|
}
|
|
328
392
|
#endif
|
|
329
|
-
{
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
if (
|
|
333
|
-
/* Either skippable or empty frame, size == 0 either way */
|
|
393
|
+
{ ZSTD_frameHeader zfh;
|
|
394
|
+
if (ZSTD_getFrameHeader(&zfh, src, srcSize) != 0)
|
|
395
|
+
return ZSTD_CONTENTSIZE_ERROR;
|
|
396
|
+
if (zfh.frameType == ZSTD_skippableFrame) {
|
|
334
397
|
return 0;
|
|
335
|
-
} else if (fParams.frameContentSize != 0) {
|
|
336
|
-
return fParams.frameContentSize;
|
|
337
398
|
} else {
|
|
338
|
-
return
|
|
339
|
-
|
|
340
|
-
}
|
|
399
|
+
return zfh.frameContentSize;
|
|
400
|
+
} }
|
|
341
401
|
}
|
|
342
402
|
|
|
343
403
|
/** ZSTD_findDecompressedSize() :
|
|
@@ -347,64 +407,61 @@ unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize)
|
|
|
347
407
|
* @return : decompressed size of the frames contained */
|
|
348
408
|
unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
|
|
349
409
|
{
|
|
350
|
-
|
|
351
|
-
unsigned long long totalDstSize = 0;
|
|
352
|
-
while (srcSize >= ZSTD_frameHeaderSize_prefix) {
|
|
353
|
-
const U32 magicNumber = MEM_readLE32(src);
|
|
410
|
+
unsigned long long totalDstSize = 0;
|
|
354
411
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
srcSize -= skippableSize;
|
|
367
|
-
continue;
|
|
412
|
+
while (srcSize >= ZSTD_frameHeaderSize_prefix) {
|
|
413
|
+
U32 const magicNumber = MEM_readLE32(src);
|
|
414
|
+
|
|
415
|
+
if ((magicNumber & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
|
|
416
|
+
size_t skippableSize;
|
|
417
|
+
if (srcSize < ZSTD_skippableHeaderSize)
|
|
418
|
+
return ERROR(srcSize_wrong);
|
|
419
|
+
skippableSize = MEM_readLE32((const BYTE *)src + ZSTD_frameIdSize)
|
|
420
|
+
+ ZSTD_skippableHeaderSize;
|
|
421
|
+
if (srcSize < skippableSize) {
|
|
422
|
+
return ZSTD_CONTENTSIZE_ERROR;
|
|
368
423
|
}
|
|
369
424
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
425
|
+
src = (const BYTE *)src + skippableSize;
|
|
426
|
+
srcSize -= skippableSize;
|
|
427
|
+
continue;
|
|
428
|
+
}
|
|
373
429
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
totalDstSize += ret;
|
|
377
|
-
}
|
|
378
|
-
{
|
|
379
|
-
size_t const frameSrcSize = ZSTD_findFrameCompressedSize(src, srcSize);
|
|
380
|
-
if (ZSTD_isError(frameSrcSize)) {
|
|
381
|
-
return ZSTD_CONTENTSIZE_ERROR;
|
|
382
|
-
}
|
|
430
|
+
{ unsigned long long const ret = ZSTD_getFrameContentSize(src, srcSize);
|
|
431
|
+
if (ret >= ZSTD_CONTENTSIZE_ERROR) return ret;
|
|
383
432
|
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
433
|
+
/* check for overflow */
|
|
434
|
+
if (totalDstSize + ret < totalDstSize) return ZSTD_CONTENTSIZE_ERROR;
|
|
435
|
+
totalDstSize += ret;
|
|
387
436
|
}
|
|
437
|
+
{ size_t const frameSrcSize = ZSTD_findFrameCompressedSize(src, srcSize);
|
|
438
|
+
if (ZSTD_isError(frameSrcSize)) {
|
|
439
|
+
return ZSTD_CONTENTSIZE_ERROR;
|
|
440
|
+
}
|
|
388
441
|
|
|
389
|
-
|
|
390
|
-
|
|
442
|
+
src = (const BYTE *)src + frameSrcSize;
|
|
443
|
+
srcSize -= frameSrcSize;
|
|
391
444
|
}
|
|
445
|
+
} /* while (srcSize >= ZSTD_frameHeaderSize_prefix) */
|
|
392
446
|
|
|
393
|
-
|
|
394
|
-
|
|
447
|
+
if (srcSize) return ZSTD_CONTENTSIZE_ERROR;
|
|
448
|
+
|
|
449
|
+
return totalDstSize;
|
|
395
450
|
}
|
|
396
451
|
|
|
397
452
|
/** ZSTD_getDecompressedSize() :
|
|
398
453
|
* compatible with legacy mode
|
|
399
454
|
* @return : decompressed size if known, 0 otherwise
|
|
400
455
|
note : 0 can mean any of the following :
|
|
401
|
-
-
|
|
456
|
+
- frame content is empty
|
|
457
|
+
- decompressed size field is not present in frame header
|
|
402
458
|
- frame header unknown / not supported
|
|
403
459
|
- frame header not complete (`srcSize` too small) */
|
|
404
460
|
unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize)
|
|
405
461
|
{
|
|
406
462
|
unsigned long long const ret = ZSTD_getFrameContentSize(src, srcSize);
|
|
407
|
-
|
|
463
|
+
ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_ERROR < ZSTD_CONTENTSIZE_UNKNOWN);
|
|
464
|
+
return (ret >= ZSTD_CONTENTSIZE_ERROR) ? 0 : ret;
|
|
408
465
|
}
|
|
409
466
|
|
|
410
467
|
|
|
@@ -413,25 +470,20 @@ unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize)
|
|
|
413
470
|
* @return : 0 if success, or an error code, which can be tested using ZSTD_isError() */
|
|
414
471
|
static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t headerSize)
|
|
415
472
|
{
|
|
416
|
-
size_t const result =
|
|
417
|
-
if (ZSTD_isError(result)) return result;
|
|
418
|
-
if (result>0) return ERROR(srcSize_wrong);
|
|
419
|
-
if (dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID))
|
|
473
|
+
size_t const result = ZSTD_getFrameHeader_internal(&(dctx->fParams), src, headerSize, dctx->format);
|
|
474
|
+
if (ZSTD_isError(result)) return result; /* invalid header */
|
|
475
|
+
if (result>0) return ERROR(srcSize_wrong); /* headerSize too small */
|
|
476
|
+
if (dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID))
|
|
477
|
+
return ERROR(dictionary_wrong);
|
|
420
478
|
if (dctx->fParams.checksumFlag) XXH64_reset(&dctx->xxhState, 0);
|
|
421
479
|
return 0;
|
|
422
480
|
}
|
|
423
481
|
|
|
424
482
|
|
|
425
|
-
typedef struct
|
|
426
|
-
{
|
|
427
|
-
blockType_e blockType;
|
|
428
|
-
U32 lastBlock;
|
|
429
|
-
U32 origSize;
|
|
430
|
-
} blockProperties_t;
|
|
431
|
-
|
|
432
483
|
/*! ZSTD_getcBlockSize() :
|
|
433
484
|
* Provides the size of compressed block from block header `src` */
|
|
434
|
-
size_t ZSTD_getcBlockSize(const void* src, size_t srcSize,
|
|
485
|
+
size_t ZSTD_getcBlockSize(const void* src, size_t srcSize,
|
|
486
|
+
blockProperties_t* bpPtr)
|
|
435
487
|
{
|
|
436
488
|
if (srcSize < ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
|
|
437
489
|
{ U32 const cBlockHeader = MEM_readLE24(src);
|
|
@@ -446,7 +498,8 @@ size_t ZSTD_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bp
|
|
|
446
498
|
}
|
|
447
499
|
|
|
448
500
|
|
|
449
|
-
static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity,
|
|
501
|
+
static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity,
|
|
502
|
+
const void* src, size_t srcSize)
|
|
450
503
|
{
|
|
451
504
|
if (srcSize > dstCapacity) return ERROR(dstSize_tooSmall);
|
|
452
505
|
memcpy(dst, src, srcSize);
|
|
@@ -454,7 +507,9 @@ static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity, const void* src,
|
|
|
454
507
|
}
|
|
455
508
|
|
|
456
509
|
|
|
457
|
-
static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity,
|
|
510
|
+
static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity,
|
|
511
|
+
const void* src, size_t srcSize,
|
|
512
|
+
size_t regenSize)
|
|
458
513
|
{
|
|
459
514
|
if (srcSize != 1) return ERROR(srcSize_wrong);
|
|
460
515
|
if (regenSize > dstCapacity) return ERROR(dstSize_tooSmall);
|
|
@@ -463,7 +518,8 @@ static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity, const void* src, s
|
|
|
463
518
|
}
|
|
464
519
|
|
|
465
520
|
/*! ZSTD_decodeLiteralsBlock() :
|
|
466
|
-
|
|
521
|
+
* @return : nb of bytes read from src (< srcSize )
|
|
522
|
+
* note : symbol not declared but exposed for fullbench */
|
|
467
523
|
size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
|
|
468
524
|
const void* src, size_t srcSize) /* note : srcSize < BLOCKSIZE */
|
|
469
525
|
{
|
|
@@ -505,7 +561,7 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
|
|
|
505
561
|
litCSize = (lhc >> 22) + (istart[4] << 10);
|
|
506
562
|
break;
|
|
507
563
|
}
|
|
508
|
-
if (litSize >
|
|
564
|
+
if (litSize > ZSTD_BLOCKSIZE_MAX) return ERROR(corruption_detected);
|
|
509
565
|
if (litCSize + lhSize > srcSize) return ERROR(corruption_detected);
|
|
510
566
|
|
|
511
567
|
if (HUF_isError((litEncType==set_repeat) ?
|
|
@@ -513,8 +569,10 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
|
|
|
513
569
|
HUF_decompress1X_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->HUFptr) :
|
|
514
570
|
HUF_decompress4X_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->HUFptr) ) :
|
|
515
571
|
( singleStream ?
|
|
516
|
-
|
|
517
|
-
|
|
572
|
+
HUF_decompress1X2_DCtx_wksp(dctx->entropy.hufTable, dctx->litBuffer, litSize, istart+lhSize, litCSize,
|
|
573
|
+
dctx->entropy.workspace, sizeof(dctx->entropy.workspace)) :
|
|
574
|
+
HUF_decompress4X_hufOnly_wksp(dctx->entropy.hufTable, dctx->litBuffer, litSize, istart+lhSize, litCSize,
|
|
575
|
+
dctx->entropy.workspace, sizeof(dctx->entropy.workspace)))))
|
|
518
576
|
return ERROR(corruption_detected);
|
|
519
577
|
|
|
520
578
|
dctx->litPtr = dctx->litBuffer;
|
|
@@ -577,7 +635,7 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
|
|
|
577
635
|
if (srcSize<4) return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4 */
|
|
578
636
|
break;
|
|
579
637
|
}
|
|
580
|
-
if (litSize >
|
|
638
|
+
if (litSize > ZSTD_BLOCKSIZE_MAX) return ERROR(corruption_detected);
|
|
581
639
|
memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH);
|
|
582
640
|
dctx->litPtr = dctx->litBuffer;
|
|
583
641
|
dctx->litSize = litSize;
|
|
@@ -595,182 +653,76 @@ typedef union {
|
|
|
595
653
|
U32 alignedBy4;
|
|
596
654
|
} FSE_decode_t4;
|
|
597
655
|
|
|
656
|
+
/* Default FSE distribution table for Literal Lengths */
|
|
598
657
|
static const FSE_decode_t4 LL_defaultDTable[(1<<LL_DEFAULTNORMLOG)+1] = {
|
|
599
658
|
{ { LL_DEFAULTNORMLOG, 1, 1 } }, /* header : tableLog, fastMode, fastMode */
|
|
600
|
-
|
|
601
|
-
{ { 16, 0, 4 } },
|
|
602
|
-
{ {
|
|
603
|
-
{ { 0,
|
|
604
|
-
{ { 0,
|
|
605
|
-
{ { 0,
|
|
606
|
-
{ { 0,
|
|
607
|
-
{ { 0,
|
|
608
|
-
{ { 0, 10, 5 } },
|
|
609
|
-
{ { 0,
|
|
610
|
-
{ { 0,
|
|
611
|
-
{ { 0,
|
|
612
|
-
{ {
|
|
613
|
-
{ {
|
|
614
|
-
{ { 0,
|
|
615
|
-
{ {
|
|
616
|
-
{ { 0,
|
|
617
|
-
{ { 32, 25, 5 } },
|
|
618
|
-
{ { 0, 26, 5 } },
|
|
619
|
-
{ { 0, 27, 6 } },
|
|
620
|
-
{ { 0, 29, 6 } },
|
|
621
|
-
{ { 0, 31, 6 } },
|
|
622
|
-
{ { 32, 0, 4 } },
|
|
623
|
-
{ { 0, 1, 4 } },
|
|
624
|
-
{ { 0, 2, 5 } },
|
|
625
|
-
{ { 32, 4, 5 } },
|
|
626
|
-
{ { 0, 5, 5 } },
|
|
627
|
-
{ { 32, 7, 5 } },
|
|
628
|
-
{ { 0, 8, 5 } },
|
|
629
|
-
{ { 32, 10, 5 } },
|
|
630
|
-
{ { 0, 11, 5 } },
|
|
631
|
-
{ { 0, 13, 6 } },
|
|
632
|
-
{ { 32, 16, 5 } },
|
|
633
|
-
{ { 0, 17, 5 } },
|
|
634
|
-
{ { 32, 19, 5 } },
|
|
635
|
-
{ { 0, 20, 5 } },
|
|
636
|
-
{ { 32, 22, 5 } },
|
|
637
|
-
{ { 0, 23, 5 } },
|
|
638
|
-
{ { 0, 25, 4 } },
|
|
639
|
-
{ { 16, 25, 4 } },
|
|
640
|
-
{ { 32, 26, 5 } },
|
|
641
|
-
{ { 0, 28, 6 } },
|
|
642
|
-
{ { 0, 30, 6 } },
|
|
643
|
-
{ { 48, 0, 4 } },
|
|
644
|
-
{ { 16, 1, 4 } },
|
|
645
|
-
{ { 32, 2, 5 } },
|
|
646
|
-
{ { 32, 3, 5 } },
|
|
647
|
-
{ { 32, 5, 5 } },
|
|
648
|
-
{ { 32, 6, 5 } },
|
|
649
|
-
{ { 32, 8, 5 } },
|
|
650
|
-
{ { 32, 9, 5 } },
|
|
651
|
-
{ { 32, 11, 5 } },
|
|
652
|
-
{ { 32, 12, 5 } },
|
|
653
|
-
{ { 0, 15, 6 } },
|
|
654
|
-
{ { 32, 17, 5 } },
|
|
655
|
-
{ { 32, 18, 5 } },
|
|
656
|
-
{ { 32, 20, 5 } },
|
|
657
|
-
{ { 32, 21, 5 } },
|
|
658
|
-
{ { 32, 23, 5 } },
|
|
659
|
-
{ { 32, 24, 5 } },
|
|
660
|
-
{ { 0, 35, 6 } },
|
|
661
|
-
{ { 0, 34, 6 } },
|
|
662
|
-
{ { 0, 33, 6 } },
|
|
663
|
-
{ { 0, 32, 6 } },
|
|
659
|
+
/* base, symbol, bits */
|
|
660
|
+
{ { 0, 0, 4 } }, { { 16, 0, 4 } }, { { 32, 1, 5 } }, { { 0, 3, 5 } },
|
|
661
|
+
{ { 0, 4, 5 } }, { { 0, 6, 5 } }, { { 0, 7, 5 } }, { { 0, 9, 5 } },
|
|
662
|
+
{ { 0, 10, 5 } }, { { 0, 12, 5 } }, { { 0, 14, 6 } }, { { 0, 16, 5 } },
|
|
663
|
+
{ { 0, 18, 5 } }, { { 0, 19, 5 } }, { { 0, 21, 5 } }, { { 0, 22, 5 } },
|
|
664
|
+
{ { 0, 24, 5 } }, { { 32, 25, 5 } }, { { 0, 26, 5 } }, { { 0, 27, 6 } },
|
|
665
|
+
{ { 0, 29, 6 } }, { { 0, 31, 6 } }, { { 32, 0, 4 } }, { { 0, 1, 4 } },
|
|
666
|
+
{ { 0, 2, 5 } }, { { 32, 4, 5 } }, { { 0, 5, 5 } }, { { 32, 7, 5 } },
|
|
667
|
+
{ { 0, 8, 5 } }, { { 32, 10, 5 } }, { { 0, 11, 5 } }, { { 0, 13, 6 } },
|
|
668
|
+
{ { 32, 16, 5 } }, { { 0, 17, 5 } }, { { 32, 19, 5 } }, { { 0, 20, 5 } },
|
|
669
|
+
{ { 32, 22, 5 } }, { { 0, 23, 5 } }, { { 0, 25, 4 } }, { { 16, 25, 4 } },
|
|
670
|
+
{ { 32, 26, 5 } }, { { 0, 28, 6 } }, { { 0, 30, 6 } }, { { 48, 0, 4 } },
|
|
671
|
+
{ { 16, 1, 4 } }, { { 32, 2, 5 } }, { { 32, 3, 5 } }, { { 32, 5, 5 } },
|
|
672
|
+
{ { 32, 6, 5 } }, { { 32, 8, 5 } }, { { 32, 9, 5 } }, { { 32, 11, 5 } },
|
|
673
|
+
{ { 32, 12, 5 } }, { { 0, 15, 6 } }, { { 32, 17, 5 } }, { { 32, 18, 5 } },
|
|
674
|
+
{ { 32, 20, 5 } }, { { 32, 21, 5 } }, { { 32, 23, 5 } }, { { 32, 24, 5 } },
|
|
675
|
+
{ { 0, 35, 6 } }, { { 0, 34, 6 } }, { { 0, 33, 6 } }, { { 0, 32, 6 } },
|
|
664
676
|
}; /* LL_defaultDTable */
|
|
665
677
|
|
|
678
|
+
/* Default FSE distribution table for Match Lengths */
|
|
666
679
|
static const FSE_decode_t4 ML_defaultDTable[(1<<ML_DEFAULTNORMLOG)+1] = {
|
|
667
680
|
{ { ML_DEFAULTNORMLOG, 1, 1 } }, /* header : tableLog, fastMode, fastMode */
|
|
668
|
-
|
|
669
|
-
{ { 0, 1, 4 } },
|
|
670
|
-
{ {
|
|
671
|
-
{ { 0,
|
|
672
|
-
{ { 0,
|
|
673
|
-
{ { 0, 6,
|
|
674
|
-
{ { 0,
|
|
675
|
-
{ { 0,
|
|
676
|
-
{ { 0,
|
|
677
|
-
{ { 0,
|
|
678
|
-
{ { 0,
|
|
679
|
-
{ { 0,
|
|
680
|
-
{ {
|
|
681
|
-
{ { 0,
|
|
682
|
-
{ { 0,
|
|
683
|
-
{ { 0,
|
|
684
|
-
{ { 0,
|
|
685
|
-
{ { 0, 37, 6 } },
|
|
686
|
-
{ { 0, 39, 6 } },
|
|
687
|
-
{ { 0, 41, 6 } },
|
|
688
|
-
{ { 0, 43, 6 } },
|
|
689
|
-
{ { 0, 45, 6 } },
|
|
690
|
-
{ { 16, 1, 4 } },
|
|
691
|
-
{ { 0, 2, 4 } },
|
|
692
|
-
{ { 32, 3, 5 } },
|
|
693
|
-
{ { 0, 4, 5 } },
|
|
694
|
-
{ { 32, 6, 5 } },
|
|
695
|
-
{ { 0, 7, 5 } },
|
|
696
|
-
{ { 0, 9, 6 } },
|
|
697
|
-
{ { 0, 12, 6 } },
|
|
698
|
-
{ { 0, 15, 6 } },
|
|
699
|
-
{ { 0, 18, 6 } },
|
|
700
|
-
{ { 0, 21, 6 } },
|
|
701
|
-
{ { 0, 24, 6 } },
|
|
702
|
-
{ { 0, 27, 6 } },
|
|
703
|
-
{ { 0, 30, 6 } },
|
|
704
|
-
{ { 0, 32, 6 } },
|
|
705
|
-
{ { 0, 34, 6 } },
|
|
706
|
-
{ { 0, 36, 6 } },
|
|
707
|
-
{ { 0, 38, 6 } },
|
|
708
|
-
{ { 0, 40, 6 } },
|
|
709
|
-
{ { 0, 42, 6 } },
|
|
710
|
-
{ { 0, 44, 6 } },
|
|
711
|
-
{ { 32, 1, 4 } },
|
|
712
|
-
{ { 48, 1, 4 } },
|
|
713
|
-
{ { 16, 2, 4 } },
|
|
714
|
-
{ { 32, 4, 5 } },
|
|
715
|
-
{ { 32, 5, 5 } },
|
|
716
|
-
{ { 32, 7, 5 } },
|
|
717
|
-
{ { 32, 8, 5 } },
|
|
718
|
-
{ { 0, 11, 6 } },
|
|
719
|
-
{ { 0, 14, 6 } },
|
|
720
|
-
{ { 0, 17, 6 } },
|
|
721
|
-
{ { 0, 20, 6 } },
|
|
722
|
-
{ { 0, 23, 6 } },
|
|
723
|
-
{ { 0, 26, 6 } },
|
|
724
|
-
{ { 0, 29, 6 } },
|
|
725
|
-
{ { 0, 52, 6 } },
|
|
726
|
-
{ { 0, 51, 6 } },
|
|
727
|
-
{ { 0, 50, 6 } },
|
|
728
|
-
{ { 0, 49, 6 } },
|
|
729
|
-
{ { 0, 48, 6 } },
|
|
730
|
-
{ { 0, 47, 6 } },
|
|
731
|
-
{ { 0, 46, 6 } },
|
|
681
|
+
/* base, symbol, bits */
|
|
682
|
+
{ { 0, 0, 6 } }, { { 0, 1, 4 } }, { { 32, 2, 5 } }, { { 0, 3, 5 } },
|
|
683
|
+
{ { 0, 5, 5 } }, { { 0, 6, 5 } }, { { 0, 8, 5 } }, { { 0, 10, 6 } },
|
|
684
|
+
{ { 0, 13, 6 } }, { { 0, 16, 6 } }, { { 0, 19, 6 } }, { { 0, 22, 6 } },
|
|
685
|
+
{ { 0, 25, 6 } }, { { 0, 28, 6 } }, { { 0, 31, 6 } }, { { 0, 33, 6 } },
|
|
686
|
+
{ { 0, 35, 6 } }, { { 0, 37, 6 } }, { { 0, 39, 6 } }, { { 0, 41, 6 } },
|
|
687
|
+
{ { 0, 43, 6 } }, { { 0, 45, 6 } }, { { 16, 1, 4 } }, { { 0, 2, 4 } },
|
|
688
|
+
{ { 32, 3, 5 } }, { { 0, 4, 5 } }, { { 32, 6, 5 } }, { { 0, 7, 5 } },
|
|
689
|
+
{ { 0, 9, 6 } }, { { 0, 12, 6 } }, { { 0, 15, 6 } }, { { 0, 18, 6 } },
|
|
690
|
+
{ { 0, 21, 6 } }, { { 0, 24, 6 } }, { { 0, 27, 6 } }, { { 0, 30, 6 } },
|
|
691
|
+
{ { 0, 32, 6 } }, { { 0, 34, 6 } }, { { 0, 36, 6 } }, { { 0, 38, 6 } },
|
|
692
|
+
{ { 0, 40, 6 } }, { { 0, 42, 6 } }, { { 0, 44, 6 } }, { { 32, 1, 4 } },
|
|
693
|
+
{ { 48, 1, 4 } }, { { 16, 2, 4 } }, { { 32, 4, 5 } }, { { 32, 5, 5 } },
|
|
694
|
+
{ { 32, 7, 5 } }, { { 32, 8, 5 } }, { { 0, 11, 6 } }, { { 0, 14, 6 } },
|
|
695
|
+
{ { 0, 17, 6 } }, { { 0, 20, 6 } }, { { 0, 23, 6 } }, { { 0, 26, 6 } },
|
|
696
|
+
{ { 0, 29, 6 } }, { { 0, 52, 6 } }, { { 0, 51, 6 } }, { { 0, 50, 6 } },
|
|
697
|
+
{ { 0, 49, 6 } }, { { 0, 48, 6 } }, { { 0, 47, 6 } }, { { 0, 46, 6 } },
|
|
732
698
|
}; /* ML_defaultDTable */
|
|
733
699
|
|
|
700
|
+
/* Default FSE distribution table for Offset Codes */
|
|
734
701
|
static const FSE_decode_t4 OF_defaultDTable[(1<<OF_DEFAULTNORMLOG)+1] = {
|
|
735
702
|
{ { OF_DEFAULTNORMLOG, 1, 1 } }, /* header : tableLog, fastMode, fastMode */
|
|
736
|
-
|
|
737
|
-
{ { 0, 6, 4 } },
|
|
738
|
-
{ { 0, 9, 5 } },
|
|
739
|
-
{ { 0,
|
|
740
|
-
{ { 0,
|
|
741
|
-
{ { 0,
|
|
742
|
-
{ { 0,
|
|
743
|
-
{ { 0,
|
|
744
|
-
{ { 0,
|
|
745
|
-
{ { 0,
|
|
746
|
-
{ { 0, 5, 5 } },
|
|
747
|
-
{ {
|
|
748
|
-
{ { 0,
|
|
749
|
-
{ { 0,
|
|
750
|
-
{ { 0,
|
|
751
|
-
{ {
|
|
752
|
-
{ { 0,
|
|
753
|
-
{ { 0, 17, 5 } },
|
|
754
|
-
{ { 0, 22, 5 } },
|
|
755
|
-
{ { 0, 4, 5 } },
|
|
756
|
-
{ { 16, 8, 4 } },
|
|
757
|
-
{ { 0, 13, 5 } },
|
|
758
|
-
{ { 0, 19, 5 } },
|
|
759
|
-
{ { 0, 1, 5 } },
|
|
760
|
-
{ { 16, 6, 4 } },
|
|
761
|
-
{ { 0, 10, 5 } },
|
|
762
|
-
{ { 0, 16, 5 } },
|
|
763
|
-
{ { 0, 28, 5 } },
|
|
764
|
-
{ { 0, 27, 5 } },
|
|
765
|
-
{ { 0, 26, 5 } },
|
|
766
|
-
{ { 0, 25, 5 } },
|
|
767
|
-
{ { 0, 24, 5 } },
|
|
703
|
+
/* base, symbol, bits */
|
|
704
|
+
{ { 0, 0, 5 } }, { { 0, 6, 4 } },
|
|
705
|
+
{ { 0, 9, 5 } }, { { 0, 15, 5 } },
|
|
706
|
+
{ { 0, 21, 5 } }, { { 0, 3, 5 } },
|
|
707
|
+
{ { 0, 7, 4 } }, { { 0, 12, 5 } },
|
|
708
|
+
{ { 0, 18, 5 } }, { { 0, 23, 5 } },
|
|
709
|
+
{ { 0, 5, 5 } }, { { 0, 8, 4 } },
|
|
710
|
+
{ { 0, 14, 5 } }, { { 0, 20, 5 } },
|
|
711
|
+
{ { 0, 2, 5 } }, { { 16, 7, 4 } },
|
|
712
|
+
{ { 0, 11, 5 } }, { { 0, 17, 5 } },
|
|
713
|
+
{ { 0, 22, 5 } }, { { 0, 4, 5 } },
|
|
714
|
+
{ { 16, 8, 4 } }, { { 0, 13, 5 } },
|
|
715
|
+
{ { 0, 19, 5 } }, { { 0, 1, 5 } },
|
|
716
|
+
{ { 16, 6, 4 } }, { { 0, 10, 5 } },
|
|
717
|
+
{ { 0, 16, 5 } }, { { 0, 28, 5 } },
|
|
718
|
+
{ { 0, 27, 5 } }, { { 0, 26, 5 } },
|
|
719
|
+
{ { 0, 25, 5 } }, { { 0, 24, 5 } },
|
|
768
720
|
}; /* OF_defaultDTable */
|
|
769
721
|
|
|
770
722
|
/*! ZSTD_buildSeqTable() :
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
*/
|
|
723
|
+
* @return : nb bytes read from src,
|
|
724
|
+
* or an error code if it fails, testable with ZSTD_isError()
|
|
725
|
+
*/
|
|
774
726
|
static size_t ZSTD_buildSeqTable(FSE_DTable* DTableSpace, const FSE_DTable** DTablePtr,
|
|
775
727
|
symbolEncodingType_e type, U32 max, U32 maxLog,
|
|
776
728
|
const void* src, size_t srcSize,
|
|
@@ -810,6 +762,7 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
|
|
|
810
762
|
const BYTE* const istart = (const BYTE* const)src;
|
|
811
763
|
const BYTE* const iend = istart + srcSize;
|
|
812
764
|
const BYTE* ip = istart;
|
|
765
|
+
DEBUGLOG(5, "ZSTD_decodeSeqHeaders");
|
|
813
766
|
|
|
814
767
|
/* check */
|
|
815
768
|
if (srcSize < MIN_SEQUENCES_SIZE) return ERROR(srcSize_wrong);
|
|
@@ -874,9 +827,9 @@ typedef struct {
|
|
|
874
827
|
FSE_DState_t stateOffb;
|
|
875
828
|
FSE_DState_t stateML;
|
|
876
829
|
size_t prevOffset[ZSTD_REP_NUM];
|
|
877
|
-
const BYTE*
|
|
830
|
+
const BYTE* prefixStart;
|
|
831
|
+
const BYTE* dictEnd;
|
|
878
832
|
size_t pos;
|
|
879
|
-
uPtrDiff gotoDict;
|
|
880
833
|
} seqState_t;
|
|
881
834
|
|
|
882
835
|
|
|
@@ -927,15 +880,25 @@ size_t ZSTD_execSequenceLast7(BYTE* op,
|
|
|
927
880
|
}
|
|
928
881
|
|
|
929
882
|
|
|
883
|
+
typedef enum { ZSTD_lo_isRegularOffset, ZSTD_lo_isLongOffset=1 } ZSTD_longOffset_e;
|
|
930
884
|
|
|
885
|
+
/* We need to add at most (ZSTD_WINDOWLOG_MAX_32 - 1) bits to read the maximum
|
|
886
|
+
* offset bits. But we can only read at most (STREAM_ACCUMULATOR_MIN_32 - 1)
|
|
887
|
+
* bits before reloading. This value is the maximum number of bytes we read
|
|
888
|
+
* after reloading when we are decoding long offets.
|
|
889
|
+
*/
|
|
890
|
+
#define LONG_OFFSETS_MAX_EXTRA_BITS_32 \
|
|
891
|
+
(ZSTD_WINDOWLOG_MAX_32 > STREAM_ACCUMULATOR_MIN_32 \
|
|
892
|
+
? ZSTD_WINDOWLOG_MAX_32 - STREAM_ACCUMULATOR_MIN_32 \
|
|
893
|
+
: 0)
|
|
931
894
|
|
|
932
|
-
static seq_t ZSTD_decodeSequence(seqState_t* seqState)
|
|
895
|
+
static seq_t ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets)
|
|
933
896
|
{
|
|
934
897
|
seq_t seq;
|
|
935
898
|
|
|
936
899
|
U32 const llCode = FSE_peekSymbol(&seqState->stateLL);
|
|
937
900
|
U32 const mlCode = FSE_peekSymbol(&seqState->stateML);
|
|
938
|
-
U32 const ofCode = FSE_peekSymbol(&seqState->stateOffb); /* <=
|
|
901
|
+
U32 const ofCode = FSE_peekSymbol(&seqState->stateOffb); /* <= MaxOff, by table construction */
|
|
939
902
|
|
|
940
903
|
U32 const llBits = LL_bits[llCode];
|
|
941
904
|
U32 const mlBits = ML_bits[mlCode];
|
|
@@ -943,29 +906,44 @@ static seq_t ZSTD_decodeSequence(seqState_t* seqState)
|
|
|
943
906
|
U32 const totalBits = llBits+mlBits+ofBits;
|
|
944
907
|
|
|
945
908
|
static const U32 LL_base[MaxLL+1] = {
|
|
946
|
-
0,
|
|
947
|
-
|
|
909
|
+
0, 1, 2, 3, 4, 5, 6, 7,
|
|
910
|
+
8, 9, 10, 11, 12, 13, 14, 15,
|
|
911
|
+
16, 18, 20, 22, 24, 28, 32, 40,
|
|
912
|
+
48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000,
|
|
948
913
|
0x2000, 0x4000, 0x8000, 0x10000 };
|
|
949
914
|
|
|
950
915
|
static const U32 ML_base[MaxML+1] = {
|
|
951
|
-
3, 4, 5,
|
|
952
|
-
|
|
953
|
-
|
|
916
|
+
3, 4, 5, 6, 7, 8, 9, 10,
|
|
917
|
+
11, 12, 13, 14, 15, 16, 17, 18,
|
|
918
|
+
19, 20, 21, 22, 23, 24, 25, 26,
|
|
919
|
+
27, 28, 29, 30, 31, 32, 33, 34,
|
|
920
|
+
35, 37, 39, 41, 43, 47, 51, 59,
|
|
921
|
+
67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803,
|
|
954
922
|
0x1003, 0x2003, 0x4003, 0x8003, 0x10003 };
|
|
955
923
|
|
|
956
924
|
static const U32 OF_base[MaxOff+1] = {
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
925
|
+
0, 1, 1, 5, 0xD, 0x1D, 0x3D, 0x7D,
|
|
926
|
+
0xFD, 0x1FD, 0x3FD, 0x7FD, 0xFFD, 0x1FFD, 0x3FFD, 0x7FFD,
|
|
927
|
+
0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD,
|
|
928
|
+
0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD, 0x1FFFFFFD, 0x3FFFFFFD, 0x7FFFFFFD };
|
|
961
929
|
|
|
962
930
|
/* sequence */
|
|
963
931
|
{ size_t offset;
|
|
964
932
|
if (!ofCode)
|
|
965
933
|
offset = 0;
|
|
966
934
|
else {
|
|
967
|
-
|
|
968
|
-
|
|
935
|
+
ZSTD_STATIC_ASSERT(ZSTD_lo_isLongOffset == 1);
|
|
936
|
+
ZSTD_STATIC_ASSERT(LONG_OFFSETS_MAX_EXTRA_BITS_32 == 5);
|
|
937
|
+
assert(ofBits <= MaxOff);
|
|
938
|
+
if (MEM_32bits() && longOffsets) {
|
|
939
|
+
U32 const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN_32-1);
|
|
940
|
+
offset = OF_base[ofCode] + (BIT_readBitsFast(&seqState->DStream, ofBits - extraBits) << extraBits);
|
|
941
|
+
if (MEM_32bits() || extraBits) BIT_reloadDStream(&seqState->DStream);
|
|
942
|
+
if (extraBits) offset += BIT_readBitsFast(&seqState->DStream, extraBits);
|
|
943
|
+
} else {
|
|
944
|
+
offset = OF_base[ofCode] + BIT_readBitsFast(&seqState->DStream, ofBits); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */
|
|
945
|
+
if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream);
|
|
946
|
+
}
|
|
969
947
|
}
|
|
970
948
|
|
|
971
949
|
if (ofCode <= 1) {
|
|
@@ -987,12 +965,22 @@ static seq_t ZSTD_decodeSequence(seqState_t* seqState)
|
|
|
987
965
|
seq.offset = offset;
|
|
988
966
|
}
|
|
989
967
|
|
|
990
|
-
seq.matchLength = ML_base[mlCode]
|
|
991
|
-
|
|
968
|
+
seq.matchLength = ML_base[mlCode]
|
|
969
|
+
+ ((mlCode>31) ? BIT_readBitsFast(&seqState->DStream, mlBits) : 0); /* <= 16 bits */
|
|
970
|
+
if (MEM_32bits() && (mlBits+llBits >= STREAM_ACCUMULATOR_MIN_32-LONG_OFFSETS_MAX_EXTRA_BITS_32))
|
|
971
|
+
BIT_reloadDStream(&seqState->DStream);
|
|
972
|
+
if (MEM_64bits() && (totalBits >= STREAM_ACCUMULATOR_MIN_64-(LLFSELog+MLFSELog+OffFSELog)))
|
|
973
|
+
BIT_reloadDStream(&seqState->DStream);
|
|
974
|
+
/* Verify that there is enough bits to read the rest of the data in 64-bit mode. */
|
|
975
|
+
ZSTD_STATIC_ASSERT(16+LLFSELog+MLFSELog+OffFSELog < STREAM_ACCUMULATOR_MIN_64);
|
|
992
976
|
|
|
993
|
-
seq.litLength = LL_base[llCode]
|
|
994
|
-
|
|
995
|
-
|
|
977
|
+
seq.litLength = LL_base[llCode]
|
|
978
|
+
+ ((llCode>15) ? BIT_readBitsFast(&seqState->DStream, llBits) : 0); /* <= 16 bits */
|
|
979
|
+
if (MEM_32bits())
|
|
980
|
+
BIT_reloadDStream(&seqState->DStream);
|
|
981
|
+
|
|
982
|
+
DEBUGLOG(6, "seq: litL=%u, matchL=%u, offset=%u",
|
|
983
|
+
(U32)seq.litLength, (U32)seq.matchLength, (U32)seq.offset);
|
|
996
984
|
|
|
997
985
|
/* ANS state update */
|
|
998
986
|
FSE_updateState(&seqState->stateLL, &seqState->DStream); /* <= 9 bits */
|
|
@@ -1004,7 +992,7 @@ static seq_t ZSTD_decodeSequence(seqState_t* seqState)
|
|
|
1004
992
|
}
|
|
1005
993
|
|
|
1006
994
|
|
|
1007
|
-
|
|
995
|
+
HINT_INLINE
|
|
1008
996
|
size_t ZSTD_execSequence(BYTE* op,
|
|
1009
997
|
BYTE* const oend, seq_t sequence,
|
|
1010
998
|
const BYTE** litPtr, const BYTE* const litLimit,
|
|
@@ -1031,8 +1019,9 @@ size_t ZSTD_execSequence(BYTE* op,
|
|
|
1031
1019
|
|
|
1032
1020
|
/* copy Match */
|
|
1033
1021
|
if (sequence.offset > (size_t)(oLitEnd - base)) {
|
|
1034
|
-
/* offset beyond prefix */
|
|
1035
|
-
if (sequence.offset > (size_t)(oLitEnd - vBase))
|
|
1022
|
+
/* offset beyond prefix -> go into extDict */
|
|
1023
|
+
if (sequence.offset > (size_t)(oLitEnd - vBase))
|
|
1024
|
+
return ERROR(corruption_detected);
|
|
1036
1025
|
match = dictEnd + (match - base);
|
|
1037
1026
|
if (match + sequence.matchLength <= dictEnd) {
|
|
1038
1027
|
memmove(oLitEnd, match, sequence.matchLength);
|
|
@@ -1087,7 +1076,8 @@ size_t ZSTD_execSequence(BYTE* op,
|
|
|
1087
1076
|
static size_t ZSTD_decompressSequences(
|
|
1088
1077
|
ZSTD_DCtx* dctx,
|
|
1089
1078
|
void* dst, size_t maxDstSize,
|
|
1090
|
-
const void* seqStart, size_t seqSize
|
|
1079
|
+
const void* seqStart, size_t seqSize,
|
|
1080
|
+
const ZSTD_longOffset_e isLongOffset)
|
|
1091
1081
|
{
|
|
1092
1082
|
const BYTE* ip = (const BYTE*)seqStart;
|
|
1093
1083
|
const BYTE* const iend = ip + seqSize;
|
|
@@ -1100,9 +1090,12 @@ static size_t ZSTD_decompressSequences(
|
|
|
1100
1090
|
const BYTE* const vBase = (const BYTE*) (dctx->vBase);
|
|
1101
1091
|
const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);
|
|
1102
1092
|
int nbSeq;
|
|
1093
|
+
DEBUGLOG(5, "ZSTD_decompressSequences");
|
|
1103
1094
|
|
|
1104
1095
|
/* Build Decoding Tables */
|
|
1105
1096
|
{ size_t const seqHSize = ZSTD_decodeSeqHeaders(dctx, &nbSeq, ip, seqSize);
|
|
1097
|
+
DEBUGLOG(5, "ZSTD_decodeSeqHeaders: size=%u, nbSeq=%i",
|
|
1098
|
+
(U32)seqHSize, nbSeq);
|
|
1106
1099
|
if (ZSTD_isError(seqHSize)) return seqHSize;
|
|
1107
1100
|
ip += seqHSize;
|
|
1108
1101
|
}
|
|
@@ -1119,13 +1112,15 @@ static size_t ZSTD_decompressSequences(
|
|
|
1119
1112
|
|
|
1120
1113
|
for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && nbSeq ; ) {
|
|
1121
1114
|
nbSeq--;
|
|
1122
|
-
{ seq_t const sequence = ZSTD_decodeSequence(&seqState);
|
|
1115
|
+
{ seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset);
|
|
1123
1116
|
size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litEnd, base, vBase, dictEnd);
|
|
1117
|
+
DEBUGLOG(6, "regenerated sequence size : %u", (U32)oneSeqSize);
|
|
1124
1118
|
if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
|
|
1125
1119
|
op += oneSeqSize;
|
|
1126
1120
|
} }
|
|
1127
1121
|
|
|
1128
1122
|
/* check if reached exact end */
|
|
1123
|
+
DEBUGLOG(5, "after decode loop, remaining nbSeq : %i", nbSeq);
|
|
1129
1124
|
if (nbSeq) return ERROR(corruption_detected);
|
|
1130
1125
|
/* save reps for next block */
|
|
1131
1126
|
{ U32 i; for (i=0; i<ZSTD_REP_NUM; i++) dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]); }
|
|
@@ -1142,13 +1137,14 @@ static size_t ZSTD_decompressSequences(
|
|
|
1142
1137
|
}
|
|
1143
1138
|
|
|
1144
1139
|
|
|
1145
|
-
|
|
1140
|
+
HINT_INLINE
|
|
1141
|
+
seq_t ZSTD_decodeSequenceLong(seqState_t* seqState, ZSTD_longOffset_e const longOffsets)
|
|
1146
1142
|
{
|
|
1147
1143
|
seq_t seq;
|
|
1148
1144
|
|
|
1149
1145
|
U32 const llCode = FSE_peekSymbol(&seqState->stateLL);
|
|
1150
1146
|
U32 const mlCode = FSE_peekSymbol(&seqState->stateML);
|
|
1151
|
-
U32 const ofCode = FSE_peekSymbol(&seqState->stateOffb); /* <=
|
|
1147
|
+
U32 const ofCode = FSE_peekSymbol(&seqState->stateOffb); /* <= MaxOff, by table construction */
|
|
1152
1148
|
|
|
1153
1149
|
U32 const llBits = LL_bits[llCode];
|
|
1154
1150
|
U32 const mlBits = ML_bits[mlCode];
|
|
@@ -1156,29 +1152,37 @@ FORCE_INLINE seq_t ZSTD_decodeSequenceLong_generic(seqState_t* seqState, int con
|
|
|
1156
1152
|
U32 const totalBits = llBits+mlBits+ofBits;
|
|
1157
1153
|
|
|
1158
1154
|
static const U32 LL_base[MaxLL+1] = {
|
|
1159
|
-
0, 1,
|
|
1160
|
-
|
|
1155
|
+
0, 1, 2, 3, 4, 5, 6, 7,
|
|
1156
|
+
8, 9, 10, 11, 12, 13, 14, 15,
|
|
1157
|
+
16, 18, 20, 22, 24, 28, 32, 40,
|
|
1158
|
+
48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000,
|
|
1161
1159
|
0x2000, 0x4000, 0x8000, 0x10000 };
|
|
1162
1160
|
|
|
1163
1161
|
static const U32 ML_base[MaxML+1] = {
|
|
1164
|
-
3, 4, 5,
|
|
1165
|
-
|
|
1166
|
-
|
|
1162
|
+
3, 4, 5, 6, 7, 8, 9, 10,
|
|
1163
|
+
11, 12, 13, 14, 15, 16, 17, 18,
|
|
1164
|
+
19, 20, 21, 22, 23, 24, 25, 26,
|
|
1165
|
+
27, 28, 29, 30, 31, 32, 33, 34,
|
|
1166
|
+
35, 37, 39, 41, 43, 47, 51, 59,
|
|
1167
|
+
67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803,
|
|
1167
1168
|
0x1003, 0x2003, 0x4003, 0x8003, 0x10003 };
|
|
1168
1169
|
|
|
1169
1170
|
static const U32 OF_base[MaxOff+1] = {
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1171
|
+
0, 1, 1, 5, 0xD, 0x1D, 0x3D, 0x7D,
|
|
1172
|
+
0xFD, 0x1FD, 0x3FD, 0x7FD, 0xFFD, 0x1FFD, 0x3FFD, 0x7FFD,
|
|
1173
|
+
0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD,
|
|
1174
|
+
0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD, 0x1FFFFFFD, 0x3FFFFFFD, 0x7FFFFFFD };
|
|
1174
1175
|
|
|
1175
1176
|
/* sequence */
|
|
1176
1177
|
{ size_t offset;
|
|
1177
1178
|
if (!ofCode)
|
|
1178
1179
|
offset = 0;
|
|
1179
1180
|
else {
|
|
1180
|
-
|
|
1181
|
-
|
|
1181
|
+
ZSTD_STATIC_ASSERT(ZSTD_lo_isLongOffset == 1);
|
|
1182
|
+
ZSTD_STATIC_ASSERT(LONG_OFFSETS_MAX_EXTRA_BITS_32 == 5);
|
|
1183
|
+
assert(ofBits <= MaxOff);
|
|
1184
|
+
if (MEM_32bits() && longOffsets) {
|
|
1185
|
+
U32 const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN_32-1);
|
|
1182
1186
|
offset = OF_base[ofCode] + (BIT_readBitsFast(&seqState->DStream, ofBits - extraBits) << extraBits);
|
|
1183
1187
|
if (MEM_32bits() || extraBits) BIT_reloadDStream(&seqState->DStream);
|
|
1184
1188
|
if (extraBits) offset += BIT_readBitsFast(&seqState->DStream, extraBits);
|
|
@@ -1208,15 +1212,21 @@ FORCE_INLINE seq_t ZSTD_decodeSequenceLong_generic(seqState_t* seqState, int con
|
|
|
1208
1212
|
}
|
|
1209
1213
|
|
|
1210
1214
|
seq.matchLength = ML_base[mlCode] + ((mlCode>31) ? BIT_readBitsFast(&seqState->DStream, mlBits) : 0); /* <= 16 bits */
|
|
1211
|
-
if (MEM_32bits() && (mlBits+llBits
|
|
1215
|
+
if (MEM_32bits() && (mlBits+llBits >= STREAM_ACCUMULATOR_MIN_32-LONG_OFFSETS_MAX_EXTRA_BITS_32))
|
|
1216
|
+
BIT_reloadDStream(&seqState->DStream);
|
|
1217
|
+
if (MEM_64bits() && (totalBits >= STREAM_ACCUMULATOR_MIN_64-(LLFSELog+MLFSELog+OffFSELog)))
|
|
1218
|
+
BIT_reloadDStream(&seqState->DStream);
|
|
1219
|
+
/* Verify that there is enough bits to read the rest of the data in 64-bit mode. */
|
|
1220
|
+
ZSTD_STATIC_ASSERT(16+LLFSELog+MLFSELog+OffFSELog < STREAM_ACCUMULATOR_MIN_64);
|
|
1212
1221
|
|
|
1213
1222
|
seq.litLength = LL_base[llCode] + ((llCode>15) ? BIT_readBitsFast(&seqState->DStream, llBits) : 0); /* <= 16 bits */
|
|
1214
|
-
if (MEM_32bits()
|
|
1215
|
-
|
|
1223
|
+
if (MEM_32bits())
|
|
1224
|
+
BIT_reloadDStream(&seqState->DStream);
|
|
1216
1225
|
|
|
1217
1226
|
{ size_t const pos = seqState->pos + seq.litLength;
|
|
1218
|
-
|
|
1219
|
-
|
|
1227
|
+
const BYTE* const matchBase = (seq.offset > pos) ? seqState->dictEnd : seqState->prefixStart;
|
|
1228
|
+
seq.match = matchBase + pos - seq.offset; /* note : this operation can overflow when seq.offset is really too large, which can only happen when input is corrupted.
|
|
1229
|
+
* No consequence though : no memory access will occur, overly large offset will be detected in ZSTD_execSequenceLong() */
|
|
1220
1230
|
seqState->pos = pos + seq.matchLength;
|
|
1221
1231
|
}
|
|
1222
1232
|
|
|
@@ -1229,19 +1239,12 @@ FORCE_INLINE seq_t ZSTD_decodeSequenceLong_generic(seqState_t* seqState, int con
|
|
|
1229
1239
|
return seq;
|
|
1230
1240
|
}
|
|
1231
1241
|
|
|
1232
|
-
static seq_t ZSTD_decodeSequenceLong(seqState_t* seqState, unsigned const windowSize) {
|
|
1233
|
-
if (ZSTD_highbit32(windowSize) > STREAM_ACCUMULATOR_MIN) {
|
|
1234
|
-
return ZSTD_decodeSequenceLong_generic(seqState, 1);
|
|
1235
|
-
} else {
|
|
1236
|
-
return ZSTD_decodeSequenceLong_generic(seqState, 0);
|
|
1237
|
-
}
|
|
1238
|
-
}
|
|
1239
1242
|
|
|
1240
|
-
|
|
1243
|
+
HINT_INLINE
|
|
1241
1244
|
size_t ZSTD_execSequenceLong(BYTE* op,
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
+
BYTE* const oend, seq_t sequence,
|
|
1246
|
+
const BYTE** litPtr, const BYTE* const litLimit,
|
|
1247
|
+
const BYTE* const prefixStart, const BYTE* const dictStart, const BYTE* const dictEnd)
|
|
1245
1248
|
{
|
|
1246
1249
|
BYTE* const oLitEnd = op + sequence.litLength;
|
|
1247
1250
|
size_t const sequenceLength = sequence.litLength + sequence.matchLength;
|
|
@@ -1251,24 +1254,21 @@ size_t ZSTD_execSequenceLong(BYTE* op,
|
|
|
1251
1254
|
const BYTE* match = sequence.match;
|
|
1252
1255
|
|
|
1253
1256
|
/* check */
|
|
1254
|
-
|
|
1255
|
-
if (oMatchEnd>oend) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */
|
|
1257
|
+
if (oMatchEnd > oend) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */
|
|
1256
1258
|
if (iLitEnd > litLimit) return ERROR(corruption_detected); /* over-read beyond lit buffer */
|
|
1257
|
-
if (oLitEnd>oend_w) return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit,
|
|
1258
|
-
#endif
|
|
1259
|
+
if (oLitEnd > oend_w) return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit, prefixStart, dictStart, dictEnd);
|
|
1259
1260
|
|
|
1260
1261
|
/* copy Literals */
|
|
1261
|
-
ZSTD_copy8(op, *litPtr);
|
|
1262
|
+
ZSTD_copy8(op, *litPtr); /* note : op <= oLitEnd <= oend_w == oend - 8 */
|
|
1262
1263
|
if (sequence.litLength > 8)
|
|
1263
1264
|
ZSTD_wildcopy(op+8, (*litPtr)+8, sequence.litLength - 8); /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */
|
|
1264
1265
|
op = oLitEnd;
|
|
1265
1266
|
*litPtr = iLitEnd; /* update for next sequence */
|
|
1266
1267
|
|
|
1267
1268
|
/* copy Match */
|
|
1268
|
-
|
|
1269
|
-
if (sequence.offset > (size_t)(oLitEnd - base)) {
|
|
1269
|
+
if (sequence.offset > (size_t)(oLitEnd - prefixStart)) {
|
|
1270
1270
|
/* offset beyond prefix */
|
|
1271
|
-
if (sequence.offset > (size_t)(oLitEnd -
|
|
1271
|
+
if (sequence.offset > (size_t)(oLitEnd - dictStart)) return ERROR(corruption_detected);
|
|
1272
1272
|
if (match + sequence.matchLength <= dictEnd) {
|
|
1273
1273
|
memmove(oLitEnd, match, sequence.matchLength);
|
|
1274
1274
|
return sequenceLength;
|
|
@@ -1278,15 +1278,15 @@ size_t ZSTD_execSequenceLong(BYTE* op,
|
|
|
1278
1278
|
memmove(oLitEnd, match, length1);
|
|
1279
1279
|
op = oLitEnd + length1;
|
|
1280
1280
|
sequence.matchLength -= length1;
|
|
1281
|
-
match =
|
|
1281
|
+
match = prefixStart;
|
|
1282
1282
|
if (op > oend_w || sequence.matchLength < MINMATCH) {
|
|
1283
1283
|
U32 i;
|
|
1284
1284
|
for (i = 0; i < sequence.matchLength; ++i) op[i] = match[i];
|
|
1285
1285
|
return sequenceLength;
|
|
1286
1286
|
}
|
|
1287
1287
|
} }
|
|
1288
|
-
|
|
1289
|
-
|
|
1288
|
+
assert(op <= oend_w);
|
|
1289
|
+
assert(sequence.matchLength >= MINMATCH);
|
|
1290
1290
|
|
|
1291
1291
|
/* match within prefix */
|
|
1292
1292
|
if (sequence.offset < 8) {
|
|
@@ -1322,7 +1322,8 @@ size_t ZSTD_execSequenceLong(BYTE* op,
|
|
|
1322
1322
|
static size_t ZSTD_decompressSequencesLong(
|
|
1323
1323
|
ZSTD_DCtx* dctx,
|
|
1324
1324
|
void* dst, size_t maxDstSize,
|
|
1325
|
-
const void* seqStart, size_t seqSize
|
|
1325
|
+
const void* seqStart, size_t seqSize,
|
|
1326
|
+
const ZSTD_longOffset_e isLongOffset)
|
|
1326
1327
|
{
|
|
1327
1328
|
const BYTE* ip = (const BYTE*)seqStart;
|
|
1328
1329
|
const BYTE* const iend = ip + seqSize;
|
|
@@ -1331,10 +1332,9 @@ static size_t ZSTD_decompressSequencesLong(
|
|
|
1331
1332
|
BYTE* op = ostart;
|
|
1332
1333
|
const BYTE* litPtr = dctx->litPtr;
|
|
1333
1334
|
const BYTE* const litEnd = litPtr + dctx->litSize;
|
|
1334
|
-
const BYTE* const
|
|
1335
|
-
const BYTE* const
|
|
1335
|
+
const BYTE* const prefixStart = (const BYTE*) (dctx->base);
|
|
1336
|
+
const BYTE* const dictStart = (const BYTE*) (dctx->vBase);
|
|
1336
1337
|
const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);
|
|
1337
|
-
unsigned const windowSize = dctx->fParams.windowSize;
|
|
1338
1338
|
int nbSeq;
|
|
1339
1339
|
|
|
1340
1340
|
/* Build Decoding Tables */
|
|
@@ -1354,9 +1354,9 @@ static size_t ZSTD_decompressSequencesLong(
|
|
|
1354
1354
|
int seqNb;
|
|
1355
1355
|
dctx->fseEntropy = 1;
|
|
1356
1356
|
{ U32 i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }
|
|
1357
|
-
seqState.
|
|
1358
|
-
seqState.pos = (size_t)(op-
|
|
1359
|
-
seqState.
|
|
1357
|
+
seqState.prefixStart = prefixStart;
|
|
1358
|
+
seqState.pos = (size_t)(op-prefixStart);
|
|
1359
|
+
seqState.dictEnd = dictEnd;
|
|
1360
1360
|
CHECK_E(BIT_initDStream(&seqState.DStream, ip, iend-ip), corruption_detected);
|
|
1361
1361
|
FSE_initDState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
|
|
1362
1362
|
FSE_initDState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
|
|
@@ -1364,16 +1364,16 @@ static size_t ZSTD_decompressSequencesLong(
|
|
|
1364
1364
|
|
|
1365
1365
|
/* prepare in advance */
|
|
1366
1366
|
for (seqNb=0; (BIT_reloadDStream(&seqState.DStream) <= BIT_DStream_completed) && seqNb<seqAdvance; seqNb++) {
|
|
1367
|
-
sequences[seqNb] = ZSTD_decodeSequenceLong(&seqState,
|
|
1367
|
+
sequences[seqNb] = ZSTD_decodeSequenceLong(&seqState, isLongOffset);
|
|
1368
1368
|
}
|
|
1369
1369
|
if (seqNb<seqAdvance) return ERROR(corruption_detected);
|
|
1370
1370
|
|
|
1371
1371
|
/* decode and decompress */
|
|
1372
1372
|
for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && seqNb<nbSeq ; seqNb++) {
|
|
1373
|
-
seq_t const sequence = ZSTD_decodeSequenceLong(&seqState,
|
|
1374
|
-
size_t const oneSeqSize = ZSTD_execSequenceLong(op, oend, sequences[(seqNb-ADVANCED_SEQS) & STOSEQ_MASK], &litPtr, litEnd,
|
|
1373
|
+
seq_t const sequence = ZSTD_decodeSequenceLong(&seqState, isLongOffset);
|
|
1374
|
+
size_t const oneSeqSize = ZSTD_execSequenceLong(op, oend, sequences[(seqNb-ADVANCED_SEQS) & STOSEQ_MASK], &litPtr, litEnd, prefixStart, dictStart, dictEnd);
|
|
1375
1375
|
if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
|
|
1376
|
-
|
|
1376
|
+
PREFETCH(sequence.match); /* note : it's safe to invoke PREFETCH() on any memory address, including invalid ones */
|
|
1377
1377
|
sequences[seqNb&STOSEQ_MASK] = sequence;
|
|
1378
1378
|
op += oneSeqSize;
|
|
1379
1379
|
}
|
|
@@ -1382,7 +1382,7 @@ static size_t ZSTD_decompressSequencesLong(
|
|
|
1382
1382
|
/* finish queue */
|
|
1383
1383
|
seqNb -= seqAdvance;
|
|
1384
1384
|
for ( ; seqNb<nbSeq ; seqNb++) {
|
|
1385
|
-
size_t const oneSeqSize = ZSTD_execSequenceLong(op, oend, sequences[seqNb&STOSEQ_MASK], &litPtr, litEnd,
|
|
1385
|
+
size_t const oneSeqSize = ZSTD_execSequenceLong(op, oend, sequences[seqNb&STOSEQ_MASK], &litPtr, litEnd, prefixStart, dictStart, dictEnd);
|
|
1386
1386
|
if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
|
|
1387
1387
|
op += oneSeqSize;
|
|
1388
1388
|
}
|
|
@@ -1404,25 +1404,33 @@ static size_t ZSTD_decompressSequencesLong(
|
|
|
1404
1404
|
|
|
1405
1405
|
static size_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
|
|
1406
1406
|
void* dst, size_t dstCapacity,
|
|
1407
|
-
const void* src, size_t srcSize)
|
|
1407
|
+
const void* src, size_t srcSize, const int frame)
|
|
1408
1408
|
{ /* blockType == blockCompressed */
|
|
1409
1409
|
const BYTE* ip = (const BYTE*)src;
|
|
1410
|
-
|
|
1411
|
-
|
|
1410
|
+
/* isLongOffset must be true if there are long offsets.
|
|
1411
|
+
* Offsets are long if they are larger than 2^STREAM_ACCUMULATOR_MIN.
|
|
1412
|
+
* We don't expect that to be the case in 64-bit mode.
|
|
1413
|
+
* If we are in block mode we don't know the window size, so we have to be
|
|
1414
|
+
* conservative.
|
|
1415
|
+
*/
|
|
1416
|
+
ZSTD_longOffset_e const isLongOffset = (ZSTD_longOffset_e)(MEM_32bits() && (!frame || dctx->fParams.windowSize > (1ULL << STREAM_ACCUMULATOR_MIN)));
|
|
1417
|
+
/* windowSize could be any value at this point, since it is only validated
|
|
1418
|
+
* in the streaming API.
|
|
1419
|
+
*/
|
|
1420
|
+
DEBUGLOG(5, "ZSTD_decompressBlock_internal (size : %u)", (U32)srcSize);
|
|
1421
|
+
|
|
1422
|
+
if (srcSize >= ZSTD_BLOCKSIZE_MAX) return ERROR(srcSize_wrong);
|
|
1412
1423
|
|
|
1413
1424
|
/* Decode literals section */
|
|
1414
1425
|
{ size_t const litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize);
|
|
1426
|
+
DEBUGLOG(5, "ZSTD_decodeLiteralsBlock : %u", (U32)litCSize);
|
|
1415
1427
|
if (ZSTD_isError(litCSize)) return litCSize;
|
|
1416
1428
|
ip += litCSize;
|
|
1417
1429
|
srcSize -= litCSize;
|
|
1418
1430
|
}
|
|
1419
|
-
if (
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
/* it would be good to test this on ARM real hardware, to see if prefetch version improves speed */
|
|
1423
|
-
if (dctx->fParams.windowSize > (1<<23))
|
|
1424
|
-
return ZSTD_decompressSequencesLong(dctx, dst, dstCapacity, ip, srcSize);
|
|
1425
|
-
return ZSTD_decompressSequences(dctx, dst, dstCapacity, ip, srcSize);
|
|
1431
|
+
if (frame && dctx->fParams.windowSize > (1<<23))
|
|
1432
|
+
return ZSTD_decompressSequencesLong(dctx, dst, dstCapacity, ip, srcSize, isLongOffset);
|
|
1433
|
+
return ZSTD_decompressSequences(dctx, dst, dstCapacity, ip, srcSize, isLongOffset);
|
|
1426
1434
|
}
|
|
1427
1435
|
|
|
1428
1436
|
|
|
@@ -1442,7 +1450,7 @@ size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx,
|
|
|
1442
1450
|
{
|
|
1443
1451
|
size_t dSize;
|
|
1444
1452
|
ZSTD_checkContinuity(dctx, dst);
|
|
1445
|
-
dSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize);
|
|
1453
|
+
dSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 0);
|
|
1446
1454
|
dctx->previousDstEnd = (char*)dst + dSize;
|
|
1447
1455
|
return dSize;
|
|
1448
1456
|
}
|
|
@@ -1458,7 +1466,7 @@ ZSTDLIB_API size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, siz
|
|
|
1458
1466
|
}
|
|
1459
1467
|
|
|
1460
1468
|
|
|
1461
|
-
size_t ZSTD_generateNxBytes(void* dst, size_t dstCapacity, BYTE byte, size_t length)
|
|
1469
|
+
static size_t ZSTD_generateNxBytes(void* dst, size_t dstCapacity, BYTE byte, size_t length)
|
|
1462
1470
|
{
|
|
1463
1471
|
if (length > dstCapacity) return ERROR(dstSize_tooSmall);
|
|
1464
1472
|
memset(dst, byte, length);
|
|
@@ -1473,28 +1481,26 @@ size_t ZSTD_generateNxBytes(void* dst, size_t dstCapacity, BYTE byte, size_t len
|
|
|
1473
1481
|
size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
|
|
1474
1482
|
{
|
|
1475
1483
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
|
|
1476
|
-
if (ZSTD_isLegacy(src, srcSize))
|
|
1484
|
+
if (ZSTD_isLegacy(src, srcSize))
|
|
1485
|
+
return ZSTD_findFrameCompressedSizeLegacy(src, srcSize);
|
|
1477
1486
|
#endif
|
|
1478
|
-
if (srcSize >= ZSTD_skippableHeaderSize
|
|
1479
|
-
|
|
1480
|
-
return ZSTD_skippableHeaderSize + MEM_readLE32((const BYTE*)src +
|
|
1487
|
+
if ( (srcSize >= ZSTD_skippableHeaderSize)
|
|
1488
|
+
&& (MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START ) {
|
|
1489
|
+
return ZSTD_skippableHeaderSize + MEM_readLE32((const BYTE*)src + ZSTD_frameIdSize);
|
|
1481
1490
|
} else {
|
|
1482
1491
|
const BYTE* ip = (const BYTE*)src;
|
|
1483
1492
|
const BYTE* const ipstart = ip;
|
|
1484
1493
|
size_t remainingSize = srcSize;
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
size_t const headerSize = ZSTD_frameHeaderSize(ip, remainingSize);
|
|
1488
|
-
if (ZSTD_isError(headerSize)) return headerSize;
|
|
1494
|
+
ZSTD_frameHeader zfh;
|
|
1489
1495
|
|
|
1490
|
-
/* Frame Header */
|
|
1491
|
-
{ size_t const ret =
|
|
1496
|
+
/* Extract Frame Header */
|
|
1497
|
+
{ size_t const ret = ZSTD_getFrameHeader(&zfh, src, srcSize);
|
|
1492
1498
|
if (ZSTD_isError(ret)) return ret;
|
|
1493
1499
|
if (ret > 0) return ERROR(srcSize_wrong);
|
|
1494
1500
|
}
|
|
1495
1501
|
|
|
1496
|
-
ip += headerSize;
|
|
1497
|
-
remainingSize -= headerSize;
|
|
1502
|
+
ip += zfh.headerSize;
|
|
1503
|
+
remainingSize -= zfh.headerSize;
|
|
1498
1504
|
|
|
1499
1505
|
/* Loop on each block */
|
|
1500
1506
|
while (1) {
|
|
@@ -1502,7 +1508,8 @@ size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
|
|
|
1502
1508
|
size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
|
|
1503
1509
|
if (ZSTD_isError(cBlockSize)) return cBlockSize;
|
|
1504
1510
|
|
|
1505
|
-
if (ZSTD_blockHeaderSize + cBlockSize > remainingSize)
|
|
1511
|
+
if (ZSTD_blockHeaderSize + cBlockSize > remainingSize)
|
|
1512
|
+
return ERROR(srcSize_wrong);
|
|
1506
1513
|
|
|
1507
1514
|
ip += ZSTD_blockHeaderSize + cBlockSize;
|
|
1508
1515
|
remainingSize -= ZSTD_blockHeaderSize + cBlockSize;
|
|
@@ -1510,7 +1517,7 @@ size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
|
|
|
1510
1517
|
if (blockProperties.lastBlock) break;
|
|
1511
1518
|
}
|
|
1512
1519
|
|
|
1513
|
-
if (
|
|
1520
|
+
if (zfh.checksumFlag) { /* Final frame content checksum */
|
|
1514
1521
|
if (remainingSize < 4) return ERROR(srcSize_wrong);
|
|
1515
1522
|
ip += 4;
|
|
1516
1523
|
remainingSize -= 4;
|
|
@@ -1523,8 +1530,8 @@ size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
|
|
|
1523
1530
|
/*! ZSTD_decompressFrame() :
|
|
1524
1531
|
* @dctx must be properly initialized */
|
|
1525
1532
|
static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|
1526
|
-
|
|
1527
|
-
|
|
1533
|
+
void* dst, size_t dstCapacity,
|
|
1534
|
+
const void** srcPtr, size_t *srcSizePtr)
|
|
1528
1535
|
{
|
|
1529
1536
|
const BYTE* ip = (const BYTE*)(*srcPtr);
|
|
1530
1537
|
BYTE* const ostart = (BYTE* const)dst;
|
|
@@ -1533,13 +1540,15 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|
|
1533
1540
|
size_t remainingSize = *srcSizePtr;
|
|
1534
1541
|
|
|
1535
1542
|
/* check */
|
|
1536
|
-
if (remainingSize < ZSTD_frameHeaderSize_min+ZSTD_blockHeaderSize)
|
|
1543
|
+
if (remainingSize < ZSTD_frameHeaderSize_min+ZSTD_blockHeaderSize)
|
|
1544
|
+
return ERROR(srcSize_wrong);
|
|
1537
1545
|
|
|
1538
1546
|
/* Frame Header */
|
|
1539
1547
|
{ size_t const frameHeaderSize = ZSTD_frameHeaderSize(ip, ZSTD_frameHeaderSize_prefix);
|
|
1540
1548
|
if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;
|
|
1541
|
-
if (remainingSize < frameHeaderSize+ZSTD_blockHeaderSize)
|
|
1542
|
-
|
|
1549
|
+
if (remainingSize < frameHeaderSize+ZSTD_blockHeaderSize)
|
|
1550
|
+
return ERROR(srcSize_wrong);
|
|
1551
|
+
CHECK_F( ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize) );
|
|
1543
1552
|
ip += frameHeaderSize; remainingSize -= frameHeaderSize;
|
|
1544
1553
|
}
|
|
1545
1554
|
|
|
@@ -1557,7 +1566,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|
|
1557
1566
|
switch(blockProperties.blockType)
|
|
1558
1567
|
{
|
|
1559
1568
|
case bt_compressed:
|
|
1560
|
-
decodedSize = ZSTD_decompressBlock_internal(dctx, op, oend-op, ip, cBlockSize);
|
|
1569
|
+
decodedSize = ZSTD_decompressBlock_internal(dctx, op, oend-op, ip, cBlockSize, /* frame */ 1);
|
|
1561
1570
|
break;
|
|
1562
1571
|
case bt_raw :
|
|
1563
1572
|
decodedSize = ZSTD_copyRawBlock(op, oend-op, ip, cBlockSize);
|
|
@@ -1571,14 +1580,19 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|
|
1571
1580
|
}
|
|
1572
1581
|
|
|
1573
1582
|
if (ZSTD_isError(decodedSize)) return decodedSize;
|
|
1574
|
-
if (dctx->fParams.checksumFlag)
|
|
1583
|
+
if (dctx->fParams.checksumFlag)
|
|
1584
|
+
XXH64_update(&dctx->xxhState, op, decodedSize);
|
|
1575
1585
|
op += decodedSize;
|
|
1576
1586
|
ip += cBlockSize;
|
|
1577
1587
|
remainingSize -= cBlockSize;
|
|
1578
1588
|
if (blockProperties.lastBlock) break;
|
|
1579
1589
|
}
|
|
1580
1590
|
|
|
1581
|
-
if (dctx->fParams.
|
|
1591
|
+
if (dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) {
|
|
1592
|
+
if ((U64)(op-ostart) != dctx->fParams.frameContentSize) {
|
|
1593
|
+
return ERROR(corruption_detected);
|
|
1594
|
+
} }
|
|
1595
|
+
if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */
|
|
1582
1596
|
U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState);
|
|
1583
1597
|
U32 checkRead;
|
|
1584
1598
|
if (remainingSize<4) return ERROR(checksum_wrong);
|
|
@@ -1600,17 +1614,13 @@ static size_t ZSTD_DDictDictSize(const ZSTD_DDict* ddict);
|
|
|
1600
1614
|
static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
1601
1615
|
void* dst, size_t dstCapacity,
|
|
1602
1616
|
const void* src, size_t srcSize,
|
|
1603
|
-
const void
|
|
1617
|
+
const void* dict, size_t dictSize,
|
|
1604
1618
|
const ZSTD_DDict* ddict)
|
|
1605
1619
|
{
|
|
1606
1620
|
void* const dststart = dst;
|
|
1621
|
+
assert(dict==NULL || ddict==NULL); /* either dict or ddict set, not both */
|
|
1607
1622
|
|
|
1608
1623
|
if (ddict) {
|
|
1609
|
-
if (dict) {
|
|
1610
|
-
/* programmer error, these two cases should be mutually exclusive */
|
|
1611
|
-
return ERROR(GENERIC);
|
|
1612
|
-
}
|
|
1613
|
-
|
|
1614
1624
|
dict = ZSTD_DDictDictContent(ddict);
|
|
1615
1625
|
dictSize = ZSTD_DDictDictSize(ddict);
|
|
1616
1626
|
}
|
|
@@ -1623,6 +1633,8 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
|
1623
1633
|
size_t decodedSize;
|
|
1624
1634
|
size_t const frameSize = ZSTD_findFrameCompressedSizeLegacy(src, srcSize);
|
|
1625
1635
|
if (ZSTD_isError(frameSize)) return frameSize;
|
|
1636
|
+
/* legacy support is not compatible with static dctx */
|
|
1637
|
+
if (dctx->staticSize) return ERROR(memory_allocation);
|
|
1626
1638
|
|
|
1627
1639
|
decodedSize = ZSTD_decompressLegacy(dst, dstCapacity, src, frameSize, dict, dictSize);
|
|
1628
1640
|
|
|
@@ -1637,28 +1649,27 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
|
1637
1649
|
#endif
|
|
1638
1650
|
|
|
1639
1651
|
magicNumber = MEM_readLE32(src);
|
|
1652
|
+
DEBUGLOG(4, "reading magic number %08X (expecting %08X)",
|
|
1653
|
+
(U32)magicNumber, (U32)ZSTD_MAGICNUMBER);
|
|
1640
1654
|
if (magicNumber != ZSTD_MAGICNUMBER) {
|
|
1641
1655
|
if ((magicNumber & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
|
|
1642
1656
|
size_t skippableSize;
|
|
1643
1657
|
if (srcSize < ZSTD_skippableHeaderSize)
|
|
1644
1658
|
return ERROR(srcSize_wrong);
|
|
1645
|
-
skippableSize = MEM_readLE32((const BYTE
|
|
1646
|
-
|
|
1647
|
-
if (srcSize < skippableSize)
|
|
1648
|
-
return ERROR(srcSize_wrong);
|
|
1649
|
-
}
|
|
1659
|
+
skippableSize = MEM_readLE32((const BYTE*)src + ZSTD_frameIdSize)
|
|
1660
|
+
+ ZSTD_skippableHeaderSize;
|
|
1661
|
+
if (srcSize < skippableSize) return ERROR(srcSize_wrong);
|
|
1650
1662
|
|
|
1651
1663
|
src = (const BYTE *)src + skippableSize;
|
|
1652
1664
|
srcSize -= skippableSize;
|
|
1653
1665
|
continue;
|
|
1654
|
-
} else {
|
|
1655
|
-
return ERROR(prefix_unknown);
|
|
1656
1666
|
}
|
|
1667
|
+
return ERROR(prefix_unknown);
|
|
1657
1668
|
}
|
|
1658
1669
|
|
|
1659
1670
|
if (ddict) {
|
|
1660
1671
|
/* we were called from ZSTD_decompress_usingDDict */
|
|
1661
|
-
|
|
1672
|
+
CHECK_F(ZSTD_decompressBegin_usingDDict(dctx, ddict));
|
|
1662
1673
|
} else {
|
|
1663
1674
|
/* this will initialize correctly with no dict if dict == NULL, so
|
|
1664
1675
|
* use this in all cases but ddict */
|
|
@@ -1669,12 +1680,11 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
|
1669
1680
|
{ const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity,
|
|
1670
1681
|
&src, &srcSize);
|
|
1671
1682
|
if (ZSTD_isError(res)) return res;
|
|
1672
|
-
/*
|
|
1673
|
-
* already */
|
|
1683
|
+
/* no need to bound check, ZSTD_decompressFrame already has */
|
|
1674
1684
|
dst = (BYTE*)dst + res;
|
|
1675
1685
|
dstCapacity -= res;
|
|
1676
1686
|
}
|
|
1677
|
-
}
|
|
1687
|
+
} /* while (srcSize >= ZSTD_frameHeaderSize_prefix) */
|
|
1678
1688
|
|
|
1679
1689
|
if (srcSize) return ERROR(srcSize_wrong); /* input not entirely consumed */
|
|
1680
1690
|
|
|
@@ -1698,7 +1708,7 @@ size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const
|
|
|
1698
1708
|
|
|
1699
1709
|
size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t srcSize)
|
|
1700
1710
|
{
|
|
1701
|
-
#if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE
|
|
1711
|
+
#if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE>=1)
|
|
1702
1712
|
size_t regenSize;
|
|
1703
1713
|
ZSTD_DCtx* const dctx = ZSTD_createDCtx();
|
|
1704
1714
|
if (dctx==NULL) return ERROR(memory_allocation);
|
|
@@ -1722,6 +1732,7 @@ ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
|
|
|
1722
1732
|
switch(dctx->stage)
|
|
1723
1733
|
{
|
|
1724
1734
|
default: /* should not happen */
|
|
1735
|
+
assert(0);
|
|
1725
1736
|
case ZSTDds_getFrameHeaderSize:
|
|
1726
1737
|
case ZSTDds_decodeFrameHeader:
|
|
1727
1738
|
return ZSTDnit_frameHeader;
|
|
@@ -1739,39 +1750,41 @@ ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
|
|
|
1739
1750
|
}
|
|
1740
1751
|
}
|
|
1741
1752
|
|
|
1742
|
-
int ZSTD_isSkipFrame(ZSTD_DCtx* dctx) { return dctx->stage == ZSTDds_skipFrame; }
|
|
1753
|
+
static int ZSTD_isSkipFrame(ZSTD_DCtx* dctx) { return dctx->stage == ZSTDds_skipFrame; }
|
|
1743
1754
|
|
|
1744
1755
|
/** ZSTD_decompressContinue() :
|
|
1745
|
-
*
|
|
1746
|
-
*
|
|
1756
|
+
* srcSize : must be the exact nb of bytes expected (see ZSTD_nextSrcSizeToDecompress())
|
|
1757
|
+
* @return : nb of bytes generated into `dst` (necessarily <= `dstCapacity)
|
|
1758
|
+
* or an error code, which can be tested using ZSTD_isError() */
|
|
1747
1759
|
size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
|
|
1748
1760
|
{
|
|
1761
|
+
DEBUGLOG(5, "ZSTD_decompressContinue");
|
|
1749
1762
|
/* Sanity check */
|
|
1750
|
-
if (srcSize != dctx->expected) return ERROR(srcSize_wrong);
|
|
1763
|
+
if (srcSize != dctx->expected) return ERROR(srcSize_wrong); /* not allowed */
|
|
1751
1764
|
if (dstCapacity) ZSTD_checkContinuity(dctx, dst);
|
|
1752
1765
|
|
|
1753
1766
|
switch (dctx->stage)
|
|
1754
1767
|
{
|
|
1755
1768
|
case ZSTDds_getFrameHeaderSize :
|
|
1756
|
-
|
|
1757
|
-
if (
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1769
|
+
assert(src != NULL);
|
|
1770
|
+
if (dctx->format == ZSTD_f_zstd1) { /* allows header */
|
|
1771
|
+
assert(srcSize >= ZSTD_frameIdSize); /* to read skippable magic number */
|
|
1772
|
+
if ((MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
|
|
1773
|
+
memcpy(dctx->headerBuffer, src, srcSize);
|
|
1774
|
+
dctx->expected = ZSTD_skippableHeaderSize - srcSize; /* remaining to load to get full skippable frame header */
|
|
1775
|
+
dctx->stage = ZSTDds_decodeSkippableHeader;
|
|
1776
|
+
return 0;
|
|
1777
|
+
} }
|
|
1778
|
+
dctx->headerSize = ZSTD_frameHeaderSize_internal(src, srcSize, dctx->format);
|
|
1764
1779
|
if (ZSTD_isError(dctx->headerSize)) return dctx->headerSize;
|
|
1765
|
-
memcpy(dctx->headerBuffer, src,
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
return 0;
|
|
1770
|
-
}
|
|
1771
|
-
dctx->expected = 0; /* not necessary to copy more */
|
|
1780
|
+
memcpy(dctx->headerBuffer, src, srcSize);
|
|
1781
|
+
dctx->expected = dctx->headerSize - srcSize;
|
|
1782
|
+
dctx->stage = ZSTDds_decodeFrameHeader;
|
|
1783
|
+
return 0;
|
|
1772
1784
|
|
|
1773
1785
|
case ZSTDds_decodeFrameHeader:
|
|
1774
|
-
|
|
1786
|
+
assert(src != NULL);
|
|
1787
|
+
memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize);
|
|
1775
1788
|
CHECK_F(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize));
|
|
1776
1789
|
dctx->expected = ZSTD_blockHeaderSize;
|
|
1777
1790
|
dctx->stage = ZSTDds_decodeBlockHeader;
|
|
@@ -1798,18 +1811,21 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
1798
1811
|
dctx->stage = ZSTDds_getFrameHeaderSize;
|
|
1799
1812
|
}
|
|
1800
1813
|
} else {
|
|
1801
|
-
dctx->expected =
|
|
1814
|
+
dctx->expected = ZSTD_blockHeaderSize; /* jump to next header */
|
|
1802
1815
|
dctx->stage = ZSTDds_decodeBlockHeader;
|
|
1803
1816
|
}
|
|
1804
1817
|
return 0;
|
|
1805
1818
|
}
|
|
1819
|
+
|
|
1806
1820
|
case ZSTDds_decompressLastBlock:
|
|
1807
1821
|
case ZSTDds_decompressBlock:
|
|
1822
|
+
DEBUGLOG(5, "case ZSTDds_decompressBlock");
|
|
1808
1823
|
{ size_t rSize;
|
|
1809
1824
|
switch(dctx->bType)
|
|
1810
1825
|
{
|
|
1811
1826
|
case bt_compressed:
|
|
1812
|
-
|
|
1827
|
+
DEBUGLOG(5, "case bt_compressed");
|
|
1828
|
+
rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 1);
|
|
1813
1829
|
break;
|
|
1814
1830
|
case bt_raw :
|
|
1815
1831
|
rSize = ZSTD_copyRawBlock(dst, dstCapacity, src, srcSize);
|
|
@@ -1822,9 +1838,16 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
1822
1838
|
return ERROR(corruption_detected);
|
|
1823
1839
|
}
|
|
1824
1840
|
if (ZSTD_isError(rSize)) return rSize;
|
|
1841
|
+
DEBUGLOG(5, "decoded size from block : %u", (U32)rSize);
|
|
1842
|
+
dctx->decodedSize += rSize;
|
|
1825
1843
|
if (dctx->fParams.checksumFlag) XXH64_update(&dctx->xxhState, dst, rSize);
|
|
1826
1844
|
|
|
1827
1845
|
if (dctx->stage == ZSTDds_decompressLastBlock) { /* end of frame */
|
|
1846
|
+
DEBUGLOG(4, "decoded size from frame : %u", (U32)dctx->decodedSize);
|
|
1847
|
+
if (dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) {
|
|
1848
|
+
if (dctx->decodedSize != dctx->fParams.frameContentSize) {
|
|
1849
|
+
return ERROR(corruption_detected);
|
|
1850
|
+
} }
|
|
1828
1851
|
if (dctx->fParams.checksumFlag) { /* another round for frame checksum */
|
|
1829
1852
|
dctx->expected = 4;
|
|
1830
1853
|
dctx->stage = ZSTDds_checkChecksum;
|
|
@@ -1839,25 +1862,31 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|
|
1839
1862
|
}
|
|
1840
1863
|
return rSize;
|
|
1841
1864
|
}
|
|
1865
|
+
|
|
1842
1866
|
case ZSTDds_checkChecksum:
|
|
1867
|
+
assert(srcSize == 4); /* guaranteed by dctx->expected */
|
|
1843
1868
|
{ U32 const h32 = (U32)XXH64_digest(&dctx->xxhState);
|
|
1844
|
-
U32 const check32 = MEM_readLE32(src);
|
|
1869
|
+
U32 const check32 = MEM_readLE32(src);
|
|
1870
|
+
DEBUGLOG(4, "checksum : calculated %08X :: %08X read", h32, check32);
|
|
1845
1871
|
if (check32 != h32) return ERROR(checksum_wrong);
|
|
1846
1872
|
dctx->expected = 0;
|
|
1847
1873
|
dctx->stage = ZSTDds_getFrameHeaderSize;
|
|
1848
1874
|
return 0;
|
|
1849
1875
|
}
|
|
1876
|
+
|
|
1850
1877
|
case ZSTDds_decodeSkippableHeader:
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1878
|
+
assert(src != NULL);
|
|
1879
|
+
assert(srcSize <= ZSTD_skippableHeaderSize);
|
|
1880
|
+
memcpy(dctx->headerBuffer + (ZSTD_skippableHeaderSize - srcSize), src, srcSize); /* complete skippable header */
|
|
1881
|
+
dctx->expected = MEM_readLE32(dctx->headerBuffer + ZSTD_frameIdSize); /* note : dctx->expected can grow seriously large, beyond local buffer size */
|
|
1882
|
+
dctx->stage = ZSTDds_skipFrame;
|
|
1883
|
+
return 0;
|
|
1884
|
+
|
|
1856
1885
|
case ZSTDds_skipFrame:
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1886
|
+
dctx->expected = 0;
|
|
1887
|
+
dctx->stage = ZSTDds_getFrameHeaderSize;
|
|
1888
|
+
return 0;
|
|
1889
|
+
|
|
1861
1890
|
default:
|
|
1862
1891
|
return ERROR(GENERIC); /* impossible */
|
|
1863
1892
|
}
|
|
@@ -1876,7 +1905,7 @@ static size_t ZSTD_refDictContent(ZSTD_DCtx* dctx, const void* dict, size_t dict
|
|
|
1876
1905
|
/* ZSTD_loadEntropy() :
|
|
1877
1906
|
* dict : must point at beginning of a valid zstd dictionary
|
|
1878
1907
|
* @return : size of entropy tables read */
|
|
1879
|
-
static size_t ZSTD_loadEntropy(
|
|
1908
|
+
static size_t ZSTD_loadEntropy(ZSTD_entropyDTables_t* entropy, const void* const dict, size_t const dictSize)
|
|
1880
1909
|
{
|
|
1881
1910
|
const BYTE* dictPtr = (const BYTE*)dict;
|
|
1882
1911
|
const BYTE* const dictEnd = dictPtr + dictSize;
|
|
@@ -1885,7 +1914,9 @@ static size_t ZSTD_loadEntropy(ZSTD_entropyTables_t* entropy, const void* const
|
|
|
1885
1914
|
dictPtr += 8; /* skip header = magic + dictID */
|
|
1886
1915
|
|
|
1887
1916
|
|
|
1888
|
-
{ size_t const hSize =
|
|
1917
|
+
{ size_t const hSize = HUF_readDTableX4_wksp(
|
|
1918
|
+
entropy->hufTable, dictPtr, dictEnd - dictPtr,
|
|
1919
|
+
entropy->workspace, sizeof(entropy->workspace));
|
|
1889
1920
|
if (HUF_isError(hSize)) return ERROR(dictionary_corrupted);
|
|
1890
1921
|
dictPtr += hSize;
|
|
1891
1922
|
}
|
|
@@ -1933,10 +1964,10 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
|
|
|
1933
1964
|
{
|
|
1934
1965
|
if (dictSize < 8) return ZSTD_refDictContent(dctx, dict, dictSize);
|
|
1935
1966
|
{ U32 const magic = MEM_readLE32(dict);
|
|
1936
|
-
if (magic !=
|
|
1967
|
+
if (magic != ZSTD_MAGIC_DICTIONARY) {
|
|
1937
1968
|
return ZSTD_refDictContent(dctx, dict, dictSize); /* pure content mode */
|
|
1938
1969
|
} }
|
|
1939
|
-
dctx->dictID = MEM_readLE32((const char*)dict +
|
|
1970
|
+
dctx->dictID = MEM_readLE32((const char*)dict + ZSTD_frameIdSize);
|
|
1940
1971
|
|
|
1941
1972
|
/* load entropy tables */
|
|
1942
1973
|
{ size_t const eSize = ZSTD_loadEntropy(&dctx->entropy, dict, dictSize);
|
|
@@ -1950,10 +1981,34 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
|
|
|
1950
1981
|
return ZSTD_refDictContent(dctx, dict, dictSize);
|
|
1951
1982
|
}
|
|
1952
1983
|
|
|
1984
|
+
/* Note : this function cannot fail */
|
|
1985
|
+
size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
|
|
1986
|
+
{
|
|
1987
|
+
assert(dctx != NULL);
|
|
1988
|
+
dctx->expected = ZSTD_startingInputLength(dctx->format); /* dctx->format must be properly set */
|
|
1989
|
+
dctx->stage = ZSTDds_getFrameHeaderSize;
|
|
1990
|
+
dctx->decodedSize = 0;
|
|
1991
|
+
dctx->previousDstEnd = NULL;
|
|
1992
|
+
dctx->base = NULL;
|
|
1993
|
+
dctx->vBase = NULL;
|
|
1994
|
+
dctx->dictEnd = NULL;
|
|
1995
|
+
dctx->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
|
|
1996
|
+
dctx->litEntropy = dctx->fseEntropy = 0;
|
|
1997
|
+
dctx->dictID = 0;
|
|
1998
|
+
ZSTD_STATIC_ASSERT(sizeof(dctx->entropy.rep) == sizeof(repStartValue));
|
|
1999
|
+
memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */
|
|
2000
|
+
dctx->LLTptr = dctx->entropy.LLTable;
|
|
2001
|
+
dctx->MLTptr = dctx->entropy.MLTable;
|
|
2002
|
+
dctx->OFTptr = dctx->entropy.OFTable;
|
|
2003
|
+
dctx->HUFptr = dctx->entropy.hufTable;
|
|
2004
|
+
return 0;
|
|
2005
|
+
}
|
|
2006
|
+
|
|
1953
2007
|
size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
|
|
1954
2008
|
{
|
|
1955
|
-
CHECK_F(ZSTD_decompressBegin(dctx));
|
|
1956
|
-
if (dict && dictSize)
|
|
2009
|
+
CHECK_F( ZSTD_decompressBegin(dctx) );
|
|
2010
|
+
if (dict && dictSize)
|
|
2011
|
+
CHECK_E(ZSTD_decompress_insertDictionary(dctx, dict, dictSize), dictionary_corrupted);
|
|
1957
2012
|
return 0;
|
|
1958
2013
|
}
|
|
1959
2014
|
|
|
@@ -1964,7 +2019,7 @@ struct ZSTD_DDict_s {
|
|
|
1964
2019
|
void* dictBuffer;
|
|
1965
2020
|
const void* dictContent;
|
|
1966
2021
|
size_t dictSize;
|
|
1967
|
-
|
|
2022
|
+
ZSTD_entropyDTables_t entropy;
|
|
1968
2023
|
U32 dictID;
|
|
1969
2024
|
U32 entropyPresent;
|
|
1970
2025
|
ZSTD_customMem cMem;
|
|
@@ -1980,10 +2035,10 @@ static size_t ZSTD_DDictDictSize(const ZSTD_DDict* ddict)
|
|
|
1980
2035
|
return ddict->dictSize;
|
|
1981
2036
|
}
|
|
1982
2037
|
|
|
1983
|
-
|
|
2038
|
+
size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dstDCtx, const ZSTD_DDict* ddict)
|
|
1984
2039
|
{
|
|
1985
|
-
ZSTD_decompressBegin(dstDCtx);
|
|
1986
|
-
if (ddict) { /* support
|
|
2040
|
+
CHECK_F( ZSTD_decompressBegin(dstDCtx) );
|
|
2041
|
+
if (ddict) { /* support begin on NULL */
|
|
1987
2042
|
dstDCtx->dictID = ddict->dictID;
|
|
1988
2043
|
dstDCtx->base = ddict->dictContent;
|
|
1989
2044
|
dstDCtx->vBase = ddict->dictContent;
|
|
@@ -2004,6 +2059,7 @@ static void ZSTD_refDDict(ZSTD_DCtx* dstDCtx, const ZSTD_DDict* ddict)
|
|
|
2004
2059
|
dstDCtx->fseEntropy = 0;
|
|
2005
2060
|
}
|
|
2006
2061
|
}
|
|
2062
|
+
return 0;
|
|
2007
2063
|
}
|
|
2008
2064
|
|
|
2009
2065
|
static size_t ZSTD_loadEntropy_inDDict(ZSTD_DDict* ddict)
|
|
@@ -2012,9 +2068,9 @@ static size_t ZSTD_loadEntropy_inDDict(ZSTD_DDict* ddict)
|
|
|
2012
2068
|
ddict->entropyPresent = 0;
|
|
2013
2069
|
if (ddict->dictSize < 8) return 0;
|
|
2014
2070
|
{ U32 const magic = MEM_readLE32(ddict->dictContent);
|
|
2015
|
-
if (magic !=
|
|
2071
|
+
if (magic != ZSTD_MAGIC_DICTIONARY) return 0; /* pure content mode */
|
|
2016
2072
|
}
|
|
2017
|
-
ddict->dictID = MEM_readLE32((const char*)ddict->dictContent +
|
|
2073
|
+
ddict->dictID = MEM_readLE32((const char*)ddict->dictContent + ZSTD_frameIdSize);
|
|
2018
2074
|
|
|
2019
2075
|
/* load entropy tables */
|
|
2020
2076
|
CHECK_E( ZSTD_loadEntropy(&ddict->entropy, ddict->dictContent, ddict->dictSize), dictionary_corrupted );
|
|
@@ -2023,33 +2079,39 @@ static size_t ZSTD_loadEntropy_inDDict(ZSTD_DDict* ddict)
|
|
|
2023
2079
|
}
|
|
2024
2080
|
|
|
2025
2081
|
|
|
2026
|
-
ZSTD_DDict*
|
|
2082
|
+
static size_t ZSTD_initDDict_internal(ZSTD_DDict* ddict, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod)
|
|
2083
|
+
{
|
|
2084
|
+
if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dict) || (!dictSize)) {
|
|
2085
|
+
ddict->dictBuffer = NULL;
|
|
2086
|
+
ddict->dictContent = dict;
|
|
2087
|
+
} else {
|
|
2088
|
+
void* const internalBuffer = ZSTD_malloc(dictSize, ddict->cMem);
|
|
2089
|
+
ddict->dictBuffer = internalBuffer;
|
|
2090
|
+
ddict->dictContent = internalBuffer;
|
|
2091
|
+
if (!internalBuffer) return ERROR(memory_allocation);
|
|
2092
|
+
memcpy(internalBuffer, dict, dictSize);
|
|
2093
|
+
}
|
|
2094
|
+
ddict->dictSize = dictSize;
|
|
2095
|
+
ddict->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
|
|
2096
|
+
|
|
2097
|
+
/* parse dictionary content */
|
|
2098
|
+
CHECK_F( ZSTD_loadEntropy_inDDict(ddict) );
|
|
2099
|
+
|
|
2100
|
+
return 0;
|
|
2101
|
+
}
|
|
2102
|
+
|
|
2103
|
+
ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_customMem customMem)
|
|
2027
2104
|
{
|
|
2028
|
-
if (!customMem.customAlloc
|
|
2029
|
-
if (!customMem.customAlloc || !customMem.customFree) return NULL;
|
|
2105
|
+
if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
|
|
2030
2106
|
|
|
2031
2107
|
{ ZSTD_DDict* const ddict = (ZSTD_DDict*) ZSTD_malloc(sizeof(ZSTD_DDict), customMem);
|
|
2032
2108
|
if (!ddict) return NULL;
|
|
2033
2109
|
ddict->cMem = customMem;
|
|
2034
2110
|
|
|
2035
|
-
if ((
|
|
2036
|
-
ddict
|
|
2037
|
-
|
|
2038
|
-
} else {
|
|
2039
|
-
void* const internalBuffer = ZSTD_malloc(dictSize, customMem);
|
|
2040
|
-
if (!internalBuffer) { ZSTD_freeDDict(ddict); return NULL; }
|
|
2041
|
-
memcpy(internalBuffer, dict, dictSize);
|
|
2042
|
-
ddict->dictBuffer = internalBuffer;
|
|
2043
|
-
ddict->dictContent = internalBuffer;
|
|
2111
|
+
if (ZSTD_isError( ZSTD_initDDict_internal(ddict, dict, dictSize, dictLoadMethod) )) {
|
|
2112
|
+
ZSTD_freeDDict(ddict);
|
|
2113
|
+
return NULL;
|
|
2044
2114
|
}
|
|
2045
|
-
ddict->dictSize = dictSize;
|
|
2046
|
-
ddict->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
|
|
2047
|
-
/* parse dictionary content */
|
|
2048
|
-
{ size_t const errorCode = ZSTD_loadEntropy_inDDict(ddict);
|
|
2049
|
-
if (ZSTD_isError(errorCode)) {
|
|
2050
|
-
ZSTD_freeDDict(ddict);
|
|
2051
|
-
return NULL;
|
|
2052
|
-
} }
|
|
2053
2115
|
|
|
2054
2116
|
return ddict;
|
|
2055
2117
|
}
|
|
@@ -2062,10 +2124,9 @@ ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize, unsigne
|
|
|
2062
2124
|
ZSTD_DDict* ZSTD_createDDict(const void* dict, size_t dictSize)
|
|
2063
2125
|
{
|
|
2064
2126
|
ZSTD_customMem const allocator = { NULL, NULL, NULL };
|
|
2065
|
-
return ZSTD_createDDict_advanced(dict, dictSize,
|
|
2127
|
+
return ZSTD_createDDict_advanced(dict, dictSize, ZSTD_dlm_byCopy, allocator);
|
|
2066
2128
|
}
|
|
2067
2129
|
|
|
2068
|
-
|
|
2069
2130
|
/*! ZSTD_createDDict_byReference() :
|
|
2070
2131
|
* Create a digested dictionary, to start decompression without startup delay.
|
|
2071
2132
|
* Dictionary content is simply referenced, it will be accessed during decompression.
|
|
@@ -2073,7 +2134,28 @@ ZSTD_DDict* ZSTD_createDDict(const void* dict, size_t dictSize)
|
|
|
2073
2134
|
ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize)
|
|
2074
2135
|
{
|
|
2075
2136
|
ZSTD_customMem const allocator = { NULL, NULL, NULL };
|
|
2076
|
-
return ZSTD_createDDict_advanced(dictBuffer, dictSize,
|
|
2137
|
+
return ZSTD_createDDict_advanced(dictBuffer, dictSize, ZSTD_dlm_byRef, allocator);
|
|
2138
|
+
}
|
|
2139
|
+
|
|
2140
|
+
|
|
2141
|
+
ZSTD_DDict* ZSTD_initStaticDDict(void* workspace, size_t workspaceSize,
|
|
2142
|
+
const void* dict, size_t dictSize,
|
|
2143
|
+
ZSTD_dictLoadMethod_e dictLoadMethod)
|
|
2144
|
+
{
|
|
2145
|
+
size_t const neededSpace =
|
|
2146
|
+
sizeof(ZSTD_DDict) + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize);
|
|
2147
|
+
ZSTD_DDict* const ddict = (ZSTD_DDict*)workspace;
|
|
2148
|
+
assert(workspace != NULL);
|
|
2149
|
+
assert(dict != NULL);
|
|
2150
|
+
if ((size_t)workspace & 7) return NULL; /* 8-aligned */
|
|
2151
|
+
if (workspaceSize < neededSpace) return NULL;
|
|
2152
|
+
if (dictLoadMethod == ZSTD_dlm_byCopy) {
|
|
2153
|
+
memcpy(ddict+1, dict, dictSize); /* local copy */
|
|
2154
|
+
dict = ddict+1;
|
|
2155
|
+
}
|
|
2156
|
+
if (ZSTD_isError( ZSTD_initDDict_internal(ddict, dict, dictSize, ZSTD_dlm_byRef) ))
|
|
2157
|
+
return NULL;
|
|
2158
|
+
return ddict;
|
|
2077
2159
|
}
|
|
2078
2160
|
|
|
2079
2161
|
|
|
@@ -2087,6 +2169,14 @@ size_t ZSTD_freeDDict(ZSTD_DDict* ddict)
|
|
|
2087
2169
|
}
|
|
2088
2170
|
}
|
|
2089
2171
|
|
|
2172
|
+
/*! ZSTD_estimateDDictSize() :
|
|
2173
|
+
* Estimate amount of memory that will be needed to create a dictionary for decompression.
|
|
2174
|
+
* Note : dictionary created by reference using ZSTD_dlm_byRef are smaller */
|
|
2175
|
+
size_t ZSTD_estimateDDictSize(size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod)
|
|
2176
|
+
{
|
|
2177
|
+
return sizeof(ZSTD_DDict) + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize);
|
|
2178
|
+
}
|
|
2179
|
+
|
|
2090
2180
|
size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict)
|
|
2091
2181
|
{
|
|
2092
2182
|
if (ddict==NULL) return 0; /* support sizeof on NULL */
|
|
@@ -2100,8 +2190,8 @@ size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict)
|
|
|
2100
2190
|
unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize)
|
|
2101
2191
|
{
|
|
2102
2192
|
if (dictSize < 8) return 0;
|
|
2103
|
-
if (MEM_readLE32(dict) !=
|
|
2104
|
-
return MEM_readLE32((const char*)dict +
|
|
2193
|
+
if (MEM_readLE32(dict) != ZSTD_MAGIC_DICTIONARY) return 0;
|
|
2194
|
+
return MEM_readLE32((const char*)dict + ZSTD_frameIdSize);
|
|
2105
2195
|
}
|
|
2106
2196
|
|
|
2107
2197
|
/*! ZSTD_getDictID_fromDDict() :
|
|
@@ -2115,19 +2205,22 @@ unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict)
|
|
|
2115
2205
|
}
|
|
2116
2206
|
|
|
2117
2207
|
/*! ZSTD_getDictID_fromFrame() :
|
|
2118
|
-
* Provides the dictID required to
|
|
2208
|
+
* Provides the dictID required to decompresse frame stored within `src`.
|
|
2119
2209
|
* If @return == 0, the dictID could not be decoded.
|
|
2120
2210
|
* This could for one of the following reasons :
|
|
2121
|
-
* - The frame does not require a dictionary
|
|
2122
|
-
* - The frame was built with dictID intentionally removed.
|
|
2211
|
+
* - The frame does not require a dictionary (most common case).
|
|
2212
|
+
* - The frame was built with dictID intentionally removed.
|
|
2213
|
+
* Needed dictionary is a hidden information.
|
|
2123
2214
|
* Note : this use case also happens when using a non-conformant dictionary.
|
|
2124
|
-
* - `srcSize` is too small, and as a result,
|
|
2215
|
+
* - `srcSize` is too small, and as a result, frame header could not be decoded.
|
|
2216
|
+
* Note : possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`.
|
|
2125
2217
|
* - This is not a Zstandard frame.
|
|
2126
|
-
* When identifying the exact failure cause, it's possible to
|
|
2218
|
+
* When identifying the exact failure cause, it's possible to use
|
|
2219
|
+
* ZSTD_getFrameHeader(), which will provide a more precise error code. */
|
|
2127
2220
|
unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize)
|
|
2128
2221
|
{
|
|
2129
|
-
|
|
2130
|
-
size_t const hError =
|
|
2222
|
+
ZSTD_frameHeader zfp = { 0, 0, 0, ZSTD_frame, 0, 0, 0 };
|
|
2223
|
+
size_t const hError = ZSTD_getFrameHeader(&zfp, src, srcSize);
|
|
2131
2224
|
if (ZSTD_isError(hError)) return 0;
|
|
2132
2225
|
return zfp.dictID;
|
|
2133
2226
|
}
|
|
@@ -2152,84 +2245,35 @@ size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
|
|
|
2152
2245
|
* Streaming decompression
|
|
2153
2246
|
*====================================*/
|
|
2154
2247
|
|
|
2155
|
-
typedef enum { zdss_init, zdss_loadHeader,
|
|
2156
|
-
zdss_read, zdss_load, zdss_flush } ZSTD_dStreamStage;
|
|
2157
|
-
|
|
2158
|
-
/* *** Resource management *** */
|
|
2159
|
-
struct ZSTD_DStream_s {
|
|
2160
|
-
ZSTD_DCtx* dctx;
|
|
2161
|
-
ZSTD_DDict* ddictLocal;
|
|
2162
|
-
const ZSTD_DDict* ddict;
|
|
2163
|
-
ZSTD_frameParams fParams;
|
|
2164
|
-
ZSTD_dStreamStage stage;
|
|
2165
|
-
char* inBuff;
|
|
2166
|
-
size_t inBuffSize;
|
|
2167
|
-
size_t inPos;
|
|
2168
|
-
size_t maxWindowSize;
|
|
2169
|
-
char* outBuff;
|
|
2170
|
-
size_t outBuffSize;
|
|
2171
|
-
size_t outStart;
|
|
2172
|
-
size_t outEnd;
|
|
2173
|
-
size_t blockSize;
|
|
2174
|
-
BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX]; /* tmp buffer to store frame header */
|
|
2175
|
-
size_t lhSize;
|
|
2176
|
-
ZSTD_customMem customMem;
|
|
2177
|
-
void* legacyContext;
|
|
2178
|
-
U32 previousLegacyVersion;
|
|
2179
|
-
U32 legacyVersion;
|
|
2180
|
-
U32 hostageByte;
|
|
2181
|
-
}; /* typedef'd to ZSTD_DStream within "zstd.h" */
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
2248
|
ZSTD_DStream* ZSTD_createDStream(void)
|
|
2185
2249
|
{
|
|
2186
|
-
return ZSTD_createDStream_advanced(
|
|
2250
|
+
return ZSTD_createDStream_advanced(ZSTD_defaultCMem);
|
|
2187
2251
|
}
|
|
2188
2252
|
|
|
2189
|
-
ZSTD_DStream*
|
|
2253
|
+
ZSTD_DStream* ZSTD_initStaticDStream(void *workspace, size_t workspaceSize)
|
|
2190
2254
|
{
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
if (!customMem.customAlloc && !customMem.customFree) customMem = defaultCustomMem;
|
|
2194
|
-
if (!customMem.customAlloc || !customMem.customFree) return NULL;
|
|
2255
|
+
return ZSTD_initStaticDCtx(workspace, workspaceSize);
|
|
2256
|
+
}
|
|
2195
2257
|
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
memcpy(&zds->customMem, &customMem, sizeof(ZSTD_customMem));
|
|
2200
|
-
zds->dctx = ZSTD_createDCtx_advanced(customMem);
|
|
2201
|
-
if (zds->dctx == NULL) { ZSTD_freeDStream(zds); return NULL; }
|
|
2202
|
-
zds->stage = zdss_init;
|
|
2203
|
-
zds->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
|
|
2204
|
-
return zds;
|
|
2258
|
+
ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem)
|
|
2259
|
+
{
|
|
2260
|
+
return ZSTD_createDCtx_advanced(customMem);
|
|
2205
2261
|
}
|
|
2206
2262
|
|
|
2207
2263
|
size_t ZSTD_freeDStream(ZSTD_DStream* zds)
|
|
2208
2264
|
{
|
|
2209
|
-
|
|
2210
|
-
{ ZSTD_customMem const cMem = zds->customMem;
|
|
2211
|
-
ZSTD_freeDCtx(zds->dctx);
|
|
2212
|
-
ZSTD_freeDDict(zds->ddictLocal);
|
|
2213
|
-
ZSTD_free(zds->inBuff, cMem);
|
|
2214
|
-
ZSTD_free(zds->outBuff, cMem);
|
|
2215
|
-
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
|
|
2216
|
-
if (zds->legacyContext)
|
|
2217
|
-
ZSTD_freeLegacyStreamContext(zds->legacyContext, zds->previousLegacyVersion);
|
|
2218
|
-
#endif
|
|
2219
|
-
ZSTD_free(zds, cMem);
|
|
2220
|
-
return 0;
|
|
2221
|
-
}
|
|
2265
|
+
return ZSTD_freeDCtx(zds);
|
|
2222
2266
|
}
|
|
2223
2267
|
|
|
2224
2268
|
|
|
2225
2269
|
/* *** Initialization *** */
|
|
2226
2270
|
|
|
2227
|
-
size_t ZSTD_DStreamInSize(void) { return
|
|
2228
|
-
size_t ZSTD_DStreamOutSize(void) { return
|
|
2271
|
+
size_t ZSTD_DStreamInSize(void) { return ZSTD_BLOCKSIZE_MAX + ZSTD_blockHeaderSize; }
|
|
2272
|
+
size_t ZSTD_DStreamOutSize(void) { return ZSTD_BLOCKSIZE_MAX; }
|
|
2229
2273
|
|
|
2230
2274
|
size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize)
|
|
2231
2275
|
{
|
|
2232
|
-
zds->
|
|
2276
|
+
zds->streamStage = zdss_loadHeader;
|
|
2233
2277
|
zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
|
|
2234
2278
|
ZSTD_freeDDict(zds->ddictLocal);
|
|
2235
2279
|
if (dict && dictSize >= 8) {
|
|
@@ -2242,12 +2286,16 @@ size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t di
|
|
|
2242
2286
|
return ZSTD_frameHeaderSize_prefix;
|
|
2243
2287
|
}
|
|
2244
2288
|
|
|
2289
|
+
/* note : this variant can't fail */
|
|
2245
2290
|
size_t ZSTD_initDStream(ZSTD_DStream* zds)
|
|
2246
2291
|
{
|
|
2247
2292
|
return ZSTD_initDStream_usingDict(zds, NULL, 0);
|
|
2248
2293
|
}
|
|
2249
2294
|
|
|
2250
|
-
|
|
2295
|
+
/* ZSTD_initDStream_usingDDict() :
|
|
2296
|
+
* ddict will just be referenced, and must outlive decompression session
|
|
2297
|
+
* this function cannot fail */
|
|
2298
|
+
size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict)
|
|
2251
2299
|
{
|
|
2252
2300
|
size_t const initResult = ZSTD_initDStream(zds);
|
|
2253
2301
|
zds->ddict = ddict;
|
|
@@ -2256,7 +2304,7 @@ size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict)
|
|
|
2256
2304
|
|
|
2257
2305
|
size_t ZSTD_resetDStream(ZSTD_DStream* zds)
|
|
2258
2306
|
{
|
|
2259
|
-
zds->
|
|
2307
|
+
zds->streamStage = zdss_loadHeader;
|
|
2260
2308
|
zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
|
|
2261
2309
|
zds->legacyVersion = 0;
|
|
2262
2310
|
zds->hostageByte = 0;
|
|
@@ -2266,19 +2314,73 @@ size_t ZSTD_resetDStream(ZSTD_DStream* zds)
|
|
|
2266
2314
|
size_t ZSTD_setDStreamParameter(ZSTD_DStream* zds,
|
|
2267
2315
|
ZSTD_DStreamParameter_e paramType, unsigned paramValue)
|
|
2268
2316
|
{
|
|
2317
|
+
ZSTD_STATIC_ASSERT((unsigned)zdss_loadHeader >= (unsigned)zdss_init);
|
|
2318
|
+
if ((unsigned)zds->streamStage > (unsigned)zdss_loadHeader)
|
|
2319
|
+
return ERROR(stage_wrong);
|
|
2269
2320
|
switch(paramType)
|
|
2270
2321
|
{
|
|
2271
|
-
default : return ERROR(
|
|
2272
|
-
case DStream_p_maxWindowSize :
|
|
2322
|
+
default : return ERROR(parameter_unsupported);
|
|
2323
|
+
case DStream_p_maxWindowSize :
|
|
2324
|
+
DEBUGLOG(4, "setting maxWindowSize = %u KB", paramValue >> 10);
|
|
2325
|
+
zds->maxWindowSize = paramValue ? paramValue : (U32)(-1);
|
|
2326
|
+
break;
|
|
2273
2327
|
}
|
|
2274
2328
|
return 0;
|
|
2275
2329
|
}
|
|
2276
2330
|
|
|
2331
|
+
size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize)
|
|
2332
|
+
{
|
|
2333
|
+
ZSTD_STATIC_ASSERT((unsigned)zdss_loadHeader >= (unsigned)zdss_init);
|
|
2334
|
+
if ((unsigned)dctx->streamStage > (unsigned)zdss_loadHeader)
|
|
2335
|
+
return ERROR(stage_wrong);
|
|
2336
|
+
dctx->maxWindowSize = maxWindowSize;
|
|
2337
|
+
return 0;
|
|
2338
|
+
}
|
|
2339
|
+
|
|
2340
|
+
size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format)
|
|
2341
|
+
{
|
|
2342
|
+
DEBUGLOG(4, "ZSTD_DCtx_setFormat : %u", (unsigned)format);
|
|
2343
|
+
ZSTD_STATIC_ASSERT((unsigned)zdss_loadHeader >= (unsigned)zdss_init);
|
|
2344
|
+
if ((unsigned)dctx->streamStage > (unsigned)zdss_loadHeader)
|
|
2345
|
+
return ERROR(stage_wrong);
|
|
2346
|
+
dctx->format = format;
|
|
2347
|
+
return 0;
|
|
2348
|
+
}
|
|
2349
|
+
|
|
2277
2350
|
|
|
2278
2351
|
size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds)
|
|
2279
2352
|
{
|
|
2280
|
-
|
|
2281
|
-
|
|
2353
|
+
return ZSTD_sizeof_DCtx(zds);
|
|
2354
|
+
}
|
|
2355
|
+
|
|
2356
|
+
size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize)
|
|
2357
|
+
{
|
|
2358
|
+
size_t const blockSize = (size_t) MIN(windowSize, ZSTD_BLOCKSIZE_MAX);
|
|
2359
|
+
unsigned long long const neededRBSize = windowSize + blockSize + (WILDCOPY_OVERLENGTH * 2);
|
|
2360
|
+
unsigned long long const neededSize = MIN(frameContentSize, neededRBSize);
|
|
2361
|
+
size_t const minRBSize = (size_t) neededSize;
|
|
2362
|
+
if ((unsigned long long)minRBSize != neededSize) return ERROR(frameParameter_windowTooLarge);
|
|
2363
|
+
return minRBSize;
|
|
2364
|
+
}
|
|
2365
|
+
|
|
2366
|
+
size_t ZSTD_estimateDStreamSize(size_t windowSize)
|
|
2367
|
+
{
|
|
2368
|
+
size_t const blockSize = MIN(windowSize, ZSTD_BLOCKSIZE_MAX);
|
|
2369
|
+
size_t const inBuffSize = blockSize; /* no block can be larger */
|
|
2370
|
+
size_t const outBuffSize = ZSTD_decodingBufferSize_min(windowSize, ZSTD_CONTENTSIZE_UNKNOWN);
|
|
2371
|
+
return ZSTD_estimateDCtxSize() + inBuffSize + outBuffSize;
|
|
2372
|
+
}
|
|
2373
|
+
|
|
2374
|
+
size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize)
|
|
2375
|
+
{
|
|
2376
|
+
U32 const windowSizeMax = 1U << ZSTD_WINDOWLOG_MAX; /* note : should be user-selectable */
|
|
2377
|
+
ZSTD_frameHeader zfh;
|
|
2378
|
+
size_t const err = ZSTD_getFrameHeader(&zfh, src, srcSize);
|
|
2379
|
+
if (ZSTD_isError(err)) return err;
|
|
2380
|
+
if (err>0) return ERROR(srcSize_wrong);
|
|
2381
|
+
if (zfh.windowSize > windowSizeMax)
|
|
2382
|
+
return ERROR(frameParameter_windowTooLarge);
|
|
2383
|
+
return ZSTD_estimateDStreamSize((size_t)zfh.windowSize);
|
|
2282
2384
|
}
|
|
2283
2385
|
|
|
2284
2386
|
|
|
@@ -2302,44 +2404,68 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
2302
2404
|
char* op = ostart;
|
|
2303
2405
|
U32 someMoreWork = 1;
|
|
2304
2406
|
|
|
2407
|
+
DEBUGLOG(5, "ZSTD_decompressStream");
|
|
2408
|
+
if (input->pos > input->size) { /* forbidden */
|
|
2409
|
+
DEBUGLOG(5, "in: pos: %u vs size: %u",
|
|
2410
|
+
(U32)input->pos, (U32)input->size);
|
|
2411
|
+
return ERROR(srcSize_wrong);
|
|
2412
|
+
}
|
|
2413
|
+
if (output->pos > output->size) { /* forbidden */
|
|
2414
|
+
DEBUGLOG(5, "out: pos: %u vs size: %u",
|
|
2415
|
+
(U32)output->pos, (U32)output->size);
|
|
2416
|
+
return ERROR(dstSize_tooSmall);
|
|
2417
|
+
}
|
|
2418
|
+
DEBUGLOG(5, "input size : %u", (U32)(input->size - input->pos));
|
|
2419
|
+
|
|
2305
2420
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
|
2306
|
-
if (zds->legacyVersion)
|
|
2421
|
+
if (zds->legacyVersion) {
|
|
2422
|
+
/* legacy support is incompatible with static dctx */
|
|
2423
|
+
if (zds->staticSize) return ERROR(memory_allocation);
|
|
2307
2424
|
return ZSTD_decompressLegacyStream(zds->legacyContext, zds->legacyVersion, output, input);
|
|
2425
|
+
}
|
|
2308
2426
|
#endif
|
|
2309
2427
|
|
|
2310
2428
|
while (someMoreWork) {
|
|
2311
|
-
switch(zds->
|
|
2429
|
+
switch(zds->streamStage)
|
|
2312
2430
|
{
|
|
2313
2431
|
case zdss_init :
|
|
2314
2432
|
ZSTD_resetDStream(zds); /* transparent reset on starting decoding a new frame */
|
|
2315
2433
|
/* fall-through */
|
|
2316
2434
|
|
|
2317
2435
|
case zdss_loadHeader :
|
|
2318
|
-
|
|
2319
|
-
|
|
2436
|
+
DEBUGLOG(5, "stage zdss_loadHeader (srcSize : %u)", (U32)(iend - ip));
|
|
2437
|
+
{ size_t const hSize = ZSTD_getFrameHeader_internal(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format);
|
|
2438
|
+
DEBUGLOG(5, "header size : %u", (U32)hSize);
|
|
2439
|
+
if (ZSTD_isError(hSize)) {
|
|
2320
2440
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
|
2321
|
-
|
|
2441
|
+
U32 const legacyVersion = ZSTD_isLegacy(istart, iend-istart);
|
|
2322
2442
|
if (legacyVersion) {
|
|
2323
2443
|
const void* const dict = zds->ddict ? zds->ddict->dictContent : NULL;
|
|
2324
2444
|
size_t const dictSize = zds->ddict ? zds->ddict->dictSize : 0;
|
|
2325
|
-
|
|
2326
|
-
|
|
2445
|
+
/* legacy support is incompatible with static dctx */
|
|
2446
|
+
if (zds->staticSize) return ERROR(memory_allocation);
|
|
2447
|
+
CHECK_F(ZSTD_initLegacyStream(&zds->legacyContext,
|
|
2448
|
+
zds->previousLegacyVersion, legacyVersion,
|
|
2449
|
+
dict, dictSize));
|
|
2327
2450
|
zds->legacyVersion = zds->previousLegacyVersion = legacyVersion;
|
|
2328
|
-
return ZSTD_decompressLegacyStream(zds->legacyContext,
|
|
2329
|
-
}
|
|
2330
|
-
return hSize; /* error */
|
|
2331
|
-
} }
|
|
2332
|
-
#else
|
|
2333
|
-
return hSize;
|
|
2451
|
+
return ZSTD_decompressLegacyStream(zds->legacyContext, legacyVersion, output, input);
|
|
2452
|
+
}
|
|
2334
2453
|
#endif
|
|
2454
|
+
return hSize; /* error */
|
|
2455
|
+
}
|
|
2335
2456
|
if (hSize != 0) { /* need more input */
|
|
2336
2457
|
size_t const toLoad = hSize - zds->lhSize; /* if hSize!=0, hSize > zds->lhSize */
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2458
|
+
size_t const remainingInput = (size_t)(iend-ip);
|
|
2459
|
+
assert(iend >= ip);
|
|
2460
|
+
if (toLoad > remainingInput) { /* not enough input to load full header */
|
|
2461
|
+
if (remainingInput > 0) {
|
|
2462
|
+
memcpy(zds->headerBuffer + zds->lhSize, ip, remainingInput);
|
|
2463
|
+
zds->lhSize += remainingInput;
|
|
2464
|
+
}
|
|
2340
2465
|
input->pos = input->size;
|
|
2341
2466
|
return (MAX(ZSTD_frameHeaderSize_min, hSize) - zds->lhSize) + ZSTD_blockHeaderSize; /* remaining header bytes + next block header */
|
|
2342
2467
|
}
|
|
2468
|
+
assert(ip != NULL);
|
|
2343
2469
|
memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad); zds->lhSize = hSize; ip += toLoad;
|
|
2344
2470
|
break;
|
|
2345
2471
|
} }
|
|
@@ -2349,132 +2475,191 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
2349
2475
|
&& (U64)(size_t)(oend-op) >= zds->fParams.frameContentSize) {
|
|
2350
2476
|
size_t const cSize = ZSTD_findFrameCompressedSize(istart, iend-istart);
|
|
2351
2477
|
if (cSize <= (size_t)(iend-istart)) {
|
|
2352
|
-
|
|
2478
|
+
/* shortcut : using single-pass mode */
|
|
2479
|
+
size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, oend-op, istart, cSize, zds->ddict);
|
|
2353
2480
|
if (ZSTD_isError(decompressedSize)) return decompressedSize;
|
|
2481
|
+
DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()")
|
|
2354
2482
|
ip = istart + cSize;
|
|
2355
2483
|
op += decompressedSize;
|
|
2356
|
-
zds->
|
|
2357
|
-
zds->
|
|
2484
|
+
zds->expected = 0;
|
|
2485
|
+
zds->streamStage = zdss_init;
|
|
2358
2486
|
someMoreWork = 0;
|
|
2359
2487
|
break;
|
|
2360
2488
|
} }
|
|
2361
2489
|
|
|
2362
|
-
/* Consume header */
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
CHECK_F(ZSTD_decompressContinue(zds->dctx, NULL, 0, zds->headerBuffer, h1Size));
|
|
2366
|
-
{ size_t const h2Size = ZSTD_nextSrcSizeToDecompress(zds->dctx);
|
|
2367
|
-
CHECK_F(ZSTD_decompressContinue(zds->dctx, NULL, 0, zds->headerBuffer+h1Size, h2Size));
|
|
2368
|
-
} }
|
|
2490
|
+
/* Consume header (see ZSTDds_decodeFrameHeader) */
|
|
2491
|
+
DEBUGLOG(4, "Consume header");
|
|
2492
|
+
CHECK_F(ZSTD_decompressBegin_usingDDict(zds, zds->ddict));
|
|
2369
2493
|
|
|
2494
|
+
if ((MEM_readLE32(zds->headerBuffer) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
|
|
2495
|
+
zds->expected = MEM_readLE32(zds->headerBuffer + ZSTD_frameIdSize);
|
|
2496
|
+
zds->stage = ZSTDds_skipFrame;
|
|
2497
|
+
} else {
|
|
2498
|
+
CHECK_F(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize));
|
|
2499
|
+
zds->expected = ZSTD_blockHeaderSize;
|
|
2500
|
+
zds->stage = ZSTDds_decodeBlockHeader;
|
|
2501
|
+
}
|
|
2502
|
+
|
|
2503
|
+
/* control buffer memory usage */
|
|
2504
|
+
DEBUGLOG(4, "Control max memory usage (%u KB <= max %u KB)",
|
|
2505
|
+
(U32)(zds->fParams.windowSize >>10),
|
|
2506
|
+
(U32)(zds->maxWindowSize >> 10) );
|
|
2370
2507
|
zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN);
|
|
2371
2508
|
if (zds->fParams.windowSize > zds->maxWindowSize) return ERROR(frameParameter_windowTooLarge);
|
|
2372
2509
|
|
|
2373
2510
|
/* Adapt buffer sizes to frame header instructions */
|
|
2374
|
-
{ size_t const
|
|
2375
|
-
size_t const
|
|
2376
|
-
zds->
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2511
|
+
{ size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */);
|
|
2512
|
+
size_t const neededOutBuffSize = ZSTD_decodingBufferSize_min(zds->fParams.windowSize, zds->fParams.frameContentSize);
|
|
2513
|
+
if ((zds->inBuffSize < neededInBuffSize) || (zds->outBuffSize < neededOutBuffSize)) {
|
|
2514
|
+
size_t const bufferSize = neededInBuffSize + neededOutBuffSize;
|
|
2515
|
+
DEBUGLOG(4, "inBuff : from %u to %u",
|
|
2516
|
+
(U32)zds->inBuffSize, (U32)neededInBuffSize);
|
|
2517
|
+
DEBUGLOG(4, "outBuff : from %u to %u",
|
|
2518
|
+
(U32)zds->outBuffSize, (U32)neededOutBuffSize);
|
|
2519
|
+
if (zds->staticSize) { /* static DCtx */
|
|
2520
|
+
DEBUGLOG(4, "staticSize : %u", (U32)zds->staticSize);
|
|
2521
|
+
assert(zds->staticSize >= sizeof(ZSTD_DCtx)); /* controlled at init */
|
|
2522
|
+
if (bufferSize > zds->staticSize - sizeof(ZSTD_DCtx))
|
|
2523
|
+
return ERROR(memory_allocation);
|
|
2524
|
+
} else {
|
|
2525
|
+
ZSTD_free(zds->inBuff, zds->customMem);
|
|
2526
|
+
zds->inBuffSize = 0;
|
|
2527
|
+
zds->outBuffSize = 0;
|
|
2528
|
+
zds->inBuff = (char*)ZSTD_malloc(bufferSize, zds->customMem);
|
|
2529
|
+
if (zds->inBuff == NULL) return ERROR(memory_allocation);
|
|
2530
|
+
}
|
|
2531
|
+
zds->inBuffSize = neededInBuffSize;
|
|
2532
|
+
zds->outBuff = zds->inBuff + zds->inBuffSize;
|
|
2533
|
+
zds->outBuffSize = neededOutBuffSize;
|
|
2388
2534
|
} }
|
|
2389
|
-
zds->
|
|
2390
|
-
/*
|
|
2535
|
+
zds->streamStage = zdss_read;
|
|
2536
|
+
/* fall-through */
|
|
2391
2537
|
|
|
2392
2538
|
case zdss_read:
|
|
2393
|
-
|
|
2539
|
+
DEBUGLOG(5, "stage zdss_read");
|
|
2540
|
+
{ size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds);
|
|
2541
|
+
DEBUGLOG(5, "neededInSize = %u", (U32)neededInSize);
|
|
2394
2542
|
if (neededInSize==0) { /* end of frame */
|
|
2395
|
-
zds->
|
|
2543
|
+
zds->streamStage = zdss_init;
|
|
2396
2544
|
someMoreWork = 0;
|
|
2397
2545
|
break;
|
|
2398
2546
|
}
|
|
2399
2547
|
if ((size_t)(iend-ip) >= neededInSize) { /* decode directly from src */
|
|
2400
|
-
const
|
|
2401
|
-
size_t const decodedSize = ZSTD_decompressContinue(zds
|
|
2548
|
+
int const isSkipFrame = ZSTD_isSkipFrame(zds);
|
|
2549
|
+
size_t const decodedSize = ZSTD_decompressContinue(zds,
|
|
2402
2550
|
zds->outBuff + zds->outStart, (isSkipFrame ? 0 : zds->outBuffSize - zds->outStart),
|
|
2403
2551
|
ip, neededInSize);
|
|
2404
2552
|
if (ZSTD_isError(decodedSize)) return decodedSize;
|
|
2405
2553
|
ip += neededInSize;
|
|
2406
2554
|
if (!decodedSize && !isSkipFrame) break; /* this was just a header */
|
|
2407
2555
|
zds->outEnd = zds->outStart + decodedSize;
|
|
2408
|
-
zds->
|
|
2556
|
+
zds->streamStage = zdss_flush;
|
|
2409
2557
|
break;
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
}
|
|
2415
|
-
|
|
2558
|
+
} }
|
|
2559
|
+
if (ip==iend) { someMoreWork = 0; break; } /* no more input */
|
|
2560
|
+
zds->streamStage = zdss_load;
|
|
2561
|
+
/* fall-through */
|
|
2416
2562
|
case zdss_load:
|
|
2417
|
-
{ size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds
|
|
2418
|
-
size_t const toLoad = neededInSize - zds->inPos;
|
|
2563
|
+
{ size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds);
|
|
2564
|
+
size_t const toLoad = neededInSize - zds->inPos;
|
|
2565
|
+
int const isSkipFrame = ZSTD_isSkipFrame(zds);
|
|
2419
2566
|
size_t loadedSize;
|
|
2420
|
-
if (
|
|
2421
|
-
|
|
2567
|
+
if (isSkipFrame) {
|
|
2568
|
+
loadedSize = MIN(toLoad, (size_t)(iend-ip));
|
|
2569
|
+
} else {
|
|
2570
|
+
if (toLoad > zds->inBuffSize - zds->inPos) return ERROR(corruption_detected); /* should never happen */
|
|
2571
|
+
loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, iend-ip);
|
|
2572
|
+
}
|
|
2422
2573
|
ip += loadedSize;
|
|
2423
2574
|
zds->inPos += loadedSize;
|
|
2424
2575
|
if (loadedSize < toLoad) { someMoreWork = 0; break; } /* not enough input, wait for more */
|
|
2425
2576
|
|
|
2426
2577
|
/* decode loaded input */
|
|
2427
|
-
{
|
|
2428
|
-
size_t const decodedSize = ZSTD_decompressContinue(zds->dctx,
|
|
2578
|
+
{ size_t const decodedSize = ZSTD_decompressContinue(zds,
|
|
2429
2579
|
zds->outBuff + zds->outStart, zds->outBuffSize - zds->outStart,
|
|
2430
2580
|
zds->inBuff, neededInSize);
|
|
2431
2581
|
if (ZSTD_isError(decodedSize)) return decodedSize;
|
|
2432
2582
|
zds->inPos = 0; /* input is consumed */
|
|
2433
|
-
if (!decodedSize && !isSkipFrame) { zds->
|
|
2583
|
+
if (!decodedSize && !isSkipFrame) { zds->streamStage = zdss_read; break; } /* this was just a header */
|
|
2434
2584
|
zds->outEnd = zds->outStart + decodedSize;
|
|
2435
|
-
zds->stage = zdss_flush;
|
|
2436
|
-
/* pass-through */
|
|
2437
2585
|
} }
|
|
2438
|
-
|
|
2586
|
+
zds->streamStage = zdss_flush;
|
|
2587
|
+
/* fall-through */
|
|
2439
2588
|
case zdss_flush:
|
|
2440
2589
|
{ size_t const toFlushSize = zds->outEnd - zds->outStart;
|
|
2441
2590
|
size_t const flushedSize = ZSTD_limitCopy(op, oend-op, zds->outBuff + zds->outStart, toFlushSize);
|
|
2442
2591
|
op += flushedSize;
|
|
2443
2592
|
zds->outStart += flushedSize;
|
|
2444
2593
|
if (flushedSize == toFlushSize) { /* flush completed */
|
|
2445
|
-
zds->
|
|
2446
|
-
if (
|
|
2594
|
+
zds->streamStage = zdss_read;
|
|
2595
|
+
if ( (zds->outBuffSize < zds->fParams.frameContentSize)
|
|
2596
|
+
&& (zds->outStart + zds->fParams.blockSizeMax > zds->outBuffSize) ) {
|
|
2597
|
+
DEBUGLOG(5, "restart filling outBuff from beginning (left:%i, needed:%u)",
|
|
2598
|
+
(int)(zds->outBuffSize - zds->outStart),
|
|
2599
|
+
(U32)zds->fParams.blockSizeMax);
|
|
2447
2600
|
zds->outStart = zds->outEnd = 0;
|
|
2601
|
+
}
|
|
2448
2602
|
break;
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2603
|
+
} }
|
|
2604
|
+
/* cannot complete flush */
|
|
2605
|
+
someMoreWork = 0;
|
|
2606
|
+
break;
|
|
2607
|
+
|
|
2454
2608
|
default: return ERROR(GENERIC); /* impossible */
|
|
2455
2609
|
} }
|
|
2456
2610
|
|
|
2457
2611
|
/* result */
|
|
2458
2612
|
input->pos += (size_t)(ip-istart);
|
|
2459
2613
|
output->pos += (size_t)(op-ostart);
|
|
2460
|
-
{ size_t nextSrcSizeHint = ZSTD_nextSrcSizeToDecompress(zds
|
|
2614
|
+
{ size_t nextSrcSizeHint = ZSTD_nextSrcSizeToDecompress(zds);
|
|
2461
2615
|
if (!nextSrcSizeHint) { /* frame fully decoded */
|
|
2462
2616
|
if (zds->outEnd == zds->outStart) { /* output fully flushed */
|
|
2463
2617
|
if (zds->hostageByte) {
|
|
2464
|
-
if (input->pos >= input->size) {
|
|
2618
|
+
if (input->pos >= input->size) {
|
|
2619
|
+
/* can't release hostage (not present) */
|
|
2620
|
+
zds->streamStage = zdss_read;
|
|
2621
|
+
return 1;
|
|
2622
|
+
}
|
|
2465
2623
|
input->pos++; /* release hostage */
|
|
2466
|
-
}
|
|
2624
|
+
} /* zds->hostageByte */
|
|
2467
2625
|
return 0;
|
|
2468
|
-
}
|
|
2626
|
+
} /* zds->outEnd == zds->outStart */
|
|
2469
2627
|
if (!zds->hostageByte) { /* output not fully flushed; keep last byte as hostage; will be released when all output is flushed */
|
|
2470
2628
|
input->pos--; /* note : pos > 0, otherwise, impossible to finish reading last block */
|
|
2471
2629
|
zds->hostageByte=1;
|
|
2472
2630
|
}
|
|
2473
2631
|
return 1;
|
|
2474
|
-
}
|
|
2475
|
-
nextSrcSizeHint += ZSTD_blockHeaderSize * (ZSTD_nextInputType(zds
|
|
2632
|
+
} /* nextSrcSizeHint==0 */
|
|
2633
|
+
nextSrcSizeHint += ZSTD_blockHeaderSize * (ZSTD_nextInputType(zds) == ZSTDnit_block); /* preload header of next block */
|
|
2476
2634
|
if (zds->inPos > nextSrcSizeHint) return ERROR(GENERIC); /* should never happen */
|
|
2477
2635
|
nextSrcSizeHint -= zds->inPos; /* already loaded*/
|
|
2478
2636
|
return nextSrcSizeHint;
|
|
2479
2637
|
}
|
|
2480
2638
|
}
|
|
2639
|
+
|
|
2640
|
+
|
|
2641
|
+
size_t ZSTD_decompress_generic(ZSTD_DCtx* dctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
|
|
2642
|
+
{
|
|
2643
|
+
return ZSTD_decompressStream(dctx, output, input);
|
|
2644
|
+
}
|
|
2645
|
+
|
|
2646
|
+
size_t ZSTD_decompress_generic_simpleArgs (
|
|
2647
|
+
ZSTD_DCtx* dctx,
|
|
2648
|
+
void* dst, size_t dstCapacity, size_t* dstPos,
|
|
2649
|
+
const void* src, size_t srcSize, size_t* srcPos)
|
|
2650
|
+
{
|
|
2651
|
+
ZSTD_outBuffer output = { dst, dstCapacity, *dstPos };
|
|
2652
|
+
ZSTD_inBuffer input = { src, srcSize, *srcPos };
|
|
2653
|
+
/* ZSTD_compress_generic() will check validity of dstPos and srcPos */
|
|
2654
|
+
size_t const cErr = ZSTD_decompress_generic(dctx, &output, &input);
|
|
2655
|
+
*dstPos = output.pos;
|
|
2656
|
+
*srcPos = input.pos;
|
|
2657
|
+
return cErr;
|
|
2658
|
+
}
|
|
2659
|
+
|
|
2660
|
+
void ZSTD_DCtx_reset(ZSTD_DCtx* dctx)
|
|
2661
|
+
{
|
|
2662
|
+
(void)ZSTD_initDStream(dctx);
|
|
2663
|
+
dctx->format = ZSTD_f_zstd1;
|
|
2664
|
+
dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
|
|
2665
|
+
}
|