extzstd 0.1 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/HISTORY.ja +5 -0
- data/README.md +5 -5
- data/contrib/zstd/CONTRIBUTING.md +42 -0
- data/contrib/zstd/LICENSE-examples +11 -0
- data/contrib/zstd/Makefile +315 -0
- data/contrib/zstd/NEWS +261 -0
- data/contrib/zstd/PATENTS +33 -0
- data/contrib/zstd/README.md +121 -41
- data/contrib/zstd/TESTING.md +44 -0
- data/contrib/zstd/appveyor.yml +178 -0
- data/contrib/zstd/circle.yml +75 -0
- data/contrib/zstd/lib/BUCK +186 -0
- data/contrib/zstd/lib/Makefile +163 -0
- data/contrib/zstd/lib/README.md +77 -0
- data/contrib/zstd/{common → lib/common}/bitstream.h +7 -4
- data/contrib/zstd/{common → lib/common}/entropy_common.c +19 -23
- data/contrib/zstd/{common → lib/common}/error_private.c +0 -0
- data/contrib/zstd/{common → lib/common}/error_private.h +0 -0
- data/contrib/zstd/{common → lib/common}/fse.h +94 -34
- data/contrib/zstd/{common → lib/common}/fse_decompress.c +18 -19
- data/contrib/zstd/{common → lib/common}/huf.h +52 -20
- data/contrib/zstd/{common → lib/common}/mem.h +17 -13
- data/contrib/zstd/lib/common/pool.c +194 -0
- data/contrib/zstd/lib/common/pool.h +56 -0
- data/contrib/zstd/lib/common/threading.c +80 -0
- data/contrib/zstd/lib/common/threading.h +104 -0
- data/contrib/zstd/{common → lib/common}/xxhash.c +3 -1
- data/contrib/zstd/{common → lib/common}/xxhash.h +11 -15
- data/contrib/zstd/{common → lib/common}/zstd_common.c +1 -11
- data/contrib/zstd/{common → lib/common}/zstd_errors.h +16 -2
- data/contrib/zstd/{common → lib/common}/zstd_internal.h +17 -1
- data/contrib/zstd/{compress → lib/compress}/fse_compress.c +138 -91
- data/contrib/zstd/{compress → lib/compress}/huf_compress.c +218 -67
- data/contrib/zstd/{compress → lib/compress}/zstd_compress.c +231 -108
- data/contrib/zstd/{compress → lib/compress}/zstd_opt.h +44 -25
- data/contrib/zstd/lib/compress/zstdmt_compress.c +739 -0
- data/contrib/zstd/lib/compress/zstdmt_compress.h +78 -0
- data/contrib/zstd/{decompress → lib/decompress}/huf_decompress.c +28 -23
- data/contrib/zstd/{decompress → lib/decompress}/zstd_decompress.c +814 -176
- data/contrib/zstd/{common → lib/deprecated}/zbuff.h +60 -39
- data/contrib/zstd/lib/deprecated/zbuff_common.c +26 -0
- data/contrib/zstd/lib/deprecated/zbuff_compress.c +145 -0
- data/contrib/zstd/lib/deprecated/zbuff_decompress.c +74 -0
- data/contrib/zstd/lib/dictBuilder/cover.c +1029 -0
- data/contrib/zstd/{dictBuilder → lib/dictBuilder}/divsufsort.c +0 -0
- data/contrib/zstd/{dictBuilder → lib/dictBuilder}/divsufsort.h +0 -0
- data/contrib/zstd/{dictBuilder → lib/dictBuilder}/zdict.c +68 -18
- data/contrib/zstd/lib/dictBuilder/zdict.h +201 -0
- data/contrib/zstd/{legacy → lib/legacy}/zstd_legacy.h +122 -7
- data/contrib/zstd/{legacy → lib/legacy}/zstd_v01.c +34 -3
- data/contrib/zstd/{legacy → lib/legacy}/zstd_v01.h +8 -0
- data/contrib/zstd/{legacy → lib/legacy}/zstd_v02.c +45 -12
- data/contrib/zstd/{legacy → lib/legacy}/zstd_v02.h +8 -0
- data/contrib/zstd/{legacy → lib/legacy}/zstd_v03.c +45 -12
- data/contrib/zstd/{legacy → lib/legacy}/zstd_v03.h +8 -0
- data/contrib/zstd/{legacy → lib/legacy}/zstd_v04.c +56 -33
- data/contrib/zstd/{legacy → lib/legacy}/zstd_v04.h +8 -0
- data/contrib/zstd/{legacy → lib/legacy}/zstd_v05.c +45 -18
- data/contrib/zstd/{legacy → lib/legacy}/zstd_v05.h +7 -0
- data/contrib/zstd/{legacy → lib/legacy}/zstd_v06.c +43 -16
- data/contrib/zstd/{legacy → lib/legacy}/zstd_v06.h +7 -0
- data/contrib/zstd/{legacy → lib/legacy}/zstd_v07.c +57 -23
- data/contrib/zstd/{legacy → lib/legacy}/zstd_v07.h +8 -0
- data/contrib/zstd/lib/libzstd.pc.in +14 -0
- data/contrib/zstd/{zstd.h → lib/zstd.h} +206 -71
- data/ext/depend +2 -0
- data/ext/extconf.rb +4 -4
- data/ext/extzstd.c +1 -1
- data/ext/zstd_common.c +5 -5
- data/ext/zstd_compress.c +3 -3
- data/ext/zstd_decompress.c +2 -2
- data/ext/zstd_dictbuilder.c +2 -2
- data/ext/zstd_legacy_v01.c +1 -1
- data/ext/zstd_legacy_v02.c +1 -1
- data/ext/zstd_legacy_v03.c +1 -1
- data/ext/zstd_legacy_v04.c +1 -1
- data/ext/zstd_legacy_v05.c +1 -1
- data/ext/zstd_legacy_v06.c +1 -1
- data/ext/zstd_legacy_v07.c +1 -1
- data/gemstub.rb +9 -5
- data/lib/extzstd/version.rb +1 -1
- metadata +73 -51
- data/contrib/zstd/compress/zbuff_compress.c +0 -319
- data/contrib/zstd/decompress/zbuff_decompress.c +0 -252
- data/contrib/zstd/dictBuilder/zdict.h +0 -111
|
@@ -43,8 +43,6 @@
|
|
|
43
43
|
*********************************************************/
|
|
44
44
|
#include <string.h> /* memcpy, memmove, memset */
|
|
45
45
|
#include "mem.h" /* low level memory routines */
|
|
46
|
-
#define XXH_STATIC_LINKING_ONLY /* XXH64_state_t */
|
|
47
|
-
#include "xxhash.h" /* XXH64_* */
|
|
48
46
|
#define FSE_STATIC_LINKING_ONLY
|
|
49
47
|
#include "fse.h"
|
|
50
48
|
#define HUF_STATIC_LINKING_ONLY
|
|
@@ -56,6 +54,15 @@
|
|
|
56
54
|
#endif
|
|
57
55
|
|
|
58
56
|
|
|
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
|
+
|
|
59
66
|
/*-*************************************
|
|
60
67
|
* Macros
|
|
61
68
|
***************************************/
|
|
@@ -78,22 +85,26 @@ typedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader,
|
|
|
78
85
|
ZSTDds_decompressLastBlock, ZSTDds_checkChecksum,
|
|
79
86
|
ZSTDds_decodeSkippableHeader, ZSTDds_skipFrame } ZSTD_dStage;
|
|
80
87
|
|
|
88
|
+
typedef struct {
|
|
89
|
+
FSE_DTable LLTable[FSE_DTABLE_SIZE_U32(LLFSELog)];
|
|
90
|
+
FSE_DTable OFTable[FSE_DTABLE_SIZE_U32(OffFSELog)];
|
|
91
|
+
FSE_DTable MLTable[FSE_DTABLE_SIZE_U32(MLFSELog)];
|
|
92
|
+
HUF_DTable hufTable[HUF_DTABLE_SIZE(HufLog)]; /* can accommodate HUF_decompress4X */
|
|
93
|
+
U32 rep[ZSTD_REP_NUM];
|
|
94
|
+
} ZSTD_entropyTables_t;
|
|
95
|
+
|
|
81
96
|
struct ZSTD_DCtx_s
|
|
82
97
|
{
|
|
83
98
|
const FSE_DTable* LLTptr;
|
|
84
99
|
const FSE_DTable* MLTptr;
|
|
85
100
|
const FSE_DTable* OFTptr;
|
|
86
101
|
const HUF_DTable* HUFptr;
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
const void*
|
|
92
|
-
const void* base;
|
|
93
|
-
const void* vBase;
|
|
94
|
-
const void* dictEnd;
|
|
102
|
+
ZSTD_entropyTables_t entropy;
|
|
103
|
+
const void* previousDstEnd; /* detect continuity */
|
|
104
|
+
const void* base; /* start of current segment */
|
|
105
|
+
const void* vBase; /* virtual start of previous segment if it was just before current one */
|
|
106
|
+
const void* dictEnd; /* end of previous segment */
|
|
95
107
|
size_t expected;
|
|
96
|
-
U32 rep[ZSTD_REP_NUM];
|
|
97
108
|
ZSTD_frameParams fParams;
|
|
98
109
|
blockType_e bType; /* used in ZSTD_decompressContinue(), to transfer blockType between header decoding and block decoding stages */
|
|
99
110
|
ZSTD_dStage stage;
|
|
@@ -104,7 +115,6 @@ struct ZSTD_DCtx_s
|
|
|
104
115
|
U32 dictID;
|
|
105
116
|
const BYTE* litPtr;
|
|
106
117
|
ZSTD_customMem customMem;
|
|
107
|
-
size_t litBufSize;
|
|
108
118
|
size_t litSize;
|
|
109
119
|
size_t rleSize;
|
|
110
120
|
BYTE litBuffer[ZSTD_BLOCKSIZE_ABSOLUTEMAX + WILDCOPY_OVERLENGTH];
|
|
@@ -123,15 +133,15 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
|
|
|
123
133
|
dctx->base = NULL;
|
|
124
134
|
dctx->vBase = NULL;
|
|
125
135
|
dctx->dictEnd = NULL;
|
|
126
|
-
dctx->hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
|
|
136
|
+
dctx->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
|
|
127
137
|
dctx->litEntropy = dctx->fseEntropy = 0;
|
|
128
138
|
dctx->dictID = 0;
|
|
129
|
-
MEM_STATIC_ASSERT(sizeof(dctx->rep) == sizeof(repStartValue));
|
|
130
|
-
memcpy(dctx->rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */
|
|
131
|
-
dctx->LLTptr = dctx->LLTable;
|
|
132
|
-
dctx->MLTptr = dctx->MLTable;
|
|
133
|
-
dctx->OFTptr = dctx->OFTable;
|
|
134
|
-
dctx->HUFptr = dctx->hufTable;
|
|
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;
|
|
135
145
|
return 0;
|
|
136
146
|
}
|
|
137
147
|
|
|
@@ -167,6 +177,8 @@ void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
|
|
|
167
177
|
memcpy(dstDCtx, srcDCtx, sizeof(ZSTD_DCtx) - workSpaceSize); /* no need to copy workspace */
|
|
168
178
|
}
|
|
169
179
|
|
|
180
|
+
#if 0
|
|
181
|
+
/* deprecated */
|
|
170
182
|
static void ZSTD_refDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
|
|
171
183
|
{
|
|
172
184
|
ZSTD_decompressBegin(dstDCtx); /* init */
|
|
@@ -178,22 +190,42 @@ static void ZSTD_refDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
|
|
|
178
190
|
dstDCtx->dictID = srcDCtx->dictID;
|
|
179
191
|
dstDCtx->litEntropy = srcDCtx->litEntropy;
|
|
180
192
|
dstDCtx->fseEntropy = srcDCtx->fseEntropy;
|
|
181
|
-
dstDCtx->LLTptr = srcDCtx->LLTable;
|
|
182
|
-
dstDCtx->MLTptr = srcDCtx->MLTable;
|
|
183
|
-
dstDCtx->OFTptr = srcDCtx->OFTable;
|
|
184
|
-
dstDCtx->HUFptr = srcDCtx->hufTable;
|
|
185
|
-
dstDCtx->rep[0] = srcDCtx->rep[0];
|
|
186
|
-
dstDCtx->rep[1] = srcDCtx->rep[1];
|
|
187
|
-
dstDCtx->rep[2] = srcDCtx->rep[2];
|
|
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];
|
|
188
200
|
}
|
|
189
201
|
}
|
|
202
|
+
#endif
|
|
203
|
+
|
|
204
|
+
static void ZSTD_refDDict(ZSTD_DCtx* dstDCtx, const ZSTD_DDict* ddict);
|
|
190
205
|
|
|
191
206
|
|
|
192
207
|
/*-*************************************************************
|
|
193
208
|
* Decompression section
|
|
194
209
|
***************************************************************/
|
|
195
210
|
|
|
196
|
-
|
|
211
|
+
/*! ZSTD_isFrame() :
|
|
212
|
+
* Tells if the content of `buffer` starts with a valid Frame Identifier.
|
|
213
|
+
* Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0.
|
|
214
|
+
* Note 2 : Legacy Frame Identifiers are considered valid only if Legacy Support is enabled.
|
|
215
|
+
* Note 3 : Skippable Frame Identifiers are considered valid. */
|
|
216
|
+
unsigned ZSTD_isFrame(const void* buffer, size_t size)
|
|
217
|
+
{
|
|
218
|
+
if (size < 4) return 0;
|
|
219
|
+
{ U32 const magic = MEM_readLE32(buffer);
|
|
220
|
+
if (magic == ZSTD_MAGICNUMBER) return 1;
|
|
221
|
+
if ((magic & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) return 1;
|
|
222
|
+
}
|
|
223
|
+
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
|
|
224
|
+
if (ZSTD_isLegacy(buffer, size)) return 1;
|
|
225
|
+
#endif
|
|
226
|
+
return 0;
|
|
227
|
+
}
|
|
228
|
+
|
|
197
229
|
|
|
198
230
|
/** ZSTD_frameHeaderSize() :
|
|
199
231
|
* srcSize must be >= ZSTD_frameHeaderSize_prefix.
|
|
@@ -281,6 +313,86 @@ size_t ZSTD_getFrameParams(ZSTD_frameParams* fparamsPtr, const void* src, size_t
|
|
|
281
313
|
return 0;
|
|
282
314
|
}
|
|
283
315
|
|
|
316
|
+
/** ZSTD_getFrameContentSize() :
|
|
317
|
+
* compatible with legacy mode
|
|
318
|
+
* @return : decompressed size of the single frame pointed to be `src` if known, otherwise
|
|
319
|
+
* - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined
|
|
320
|
+
* - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small) */
|
|
321
|
+
unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize)
|
|
322
|
+
{
|
|
323
|
+
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
|
|
324
|
+
if (ZSTD_isLegacy(src, srcSize)) {
|
|
325
|
+
unsigned long long const ret = ZSTD_getDecompressedSize_legacy(src, srcSize);
|
|
326
|
+
return ret == 0 ? ZSTD_CONTENTSIZE_UNKNOWN : ret;
|
|
327
|
+
}
|
|
328
|
+
#endif
|
|
329
|
+
{
|
|
330
|
+
ZSTD_frameParams fParams;
|
|
331
|
+
if (ZSTD_getFrameParams(&fParams, src, srcSize) != 0) return ZSTD_CONTENTSIZE_ERROR;
|
|
332
|
+
if (fParams.windowSize == 0) {
|
|
333
|
+
/* Either skippable or empty frame, size == 0 either way */
|
|
334
|
+
return 0;
|
|
335
|
+
} else if (fParams.frameContentSize != 0) {
|
|
336
|
+
return fParams.frameContentSize;
|
|
337
|
+
} else {
|
|
338
|
+
return ZSTD_CONTENTSIZE_UNKNOWN;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/** ZSTD_findDecompressedSize() :
|
|
344
|
+
* compatible with legacy mode
|
|
345
|
+
* `srcSize` must be the exact length of some number of ZSTD compressed and/or
|
|
346
|
+
* skippable frames
|
|
347
|
+
* @return : decompressed size of the frames contained */
|
|
348
|
+
unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
|
|
349
|
+
{
|
|
350
|
+
{
|
|
351
|
+
unsigned long long totalDstSize = 0;
|
|
352
|
+
while (srcSize >= ZSTD_frameHeaderSize_prefix) {
|
|
353
|
+
const U32 magicNumber = MEM_readLE32(src);
|
|
354
|
+
|
|
355
|
+
if ((magicNumber & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
|
|
356
|
+
size_t skippableSize;
|
|
357
|
+
if (srcSize < ZSTD_skippableHeaderSize)
|
|
358
|
+
return ERROR(srcSize_wrong);
|
|
359
|
+
skippableSize = MEM_readLE32((const BYTE *)src + 4) +
|
|
360
|
+
ZSTD_skippableHeaderSize;
|
|
361
|
+
if (srcSize < skippableSize) {
|
|
362
|
+
return ZSTD_CONTENTSIZE_ERROR;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
src = (const BYTE *)src + skippableSize;
|
|
366
|
+
srcSize -= skippableSize;
|
|
367
|
+
continue;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
{
|
|
371
|
+
unsigned long long const ret = ZSTD_getFrameContentSize(src, srcSize);
|
|
372
|
+
if (ret >= ZSTD_CONTENTSIZE_ERROR) return ret;
|
|
373
|
+
|
|
374
|
+
/* check for overflow */
|
|
375
|
+
if (totalDstSize + ret < totalDstSize) return ZSTD_CONTENTSIZE_ERROR;
|
|
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
|
+
}
|
|
383
|
+
|
|
384
|
+
src = (const BYTE *)src + frameSrcSize;
|
|
385
|
+
srcSize -= frameSrcSize;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
if (srcSize) {
|
|
390
|
+
return ZSTD_CONTENTSIZE_ERROR;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
return totalDstSize;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
284
396
|
|
|
285
397
|
/** ZSTD_getDecompressedSize() :
|
|
286
398
|
* compatible with legacy mode
|
|
@@ -291,14 +403,8 @@ size_t ZSTD_getFrameParams(ZSTD_frameParams* fparamsPtr, const void* src, size_t
|
|
|
291
403
|
- frame header not complete (`srcSize` too small) */
|
|
292
404
|
unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize)
|
|
293
405
|
{
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
#endif
|
|
297
|
-
{ ZSTD_frameParams fparams;
|
|
298
|
-
size_t const frResult = ZSTD_getFrameParams(&fparams, src, srcSize);
|
|
299
|
-
if (frResult!=0) return 0;
|
|
300
|
-
return fparams.frameContentSize;
|
|
301
|
-
}
|
|
406
|
+
unsigned long long const ret = ZSTD_getFrameContentSize(src, srcSize);
|
|
407
|
+
return ret >= ZSTD_CONTENTSIZE_ERROR ? 0 : ret;
|
|
302
408
|
}
|
|
303
409
|
|
|
304
410
|
|
|
@@ -407,15 +513,15 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
|
|
|
407
513
|
HUF_decompress1X_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->HUFptr) :
|
|
408
514
|
HUF_decompress4X_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->HUFptr) ) :
|
|
409
515
|
( singleStream ?
|
|
410
|
-
HUF_decompress1X2_DCtx(dctx->hufTable, dctx->litBuffer, litSize, istart+lhSize, litCSize) :
|
|
411
|
-
HUF_decompress4X_hufOnly (dctx->hufTable, dctx->litBuffer, litSize, istart+lhSize, litCSize)) ))
|
|
516
|
+
HUF_decompress1X2_DCtx(dctx->entropy.hufTable, dctx->litBuffer, litSize, istart+lhSize, litCSize) :
|
|
517
|
+
HUF_decompress4X_hufOnly (dctx->entropy.hufTable, dctx->litBuffer, litSize, istart+lhSize, litCSize)) ))
|
|
412
518
|
return ERROR(corruption_detected);
|
|
413
519
|
|
|
414
520
|
dctx->litPtr = dctx->litBuffer;
|
|
415
|
-
dctx->litBufSize = ZSTD_BLOCKSIZE_ABSOLUTEMAX+WILDCOPY_OVERLENGTH;
|
|
416
521
|
dctx->litSize = litSize;
|
|
417
522
|
dctx->litEntropy = 1;
|
|
418
|
-
if (litEncType==set_compressed) dctx->HUFptr = dctx->hufTable;
|
|
523
|
+
if (litEncType==set_compressed) dctx->HUFptr = dctx->entropy.hufTable;
|
|
524
|
+
memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);
|
|
419
525
|
return litCSize + lhSize;
|
|
420
526
|
}
|
|
421
527
|
|
|
@@ -442,13 +548,12 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
|
|
|
442
548
|
if (litSize+lhSize > srcSize) return ERROR(corruption_detected);
|
|
443
549
|
memcpy(dctx->litBuffer, istart+lhSize, litSize);
|
|
444
550
|
dctx->litPtr = dctx->litBuffer;
|
|
445
|
-
dctx->litBufSize = ZSTD_BLOCKSIZE_ABSOLUTEMAX+8;
|
|
446
551
|
dctx->litSize = litSize;
|
|
552
|
+
memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);
|
|
447
553
|
return lhSize+litSize;
|
|
448
554
|
}
|
|
449
555
|
/* direct reference into compressed stream */
|
|
450
556
|
dctx->litPtr = istart+lhSize;
|
|
451
|
-
dctx->litBufSize = srcSize-lhSize;
|
|
452
557
|
dctx->litSize = litSize;
|
|
453
558
|
return lhSize+litSize;
|
|
454
559
|
}
|
|
@@ -473,9 +578,8 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
|
|
|
473
578
|
break;
|
|
474
579
|
}
|
|
475
580
|
if (litSize > ZSTD_BLOCKSIZE_ABSOLUTEMAX) return ERROR(corruption_detected);
|
|
476
|
-
memset(dctx->litBuffer, istart[lhSize], litSize);
|
|
581
|
+
memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH);
|
|
477
582
|
dctx->litPtr = dctx->litBuffer;
|
|
478
|
-
dctx->litBufSize = ZSTD_BLOCKSIZE_ABSOLUTEMAX+WILDCOPY_OVERLENGTH;
|
|
479
583
|
dctx->litSize = litSize;
|
|
480
584
|
return lhSize+1;
|
|
481
585
|
}
|
|
@@ -733,19 +837,19 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
|
|
|
733
837
|
ip++;
|
|
734
838
|
|
|
735
839
|
/* Build DTables */
|
|
736
|
-
{ size_t const llhSize = ZSTD_buildSeqTable(dctx->LLTable, &dctx->LLTptr,
|
|
840
|
+
{ size_t const llhSize = ZSTD_buildSeqTable(dctx->entropy.LLTable, &dctx->LLTptr,
|
|
737
841
|
LLtype, MaxLL, LLFSELog,
|
|
738
842
|
ip, iend-ip, LL_defaultDTable, dctx->fseEntropy);
|
|
739
843
|
if (ZSTD_isError(llhSize)) return ERROR(corruption_detected);
|
|
740
844
|
ip += llhSize;
|
|
741
845
|
}
|
|
742
|
-
{ size_t const ofhSize = ZSTD_buildSeqTable(dctx->OFTable, &dctx->OFTptr,
|
|
846
|
+
{ size_t const ofhSize = ZSTD_buildSeqTable(dctx->entropy.OFTable, &dctx->OFTptr,
|
|
743
847
|
OFtype, MaxOff, OffFSELog,
|
|
744
848
|
ip, iend-ip, OF_defaultDTable, dctx->fseEntropy);
|
|
745
849
|
if (ZSTD_isError(ofhSize)) return ERROR(corruption_detected);
|
|
746
850
|
ip += ofhSize;
|
|
747
851
|
}
|
|
748
|
-
{ size_t const mlhSize = ZSTD_buildSeqTable(dctx->MLTable, &dctx->MLTptr,
|
|
852
|
+
{ size_t const mlhSize = ZSTD_buildSeqTable(dctx->entropy.MLTable, &dctx->MLTptr,
|
|
749
853
|
MLtype, MaxML, MLFSELog,
|
|
750
854
|
ip, iend-ip, ML_defaultDTable, dctx->fseEntropy);
|
|
751
855
|
if (ZSTD_isError(mlhSize)) return ERROR(corruption_detected);
|
|
@@ -761,6 +865,7 @@ typedef struct {
|
|
|
761
865
|
size_t litLength;
|
|
762
866
|
size_t matchLength;
|
|
763
867
|
size_t offset;
|
|
868
|
+
const BYTE* match;
|
|
764
869
|
} seq_t;
|
|
765
870
|
|
|
766
871
|
typedef struct {
|
|
@@ -769,9 +874,61 @@ typedef struct {
|
|
|
769
874
|
FSE_DState_t stateOffb;
|
|
770
875
|
FSE_DState_t stateML;
|
|
771
876
|
size_t prevOffset[ZSTD_REP_NUM];
|
|
877
|
+
const BYTE* base;
|
|
878
|
+
size_t pos;
|
|
879
|
+
uPtrDiff gotoDict;
|
|
772
880
|
} seqState_t;
|
|
773
881
|
|
|
774
882
|
|
|
883
|
+
FORCE_NOINLINE
|
|
884
|
+
size_t ZSTD_execSequenceLast7(BYTE* op,
|
|
885
|
+
BYTE* const oend, seq_t sequence,
|
|
886
|
+
const BYTE** litPtr, const BYTE* const litLimit,
|
|
887
|
+
const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)
|
|
888
|
+
{
|
|
889
|
+
BYTE* const oLitEnd = op + sequence.litLength;
|
|
890
|
+
size_t const sequenceLength = sequence.litLength + sequence.matchLength;
|
|
891
|
+
BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
|
|
892
|
+
BYTE* const oend_w = oend - WILDCOPY_OVERLENGTH;
|
|
893
|
+
const BYTE* const iLitEnd = *litPtr + sequence.litLength;
|
|
894
|
+
const BYTE* match = oLitEnd - sequence.offset;
|
|
895
|
+
|
|
896
|
+
/* check */
|
|
897
|
+
if (oMatchEnd>oend) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */
|
|
898
|
+
if (iLitEnd > litLimit) return ERROR(corruption_detected); /* over-read beyond lit buffer */
|
|
899
|
+
if (oLitEnd <= oend_w) return ERROR(GENERIC); /* Precondition */
|
|
900
|
+
|
|
901
|
+
/* copy literals */
|
|
902
|
+
if (op < oend_w) {
|
|
903
|
+
ZSTD_wildcopy(op, *litPtr, oend_w - op);
|
|
904
|
+
*litPtr += oend_w - op;
|
|
905
|
+
op = oend_w;
|
|
906
|
+
}
|
|
907
|
+
while (op < oLitEnd) *op++ = *(*litPtr)++;
|
|
908
|
+
|
|
909
|
+
/* copy Match */
|
|
910
|
+
if (sequence.offset > (size_t)(oLitEnd - base)) {
|
|
911
|
+
/* offset beyond prefix */
|
|
912
|
+
if (sequence.offset > (size_t)(oLitEnd - vBase)) return ERROR(corruption_detected);
|
|
913
|
+
match = dictEnd - (base-match);
|
|
914
|
+
if (match + sequence.matchLength <= dictEnd) {
|
|
915
|
+
memmove(oLitEnd, match, sequence.matchLength);
|
|
916
|
+
return sequenceLength;
|
|
917
|
+
}
|
|
918
|
+
/* span extDict & currentPrefixSegment */
|
|
919
|
+
{ size_t const length1 = dictEnd - match;
|
|
920
|
+
memmove(oLitEnd, match, length1);
|
|
921
|
+
op = oLitEnd + length1;
|
|
922
|
+
sequence.matchLength -= length1;
|
|
923
|
+
match = base;
|
|
924
|
+
} }
|
|
925
|
+
while (op < oMatchEnd) *op++ = *match++;
|
|
926
|
+
return sequenceLength;
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
|
|
930
|
+
|
|
931
|
+
|
|
775
932
|
static seq_t ZSTD_decodeSequence(seqState_t* seqState)
|
|
776
933
|
{
|
|
777
934
|
seq_t seq;
|
|
@@ -797,17 +954,17 @@ static seq_t ZSTD_decodeSequence(seqState_t* seqState)
|
|
|
797
954
|
0x1003, 0x2003, 0x4003, 0x8003, 0x10003 };
|
|
798
955
|
|
|
799
956
|
static const U32 OF_base[MaxOff+1] = {
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
957
|
+
0, 1, 1, 5, 0xD, 0x1D, 0x3D, 0x7D,
|
|
958
|
+
0xFD, 0x1FD, 0x3FD, 0x7FD, 0xFFD, 0x1FFD, 0x3FFD, 0x7FFD,
|
|
959
|
+
0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD,
|
|
960
|
+
0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD };
|
|
804
961
|
|
|
805
962
|
/* sequence */
|
|
806
963
|
{ size_t offset;
|
|
807
964
|
if (!ofCode)
|
|
808
965
|
offset = 0;
|
|
809
966
|
else {
|
|
810
|
-
offset = OF_base[ofCode] +
|
|
967
|
+
offset = OF_base[ofCode] + BIT_readBitsFast(&seqState->DStream, ofBits); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */
|
|
811
968
|
if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream);
|
|
812
969
|
}
|
|
813
970
|
|
|
@@ -830,10 +987,10 @@ static seq_t ZSTD_decodeSequence(seqState_t* seqState)
|
|
|
830
987
|
seq.offset = offset;
|
|
831
988
|
}
|
|
832
989
|
|
|
833
|
-
seq.matchLength = ML_base[mlCode] + ((mlCode>31) ?
|
|
990
|
+
seq.matchLength = ML_base[mlCode] + ((mlCode>31) ? BIT_readBitsFast(&seqState->DStream, mlBits) : 0); /* <= 16 bits */
|
|
834
991
|
if (MEM_32bits() && (mlBits+llBits>24)) BIT_reloadDStream(&seqState->DStream);
|
|
835
992
|
|
|
836
|
-
seq.litLength = LL_base[llCode] + ((llCode>15) ?
|
|
993
|
+
seq.litLength = LL_base[llCode] + ((llCode>15) ? BIT_readBitsFast(&seqState->DStream, llBits) : 0); /* <= 16 bits */
|
|
837
994
|
if (MEM_32bits() ||
|
|
838
995
|
(totalBits > 64 - 7 - (LLFSELog+MLFSELog+OffFSELog)) ) BIT_reloadDStream(&seqState->DStream);
|
|
839
996
|
|
|
@@ -847,11 +1004,11 @@ static seq_t ZSTD_decodeSequence(seqState_t* seqState)
|
|
|
847
1004
|
}
|
|
848
1005
|
|
|
849
1006
|
|
|
850
|
-
|
|
851
|
-
size_t
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
1007
|
+
FORCE_INLINE
|
|
1008
|
+
size_t ZSTD_execSequence(BYTE* op,
|
|
1009
|
+
BYTE* const oend, seq_t sequence,
|
|
1010
|
+
const BYTE** litPtr, const BYTE* const litLimit,
|
|
1011
|
+
const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)
|
|
855
1012
|
{
|
|
856
1013
|
BYTE* const oLitEnd = op + sequence.litLength;
|
|
857
1014
|
size_t const sequenceLength = sequence.litLength + sequence.matchLength;
|
|
@@ -862,22 +1019,21 @@ size_t ZSTD_execSequenceLast7(BYTE* op,
|
|
|
862
1019
|
|
|
863
1020
|
/* check */
|
|
864
1021
|
if (oMatchEnd>oend) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */
|
|
865
|
-
if (iLitEnd >
|
|
866
|
-
if (oLitEnd
|
|
1022
|
+
if (iLitEnd > litLimit) return ERROR(corruption_detected); /* over-read beyond lit buffer */
|
|
1023
|
+
if (oLitEnd>oend_w) return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit, base, vBase, dictEnd);
|
|
867
1024
|
|
|
868
|
-
/* copy
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
*litPtr
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
while (op < oLitEnd) *op++ = *(*litPtr)++;
|
|
1025
|
+
/* copy Literals */
|
|
1026
|
+
ZSTD_copy8(op, *litPtr);
|
|
1027
|
+
if (sequence.litLength > 8)
|
|
1028
|
+
ZSTD_wildcopy(op+8, (*litPtr)+8, sequence.litLength - 8); /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */
|
|
1029
|
+
op = oLitEnd;
|
|
1030
|
+
*litPtr = iLitEnd; /* update for next sequence */
|
|
875
1031
|
|
|
876
1032
|
/* copy Match */
|
|
877
1033
|
if (sequence.offset > (size_t)(oLitEnd - base)) {
|
|
878
1034
|
/* offset beyond prefix */
|
|
879
1035
|
if (sequence.offset > (size_t)(oLitEnd - vBase)) return ERROR(corruption_detected);
|
|
880
|
-
match = dictEnd -
|
|
1036
|
+
match = dictEnd + (match - base);
|
|
881
1037
|
if (match + sequence.matchLength <= dictEnd) {
|
|
882
1038
|
memmove(oLitEnd, match, sequence.matchLength);
|
|
883
1039
|
return sequenceLength;
|
|
@@ -888,16 +1044,203 @@ size_t ZSTD_execSequenceLast7(BYTE* op,
|
|
|
888
1044
|
op = oLitEnd + length1;
|
|
889
1045
|
sequence.matchLength -= length1;
|
|
890
1046
|
match = base;
|
|
1047
|
+
if (op > oend_w || sequence.matchLength < MINMATCH) {
|
|
1048
|
+
U32 i;
|
|
1049
|
+
for (i = 0; i < sequence.matchLength; ++i) op[i] = match[i];
|
|
1050
|
+
return sequenceLength;
|
|
1051
|
+
}
|
|
891
1052
|
} }
|
|
892
|
-
|
|
1053
|
+
/* Requirement: op <= oend_w && sequence.matchLength >= MINMATCH */
|
|
1054
|
+
|
|
1055
|
+
/* match within prefix */
|
|
1056
|
+
if (sequence.offset < 8) {
|
|
1057
|
+
/* close range match, overlap */
|
|
1058
|
+
static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
|
|
1059
|
+
static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* subtracted */
|
|
1060
|
+
int const sub2 = dec64table[sequence.offset];
|
|
1061
|
+
op[0] = match[0];
|
|
1062
|
+
op[1] = match[1];
|
|
1063
|
+
op[2] = match[2];
|
|
1064
|
+
op[3] = match[3];
|
|
1065
|
+
match += dec32table[sequence.offset];
|
|
1066
|
+
ZSTD_copy4(op+4, match);
|
|
1067
|
+
match -= sub2;
|
|
1068
|
+
} else {
|
|
1069
|
+
ZSTD_copy8(op, match);
|
|
1070
|
+
}
|
|
1071
|
+
op += 8; match += 8;
|
|
1072
|
+
|
|
1073
|
+
if (oMatchEnd > oend-(16-MINMATCH)) {
|
|
1074
|
+
if (op < oend_w) {
|
|
1075
|
+
ZSTD_wildcopy(op, match, oend_w - op);
|
|
1076
|
+
match += oend_w - op;
|
|
1077
|
+
op = oend_w;
|
|
1078
|
+
}
|
|
1079
|
+
while (op < oMatchEnd) *op++ = *match++;
|
|
1080
|
+
} else {
|
|
1081
|
+
ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8); /* works even if matchLength < 8 */
|
|
1082
|
+
}
|
|
893
1083
|
return sequenceLength;
|
|
894
1084
|
}
|
|
895
1085
|
|
|
896
1086
|
|
|
1087
|
+
static size_t ZSTD_decompressSequences(
|
|
1088
|
+
ZSTD_DCtx* dctx,
|
|
1089
|
+
void* dst, size_t maxDstSize,
|
|
1090
|
+
const void* seqStart, size_t seqSize)
|
|
1091
|
+
{
|
|
1092
|
+
const BYTE* ip = (const BYTE*)seqStart;
|
|
1093
|
+
const BYTE* const iend = ip + seqSize;
|
|
1094
|
+
BYTE* const ostart = (BYTE* const)dst;
|
|
1095
|
+
BYTE* const oend = ostart + maxDstSize;
|
|
1096
|
+
BYTE* op = ostart;
|
|
1097
|
+
const BYTE* litPtr = dctx->litPtr;
|
|
1098
|
+
const BYTE* const litEnd = litPtr + dctx->litSize;
|
|
1099
|
+
const BYTE* const base = (const BYTE*) (dctx->base);
|
|
1100
|
+
const BYTE* const vBase = (const BYTE*) (dctx->vBase);
|
|
1101
|
+
const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);
|
|
1102
|
+
int nbSeq;
|
|
1103
|
+
|
|
1104
|
+
/* Build Decoding Tables */
|
|
1105
|
+
{ size_t const seqHSize = ZSTD_decodeSeqHeaders(dctx, &nbSeq, ip, seqSize);
|
|
1106
|
+
if (ZSTD_isError(seqHSize)) return seqHSize;
|
|
1107
|
+
ip += seqHSize;
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
/* Regen sequences */
|
|
1111
|
+
if (nbSeq) {
|
|
1112
|
+
seqState_t seqState;
|
|
1113
|
+
dctx->fseEntropy = 1;
|
|
1114
|
+
{ U32 i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }
|
|
1115
|
+
CHECK_E(BIT_initDStream(&seqState.DStream, ip, iend-ip), corruption_detected);
|
|
1116
|
+
FSE_initDState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
|
|
1117
|
+
FSE_initDState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
|
|
1118
|
+
FSE_initDState(&seqState.stateML, &seqState.DStream, dctx->MLTptr);
|
|
1119
|
+
|
|
1120
|
+
for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && nbSeq ; ) {
|
|
1121
|
+
nbSeq--;
|
|
1122
|
+
{ seq_t const sequence = ZSTD_decodeSequence(&seqState);
|
|
1123
|
+
size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litEnd, base, vBase, dictEnd);
|
|
1124
|
+
if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
|
|
1125
|
+
op += oneSeqSize;
|
|
1126
|
+
} }
|
|
1127
|
+
|
|
1128
|
+
/* check if reached exact end */
|
|
1129
|
+
if (nbSeq) return ERROR(corruption_detected);
|
|
1130
|
+
/* save reps for next block */
|
|
1131
|
+
{ U32 i; for (i=0; i<ZSTD_REP_NUM; i++) dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]); }
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
/* last literal segment */
|
|
1135
|
+
{ size_t const lastLLSize = litEnd - litPtr;
|
|
1136
|
+
if (lastLLSize > (size_t)(oend-op)) return ERROR(dstSize_tooSmall);
|
|
1137
|
+
memcpy(op, litPtr, lastLLSize);
|
|
1138
|
+
op += lastLLSize;
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
return op-ostart;
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
|
|
1145
|
+
FORCE_INLINE seq_t ZSTD_decodeSequenceLong_generic(seqState_t* seqState, int const longOffsets)
|
|
1146
|
+
{
|
|
1147
|
+
seq_t seq;
|
|
1148
|
+
|
|
1149
|
+
U32 const llCode = FSE_peekSymbol(&seqState->stateLL);
|
|
1150
|
+
U32 const mlCode = FSE_peekSymbol(&seqState->stateML);
|
|
1151
|
+
U32 const ofCode = FSE_peekSymbol(&seqState->stateOffb); /* <= maxOff, by table construction */
|
|
1152
|
+
|
|
1153
|
+
U32 const llBits = LL_bits[llCode];
|
|
1154
|
+
U32 const mlBits = ML_bits[mlCode];
|
|
1155
|
+
U32 const ofBits = ofCode;
|
|
1156
|
+
U32 const totalBits = llBits+mlBits+ofBits;
|
|
1157
|
+
|
|
1158
|
+
static const U32 LL_base[MaxLL+1] = {
|
|
1159
|
+
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
|
1160
|
+
16, 18, 20, 22, 24, 28, 32, 40, 48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000,
|
|
1161
|
+
0x2000, 0x4000, 0x8000, 0x10000 };
|
|
1162
|
+
|
|
1163
|
+
static const U32 ML_base[MaxML+1] = {
|
|
1164
|
+
3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
|
|
1165
|
+
19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
|
|
1166
|
+
35, 37, 39, 41, 43, 47, 51, 59, 67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803,
|
|
1167
|
+
0x1003, 0x2003, 0x4003, 0x8003, 0x10003 };
|
|
1168
|
+
|
|
1169
|
+
static const U32 OF_base[MaxOff+1] = {
|
|
1170
|
+
0, 1, 1, 5, 0xD, 0x1D, 0x3D, 0x7D,
|
|
1171
|
+
0xFD, 0x1FD, 0x3FD, 0x7FD, 0xFFD, 0x1FFD, 0x3FFD, 0x7FFD,
|
|
1172
|
+
0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD,
|
|
1173
|
+
0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD };
|
|
1174
|
+
|
|
1175
|
+
/* sequence */
|
|
1176
|
+
{ size_t offset;
|
|
1177
|
+
if (!ofCode)
|
|
1178
|
+
offset = 0;
|
|
1179
|
+
else {
|
|
1180
|
+
if (longOffsets) {
|
|
1181
|
+
int const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN);
|
|
1182
|
+
offset = OF_base[ofCode] + (BIT_readBitsFast(&seqState->DStream, ofBits - extraBits) << extraBits);
|
|
1183
|
+
if (MEM_32bits() || extraBits) BIT_reloadDStream(&seqState->DStream);
|
|
1184
|
+
if (extraBits) offset += BIT_readBitsFast(&seqState->DStream, extraBits);
|
|
1185
|
+
} else {
|
|
1186
|
+
offset = OF_base[ofCode] + BIT_readBitsFast(&seqState->DStream, ofBits); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */
|
|
1187
|
+
if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream);
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
if (ofCode <= 1) {
|
|
1192
|
+
offset += (llCode==0);
|
|
1193
|
+
if (offset) {
|
|
1194
|
+
size_t temp = (offset==3) ? seqState->prevOffset[0] - 1 : seqState->prevOffset[offset];
|
|
1195
|
+
temp += !temp; /* 0 is not valid; input is corrupted; force offset to 1 */
|
|
1196
|
+
if (offset != 1) seqState->prevOffset[2] = seqState->prevOffset[1];
|
|
1197
|
+
seqState->prevOffset[1] = seqState->prevOffset[0];
|
|
1198
|
+
seqState->prevOffset[0] = offset = temp;
|
|
1199
|
+
} else {
|
|
1200
|
+
offset = seqState->prevOffset[0];
|
|
1201
|
+
}
|
|
1202
|
+
} else {
|
|
1203
|
+
seqState->prevOffset[2] = seqState->prevOffset[1];
|
|
1204
|
+
seqState->prevOffset[1] = seqState->prevOffset[0];
|
|
1205
|
+
seqState->prevOffset[0] = offset;
|
|
1206
|
+
}
|
|
1207
|
+
seq.offset = offset;
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
seq.matchLength = ML_base[mlCode] + ((mlCode>31) ? BIT_readBitsFast(&seqState->DStream, mlBits) : 0); /* <= 16 bits */
|
|
1211
|
+
if (MEM_32bits() && (mlBits+llBits>24)) BIT_reloadDStream(&seqState->DStream);
|
|
1212
|
+
|
|
1213
|
+
seq.litLength = LL_base[llCode] + ((llCode>15) ? BIT_readBitsFast(&seqState->DStream, llBits) : 0); /* <= 16 bits */
|
|
1214
|
+
if (MEM_32bits() ||
|
|
1215
|
+
(totalBits > 64 - 7 - (LLFSELog+MLFSELog+OffFSELog)) ) BIT_reloadDStream(&seqState->DStream);
|
|
1216
|
+
|
|
1217
|
+
{ size_t const pos = seqState->pos + seq.litLength;
|
|
1218
|
+
seq.match = seqState->base + pos - seq.offset; /* single memory segment */
|
|
1219
|
+
if (seq.offset > pos) seq.match += seqState->gotoDict; /* separate memory segment */
|
|
1220
|
+
seqState->pos = pos + seq.matchLength;
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
/* ANS state update */
|
|
1224
|
+
FSE_updateState(&seqState->stateLL, &seqState->DStream); /* <= 9 bits */
|
|
1225
|
+
FSE_updateState(&seqState->stateML, &seqState->DStream); /* <= 9 bits */
|
|
1226
|
+
if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream); /* <= 18 bits */
|
|
1227
|
+
FSE_updateState(&seqState->stateOffb, &seqState->DStream); /* <= 8 bits */
|
|
1228
|
+
|
|
1229
|
+
return seq;
|
|
1230
|
+
}
|
|
1231
|
+
|
|
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
|
+
|
|
897
1240
|
FORCE_INLINE
|
|
898
|
-
size_t
|
|
1241
|
+
size_t ZSTD_execSequenceLong(BYTE* op,
|
|
899
1242
|
BYTE* const oend, seq_t sequence,
|
|
900
|
-
const BYTE** litPtr, const BYTE* const
|
|
1243
|
+
const BYTE** litPtr, const BYTE* const litLimit,
|
|
901
1244
|
const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)
|
|
902
1245
|
{
|
|
903
1246
|
BYTE* const oLitEnd = op + sequence.litLength;
|
|
@@ -905,12 +1248,14 @@ size_t ZSTD_execSequence(BYTE* op,
|
|
|
905
1248
|
BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
|
|
906
1249
|
BYTE* const oend_w = oend - WILDCOPY_OVERLENGTH;
|
|
907
1250
|
const BYTE* const iLitEnd = *litPtr + sequence.litLength;
|
|
908
|
-
const BYTE* match =
|
|
1251
|
+
const BYTE* match = sequence.match;
|
|
909
1252
|
|
|
910
1253
|
/* check */
|
|
1254
|
+
#if 1
|
|
911
1255
|
if (oMatchEnd>oend) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */
|
|
912
|
-
if (iLitEnd >
|
|
913
|
-
if (oLitEnd>oend_w) return ZSTD_execSequenceLast7(op, oend, sequence, litPtr,
|
|
1256
|
+
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, base, vBase, dictEnd);
|
|
1258
|
+
#endif
|
|
914
1259
|
|
|
915
1260
|
/* copy Literals */
|
|
916
1261
|
ZSTD_copy8(op, *litPtr);
|
|
@@ -920,10 +1265,10 @@ size_t ZSTD_execSequence(BYTE* op,
|
|
|
920
1265
|
*litPtr = iLitEnd; /* update for next sequence */
|
|
921
1266
|
|
|
922
1267
|
/* copy Match */
|
|
1268
|
+
#if 1
|
|
923
1269
|
if (sequence.offset > (size_t)(oLitEnd - base)) {
|
|
924
1270
|
/* offset beyond prefix */
|
|
925
1271
|
if (sequence.offset > (size_t)(oLitEnd - vBase)) return ERROR(corruption_detected);
|
|
926
|
-
match = dictEnd - (base-match);
|
|
927
1272
|
if (match + sequence.matchLength <= dictEnd) {
|
|
928
1273
|
memmove(oLitEnd, match, sequence.matchLength);
|
|
929
1274
|
return sequenceLength;
|
|
@@ -934,19 +1279,20 @@ size_t ZSTD_execSequence(BYTE* op,
|
|
|
934
1279
|
op = oLitEnd + length1;
|
|
935
1280
|
sequence.matchLength -= length1;
|
|
936
1281
|
match = base;
|
|
937
|
-
if (op > oend_w) {
|
|
1282
|
+
if (op > oend_w || sequence.matchLength < MINMATCH) {
|
|
938
1283
|
U32 i;
|
|
939
1284
|
for (i = 0; i < sequence.matchLength; ++i) op[i] = match[i];
|
|
940
1285
|
return sequenceLength;
|
|
941
1286
|
}
|
|
942
1287
|
} }
|
|
943
|
-
/* Requirement: op <= oend_w */
|
|
1288
|
+
/* Requirement: op <= oend_w && sequence.matchLength >= MINMATCH */
|
|
1289
|
+
#endif
|
|
944
1290
|
|
|
945
1291
|
/* match within prefix */
|
|
946
1292
|
if (sequence.offset < 8) {
|
|
947
1293
|
/* close range match, overlap */
|
|
948
1294
|
static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
|
|
949
|
-
static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /*
|
|
1295
|
+
static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* subtracted */
|
|
950
1296
|
int const sub2 = dec64table[sequence.offset];
|
|
951
1297
|
op[0] = match[0];
|
|
952
1298
|
op[1] = match[1];
|
|
@@ -968,13 +1314,12 @@ size_t ZSTD_execSequence(BYTE* op,
|
|
|
968
1314
|
}
|
|
969
1315
|
while (op < oMatchEnd) *op++ = *match++;
|
|
970
1316
|
} else {
|
|
971
|
-
ZSTD_wildcopy(op, match, sequence.matchLength-8); /* works even if matchLength < 8 */
|
|
1317
|
+
ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8); /* works even if matchLength < 8 */
|
|
972
1318
|
}
|
|
973
1319
|
return sequenceLength;
|
|
974
1320
|
}
|
|
975
1321
|
|
|
976
|
-
|
|
977
|
-
static size_t ZSTD_decompressSequences(
|
|
1322
|
+
static size_t ZSTD_decompressSequencesLong(
|
|
978
1323
|
ZSTD_DCtx* dctx,
|
|
979
1324
|
void* dst, size_t maxDstSize,
|
|
980
1325
|
const void* seqStart, size_t seqSize)
|
|
@@ -985,11 +1330,11 @@ static size_t ZSTD_decompressSequences(
|
|
|
985
1330
|
BYTE* const oend = ostart + maxDstSize;
|
|
986
1331
|
BYTE* op = ostart;
|
|
987
1332
|
const BYTE* litPtr = dctx->litPtr;
|
|
988
|
-
const BYTE* const litLimit_w = litPtr + dctx->litBufSize - WILDCOPY_OVERLENGTH;
|
|
989
1333
|
const BYTE* const litEnd = litPtr + dctx->litSize;
|
|
990
1334
|
const BYTE* const base = (const BYTE*) (dctx->base);
|
|
991
1335
|
const BYTE* const vBase = (const BYTE*) (dctx->vBase);
|
|
992
1336
|
const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);
|
|
1337
|
+
unsigned const windowSize = dctx->fParams.windowSize;
|
|
993
1338
|
int nbSeq;
|
|
994
1339
|
|
|
995
1340
|
/* Build Decoding Tables */
|
|
@@ -1000,26 +1345,50 @@ static size_t ZSTD_decompressSequences(
|
|
|
1000
1345
|
|
|
1001
1346
|
/* Regen sequences */
|
|
1002
1347
|
if (nbSeq) {
|
|
1348
|
+
#define STORED_SEQS 4
|
|
1349
|
+
#define STOSEQ_MASK (STORED_SEQS-1)
|
|
1350
|
+
#define ADVANCED_SEQS 4
|
|
1351
|
+
seq_t sequences[STORED_SEQS];
|
|
1352
|
+
int const seqAdvance = MIN(nbSeq, ADVANCED_SEQS);
|
|
1003
1353
|
seqState_t seqState;
|
|
1354
|
+
int seqNb;
|
|
1004
1355
|
dctx->fseEntropy = 1;
|
|
1005
|
-
{ U32 i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->rep[i]; }
|
|
1356
|
+
{ U32 i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }
|
|
1357
|
+
seqState.base = base;
|
|
1358
|
+
seqState.pos = (size_t)(op-base);
|
|
1359
|
+
seqState.gotoDict = (uPtrDiff)dictEnd - (uPtrDiff)base; /* cast to avoid undefined behaviour */
|
|
1006
1360
|
CHECK_E(BIT_initDStream(&seqState.DStream, ip, iend-ip), corruption_detected);
|
|
1007
1361
|
FSE_initDState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
|
|
1008
1362
|
FSE_initDState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
|
|
1009
1363
|
FSE_initDState(&seqState.stateML, &seqState.DStream, dctx->MLTptr);
|
|
1010
1364
|
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1365
|
+
/* prepare in advance */
|
|
1366
|
+
for (seqNb=0; (BIT_reloadDStream(&seqState.DStream) <= BIT_DStream_completed) && seqNb<seqAdvance; seqNb++) {
|
|
1367
|
+
sequences[seqNb] = ZSTD_decodeSequenceLong(&seqState, windowSize);
|
|
1368
|
+
}
|
|
1369
|
+
if (seqNb<seqAdvance) return ERROR(corruption_detected);
|
|
1370
|
+
|
|
1371
|
+
/* decode and decompress */
|
|
1372
|
+
for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && seqNb<nbSeq ; seqNb++) {
|
|
1373
|
+
seq_t const sequence = ZSTD_decodeSequenceLong(&seqState, windowSize);
|
|
1374
|
+
size_t const oneSeqSize = ZSTD_execSequenceLong(op, oend, sequences[(seqNb-ADVANCED_SEQS) & STOSEQ_MASK], &litPtr, litEnd, base, vBase, dictEnd);
|
|
1375
|
+
if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
|
|
1376
|
+
ZSTD_PREFETCH(sequence.match);
|
|
1377
|
+
sequences[seqNb&STOSEQ_MASK] = sequence;
|
|
1378
|
+
op += oneSeqSize;
|
|
1379
|
+
}
|
|
1380
|
+
if (seqNb<nbSeq) return ERROR(corruption_detected);
|
|
1381
|
+
|
|
1382
|
+
/* finish queue */
|
|
1383
|
+
seqNb -= seqAdvance;
|
|
1384
|
+
for ( ; seqNb<nbSeq ; seqNb++) {
|
|
1385
|
+
size_t const oneSeqSize = ZSTD_execSequenceLong(op, oend, sequences[seqNb&STOSEQ_MASK], &litPtr, litEnd, base, vBase, dictEnd);
|
|
1386
|
+
if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
|
|
1387
|
+
op += oneSeqSize;
|
|
1388
|
+
}
|
|
1018
1389
|
|
|
1019
|
-
/* check if reached exact end */
|
|
1020
|
-
if (nbSeq) return ERROR(corruption_detected);
|
|
1021
1390
|
/* save reps for next block */
|
|
1022
|
-
{ U32 i; for (i=0; i<ZSTD_REP_NUM; i++) dctx->rep[i] = (U32)(seqState.prevOffset[i]); }
|
|
1391
|
+
{ U32 i; for (i=0; i<ZSTD_REP_NUM; i++) dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]); }
|
|
1023
1392
|
}
|
|
1024
1393
|
|
|
1025
1394
|
/* last literal segment */
|
|
@@ -1033,17 +1402,6 @@ static size_t ZSTD_decompressSequences(
|
|
|
1033
1402
|
}
|
|
1034
1403
|
|
|
1035
1404
|
|
|
1036
|
-
static void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst)
|
|
1037
|
-
{
|
|
1038
|
-
if (dst != dctx->previousDstEnd) { /* not contiguous */
|
|
1039
|
-
dctx->dictEnd = dctx->previousDstEnd;
|
|
1040
|
-
dctx->vBase = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->base));
|
|
1041
|
-
dctx->base = dst;
|
|
1042
|
-
dctx->previousDstEnd = dst;
|
|
1043
|
-
}
|
|
1044
|
-
}
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
1405
|
static size_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
|
|
1048
1406
|
void* dst, size_t dstCapacity,
|
|
1049
1407
|
const void* src, size_t srcSize)
|
|
@@ -1052,16 +1410,32 @@ static size_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
|
|
|
1052
1410
|
|
|
1053
1411
|
if (srcSize >= ZSTD_BLOCKSIZE_ABSOLUTEMAX) return ERROR(srcSize_wrong);
|
|
1054
1412
|
|
|
1055
|
-
/* Decode literals
|
|
1413
|
+
/* Decode literals section */
|
|
1056
1414
|
{ size_t const litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize);
|
|
1057
1415
|
if (ZSTD_isError(litCSize)) return litCSize;
|
|
1058
1416
|
ip += litCSize;
|
|
1059
1417
|
srcSize -= litCSize;
|
|
1060
1418
|
}
|
|
1419
|
+
if (sizeof(size_t) > 4) /* do not enable prefetching on 32-bits x86, as it's performance detrimental */
|
|
1420
|
+
/* likely because of register pressure */
|
|
1421
|
+
/* if that's the correct cause, then 32-bits ARM should be affected differently */
|
|
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);
|
|
1061
1425
|
return ZSTD_decompressSequences(dctx, dst, dstCapacity, ip, srcSize);
|
|
1062
1426
|
}
|
|
1063
1427
|
|
|
1064
1428
|
|
|
1429
|
+
static void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst)
|
|
1430
|
+
{
|
|
1431
|
+
if (dst != dctx->previousDstEnd) { /* not contiguous */
|
|
1432
|
+
dctx->dictEnd = dctx->previousDstEnd;
|
|
1433
|
+
dctx->vBase = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->base));
|
|
1434
|
+
dctx->base = dst;
|
|
1435
|
+
dctx->previousDstEnd = dst;
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1438
|
+
|
|
1065
1439
|
size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx,
|
|
1066
1440
|
void* dst, size_t dstCapacity,
|
|
1067
1441
|
const void* src, size_t srcSize)
|
|
@@ -1091,27 +1465,81 @@ size_t ZSTD_generateNxBytes(void* dst, size_t dstCapacity, BYTE byte, size_t len
|
|
|
1091
1465
|
return length;
|
|
1092
1466
|
}
|
|
1093
1467
|
|
|
1468
|
+
/** ZSTD_findFrameCompressedSize() :
|
|
1469
|
+
* compatible with legacy mode
|
|
1470
|
+
* `src` must point to the start of a ZSTD frame, ZSTD legacy frame, or skippable frame
|
|
1471
|
+
* `srcSize` must be at least as large as the frame contained
|
|
1472
|
+
* @return : the compressed size of the frame starting at `src` */
|
|
1473
|
+
size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
|
|
1474
|
+
{
|
|
1475
|
+
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
|
|
1476
|
+
if (ZSTD_isLegacy(src, srcSize)) return ZSTD_findFrameCompressedSizeLegacy(src, srcSize);
|
|
1477
|
+
#endif
|
|
1478
|
+
if (srcSize >= ZSTD_skippableHeaderSize &&
|
|
1479
|
+
(MEM_readLE32(src) & 0xFFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
|
|
1480
|
+
return ZSTD_skippableHeaderSize + MEM_readLE32((const BYTE*)src + 4);
|
|
1481
|
+
} else {
|
|
1482
|
+
const BYTE* ip = (const BYTE*)src;
|
|
1483
|
+
const BYTE* const ipstart = ip;
|
|
1484
|
+
size_t remainingSize = srcSize;
|
|
1485
|
+
ZSTD_frameParams fParams;
|
|
1486
|
+
|
|
1487
|
+
size_t const headerSize = ZSTD_frameHeaderSize(ip, remainingSize);
|
|
1488
|
+
if (ZSTD_isError(headerSize)) return headerSize;
|
|
1489
|
+
|
|
1490
|
+
/* Frame Header */
|
|
1491
|
+
{ size_t const ret = ZSTD_getFrameParams(&fParams, ip, remainingSize);
|
|
1492
|
+
if (ZSTD_isError(ret)) return ret;
|
|
1493
|
+
if (ret > 0) return ERROR(srcSize_wrong);
|
|
1494
|
+
}
|
|
1495
|
+
|
|
1496
|
+
ip += headerSize;
|
|
1497
|
+
remainingSize -= headerSize;
|
|
1498
|
+
|
|
1499
|
+
/* Loop on each block */
|
|
1500
|
+
while (1) {
|
|
1501
|
+
blockProperties_t blockProperties;
|
|
1502
|
+
size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
|
|
1503
|
+
if (ZSTD_isError(cBlockSize)) return cBlockSize;
|
|
1504
|
+
|
|
1505
|
+
if (ZSTD_blockHeaderSize + cBlockSize > remainingSize) return ERROR(srcSize_wrong);
|
|
1506
|
+
|
|
1507
|
+
ip += ZSTD_blockHeaderSize + cBlockSize;
|
|
1508
|
+
remainingSize -= ZSTD_blockHeaderSize + cBlockSize;
|
|
1509
|
+
|
|
1510
|
+
if (blockProperties.lastBlock) break;
|
|
1511
|
+
}
|
|
1512
|
+
|
|
1513
|
+
if (fParams.checksumFlag) { /* Frame content checksum */
|
|
1514
|
+
if (remainingSize < 4) return ERROR(srcSize_wrong);
|
|
1515
|
+
ip += 4;
|
|
1516
|
+
remainingSize -= 4;
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1519
|
+
return ip - ipstart;
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1094
1522
|
|
|
1095
1523
|
/*! ZSTD_decompressFrame() :
|
|
1096
|
-
*
|
|
1524
|
+
* @dctx must be properly initialized */
|
|
1097
1525
|
static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|
1098
1526
|
void* dst, size_t dstCapacity,
|
|
1099
|
-
const void
|
|
1527
|
+
const void** srcPtr, size_t *srcSizePtr)
|
|
1100
1528
|
{
|
|
1101
|
-
const BYTE* ip = (const BYTE*)
|
|
1529
|
+
const BYTE* ip = (const BYTE*)(*srcPtr);
|
|
1102
1530
|
BYTE* const ostart = (BYTE* const)dst;
|
|
1103
1531
|
BYTE* const oend = ostart + dstCapacity;
|
|
1104
1532
|
BYTE* op = ostart;
|
|
1105
|
-
size_t remainingSize =
|
|
1533
|
+
size_t remainingSize = *srcSizePtr;
|
|
1106
1534
|
|
|
1107
1535
|
/* check */
|
|
1108
|
-
if (
|
|
1536
|
+
if (remainingSize < ZSTD_frameHeaderSize_min+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
|
|
1109
1537
|
|
|
1110
1538
|
/* Frame Header */
|
|
1111
|
-
{ size_t const frameHeaderSize = ZSTD_frameHeaderSize(
|
|
1539
|
+
{ size_t const frameHeaderSize = ZSTD_frameHeaderSize(ip, ZSTD_frameHeaderSize_prefix);
|
|
1112
1540
|
if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;
|
|
1113
|
-
if (
|
|
1114
|
-
CHECK_F(ZSTD_decodeFrameHeader(dctx,
|
|
1541
|
+
if (remainingSize < frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
|
|
1542
|
+
CHECK_F(ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize));
|
|
1115
1543
|
ip += frameHeaderSize; remainingSize -= frameHeaderSize;
|
|
1116
1544
|
}
|
|
1117
1545
|
|
|
@@ -1156,25 +1584,109 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|
|
1156
1584
|
if (remainingSize<4) return ERROR(checksum_wrong);
|
|
1157
1585
|
checkRead = MEM_readLE32(ip);
|
|
1158
1586
|
if (checkRead != checkCalc) return ERROR(checksum_wrong);
|
|
1587
|
+
ip += 4;
|
|
1159
1588
|
remainingSize -= 4;
|
|
1160
1589
|
}
|
|
1161
1590
|
|
|
1162
|
-
|
|
1591
|
+
/* Allow caller to get size read */
|
|
1592
|
+
*srcPtr = ip;
|
|
1593
|
+
*srcSizePtr = remainingSize;
|
|
1163
1594
|
return op-ostart;
|
|
1164
1595
|
}
|
|
1165
1596
|
|
|
1597
|
+
static const void* ZSTD_DDictDictContent(const ZSTD_DDict* ddict);
|
|
1598
|
+
static size_t ZSTD_DDictDictSize(const ZSTD_DDict* ddict);
|
|
1599
|
+
|
|
1600
|
+
static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|
1601
|
+
void* dst, size_t dstCapacity,
|
|
1602
|
+
const void* src, size_t srcSize,
|
|
1603
|
+
const void *dict, size_t dictSize,
|
|
1604
|
+
const ZSTD_DDict* ddict)
|
|
1605
|
+
{
|
|
1606
|
+
void* const dststart = dst;
|
|
1607
|
+
|
|
1608
|
+
if (ddict) {
|
|
1609
|
+
if (dict) {
|
|
1610
|
+
/* programmer error, these two cases should be mutually exclusive */
|
|
1611
|
+
return ERROR(GENERIC);
|
|
1612
|
+
}
|
|
1613
|
+
|
|
1614
|
+
dict = ZSTD_DDictDictContent(ddict);
|
|
1615
|
+
dictSize = ZSTD_DDictDictSize(ddict);
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1618
|
+
while (srcSize >= ZSTD_frameHeaderSize_prefix) {
|
|
1619
|
+
U32 magicNumber;
|
|
1620
|
+
|
|
1621
|
+
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
|
|
1622
|
+
if (ZSTD_isLegacy(src, srcSize)) {
|
|
1623
|
+
size_t decodedSize;
|
|
1624
|
+
size_t const frameSize = ZSTD_findFrameCompressedSizeLegacy(src, srcSize);
|
|
1625
|
+
if (ZSTD_isError(frameSize)) return frameSize;
|
|
1626
|
+
|
|
1627
|
+
decodedSize = ZSTD_decompressLegacy(dst, dstCapacity, src, frameSize, dict, dictSize);
|
|
1628
|
+
|
|
1629
|
+
dst = (BYTE*)dst + decodedSize;
|
|
1630
|
+
dstCapacity -= decodedSize;
|
|
1631
|
+
|
|
1632
|
+
src = (const BYTE*)src + frameSize;
|
|
1633
|
+
srcSize -= frameSize;
|
|
1634
|
+
|
|
1635
|
+
continue;
|
|
1636
|
+
}
|
|
1637
|
+
#endif
|
|
1638
|
+
|
|
1639
|
+
magicNumber = MEM_readLE32(src);
|
|
1640
|
+
if (magicNumber != ZSTD_MAGICNUMBER) {
|
|
1641
|
+
if ((magicNumber & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
|
|
1642
|
+
size_t skippableSize;
|
|
1643
|
+
if (srcSize < ZSTD_skippableHeaderSize)
|
|
1644
|
+
return ERROR(srcSize_wrong);
|
|
1645
|
+
skippableSize = MEM_readLE32((const BYTE *)src + 4) +
|
|
1646
|
+
ZSTD_skippableHeaderSize;
|
|
1647
|
+
if (srcSize < skippableSize) {
|
|
1648
|
+
return ERROR(srcSize_wrong);
|
|
1649
|
+
}
|
|
1650
|
+
|
|
1651
|
+
src = (const BYTE *)src + skippableSize;
|
|
1652
|
+
srcSize -= skippableSize;
|
|
1653
|
+
continue;
|
|
1654
|
+
} else {
|
|
1655
|
+
return ERROR(prefix_unknown);
|
|
1656
|
+
}
|
|
1657
|
+
}
|
|
1658
|
+
|
|
1659
|
+
if (ddict) {
|
|
1660
|
+
/* we were called from ZSTD_decompress_usingDDict */
|
|
1661
|
+
ZSTD_refDDict(dctx, ddict);
|
|
1662
|
+
} else {
|
|
1663
|
+
/* this will initialize correctly with no dict if dict == NULL, so
|
|
1664
|
+
* use this in all cases but ddict */
|
|
1665
|
+
CHECK_F(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize));
|
|
1666
|
+
}
|
|
1667
|
+
ZSTD_checkContinuity(dctx, dst);
|
|
1668
|
+
|
|
1669
|
+
{ const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity,
|
|
1670
|
+
&src, &srcSize);
|
|
1671
|
+
if (ZSTD_isError(res)) return res;
|
|
1672
|
+
/* don't need to bounds check this, ZSTD_decompressFrame will have
|
|
1673
|
+
* already */
|
|
1674
|
+
dst = (BYTE*)dst + res;
|
|
1675
|
+
dstCapacity -= res;
|
|
1676
|
+
}
|
|
1677
|
+
}
|
|
1678
|
+
|
|
1679
|
+
if (srcSize) return ERROR(srcSize_wrong); /* input not entirely consumed */
|
|
1680
|
+
|
|
1681
|
+
return (BYTE*)dst - (BYTE*)dststart;
|
|
1682
|
+
}
|
|
1166
1683
|
|
|
1167
1684
|
size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
|
|
1168
1685
|
void* dst, size_t dstCapacity,
|
|
1169
1686
|
const void* src, size_t srcSize,
|
|
1170
1687
|
const void* dict, size_t dictSize)
|
|
1171
1688
|
{
|
|
1172
|
-
|
|
1173
|
-
if (ZSTD_isLegacy(src, srcSize)) return ZSTD_decompressLegacy(dst, dstCapacity, src, srcSize, dict, dictSize);
|
|
1174
|
-
#endif
|
|
1175
|
-
ZSTD_decompressBegin_usingDict(dctx, dict, dictSize);
|
|
1176
|
-
ZSTD_checkContinuity(dctx, dst);
|
|
1177
|
-
return ZSTD_decompressFrame(dctx, dst, dstCapacity, src, srcSize);
|
|
1689
|
+
return ZSTD_decompressMultiFrame(dctx, dst, dstCapacity, src, srcSize, dict, dictSize, NULL);
|
|
1178
1690
|
}
|
|
1179
1691
|
|
|
1180
1692
|
|
|
@@ -1361,22 +1873,29 @@ static size_t ZSTD_refDictContent(ZSTD_DCtx* dctx, const void* dict, size_t dict
|
|
|
1361
1873
|
return 0;
|
|
1362
1874
|
}
|
|
1363
1875
|
|
|
1364
|
-
|
|
1876
|
+
/* ZSTD_loadEntropy() :
|
|
1877
|
+
* dict : must point at beginning of a valid zstd dictionary
|
|
1878
|
+
* @return : size of entropy tables read */
|
|
1879
|
+
static size_t ZSTD_loadEntropy(ZSTD_entropyTables_t* entropy, const void* const dict, size_t const dictSize)
|
|
1365
1880
|
{
|
|
1366
1881
|
const BYTE* dictPtr = (const BYTE*)dict;
|
|
1367
1882
|
const BYTE* const dictEnd = dictPtr + dictSize;
|
|
1368
1883
|
|
|
1369
|
-
|
|
1884
|
+
if (dictSize <= 8) return ERROR(dictionary_corrupted);
|
|
1885
|
+
dictPtr += 8; /* skip header = magic + dictID */
|
|
1886
|
+
|
|
1887
|
+
|
|
1888
|
+
{ size_t const hSize = HUF_readDTableX4(entropy->hufTable, dictPtr, dictEnd-dictPtr);
|
|
1370
1889
|
if (HUF_isError(hSize)) return ERROR(dictionary_corrupted);
|
|
1371
1890
|
dictPtr += hSize;
|
|
1372
1891
|
}
|
|
1373
1892
|
|
|
1374
1893
|
{ short offcodeNCount[MaxOff+1];
|
|
1375
|
-
U32 offcodeMaxValue=MaxOff, offcodeLog;
|
|
1894
|
+
U32 offcodeMaxValue = MaxOff, offcodeLog;
|
|
1376
1895
|
size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
|
|
1377
1896
|
if (FSE_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);
|
|
1378
1897
|
if (offcodeLog > OffFSELog) return ERROR(dictionary_corrupted);
|
|
1379
|
-
CHECK_E(FSE_buildDTable(
|
|
1898
|
+
CHECK_E(FSE_buildDTable(entropy->OFTable, offcodeNCount, offcodeMaxValue, offcodeLog), dictionary_corrupted);
|
|
1380
1899
|
dictPtr += offcodeHeaderSize;
|
|
1381
1900
|
}
|
|
1382
1901
|
|
|
@@ -1385,7 +1904,7 @@ static size_t ZSTD_loadEntropy(ZSTD_DCtx* dctx, const void* const dict, size_t c
|
|
|
1385
1904
|
size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
|
|
1386
1905
|
if (FSE_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted);
|
|
1387
1906
|
if (matchlengthLog > MLFSELog) return ERROR(dictionary_corrupted);
|
|
1388
|
-
CHECK_E(FSE_buildDTable(
|
|
1907
|
+
CHECK_E(FSE_buildDTable(entropy->MLTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog), dictionary_corrupted);
|
|
1389
1908
|
dictPtr += matchlengthHeaderSize;
|
|
1390
1909
|
}
|
|
1391
1910
|
|
|
@@ -1394,17 +1913,19 @@ static size_t ZSTD_loadEntropy(ZSTD_DCtx* dctx, const void* const dict, size_t c
|
|
|
1394
1913
|
size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
|
|
1395
1914
|
if (FSE_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted);
|
|
1396
1915
|
if (litlengthLog > LLFSELog) return ERROR(dictionary_corrupted);
|
|
1397
|
-
CHECK_E(FSE_buildDTable(
|
|
1916
|
+
CHECK_E(FSE_buildDTable(entropy->LLTable, litlengthNCount, litlengthMaxValue, litlengthLog), dictionary_corrupted);
|
|
1398
1917
|
dictPtr += litlengthHeaderSize;
|
|
1399
1918
|
}
|
|
1400
1919
|
|
|
1401
1920
|
if (dictPtr+12 > dictEnd) return ERROR(dictionary_corrupted);
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1921
|
+
{ int i;
|
|
1922
|
+
size_t const dictContentSize = (size_t)(dictEnd - (dictPtr+12));
|
|
1923
|
+
for (i=0; i<3; i++) {
|
|
1924
|
+
U32 const rep = MEM_readLE32(dictPtr); dictPtr += 4;
|
|
1925
|
+
if (rep==0 || rep >= dictContentSize) return ERROR(dictionary_corrupted);
|
|
1926
|
+
entropy->rep[i] = rep;
|
|
1927
|
+
} }
|
|
1406
1928
|
|
|
1407
|
-
dctx->litEntropy = dctx->fseEntropy = 1;
|
|
1408
1929
|
return dictPtr - (const BYTE*)dict;
|
|
1409
1930
|
}
|
|
1410
1931
|
|
|
@@ -1418,13 +1939,12 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
|
|
|
1418
1939
|
dctx->dictID = MEM_readLE32((const char*)dict + 4);
|
|
1419
1940
|
|
|
1420
1941
|
/* load entropy tables */
|
|
1421
|
-
|
|
1422
|
-
dictSize -= 8;
|
|
1423
|
-
{ size_t const eSize = ZSTD_loadEntropy(dctx, dict, dictSize);
|
|
1942
|
+
{ size_t const eSize = ZSTD_loadEntropy(&dctx->entropy, dict, dictSize);
|
|
1424
1943
|
if (ZSTD_isError(eSize)) return ERROR(dictionary_corrupted);
|
|
1425
1944
|
dict = (const char*)dict + eSize;
|
|
1426
1945
|
dictSize -= eSize;
|
|
1427
1946
|
}
|
|
1947
|
+
dctx->litEntropy = dctx->fseEntropy = 1;
|
|
1428
1948
|
|
|
1429
1949
|
/* reference dictionary content */
|
|
1430
1950
|
return ZSTD_refDictContent(dctx, dict, dictSize);
|
|
@@ -1441,60 +1961,127 @@ size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t
|
|
|
1441
1961
|
/* ====== ZSTD_DDict ====== */
|
|
1442
1962
|
|
|
1443
1963
|
struct ZSTD_DDict_s {
|
|
1444
|
-
void*
|
|
1964
|
+
void* dictBuffer;
|
|
1965
|
+
const void* dictContent;
|
|
1445
1966
|
size_t dictSize;
|
|
1446
|
-
|
|
1967
|
+
ZSTD_entropyTables_t entropy;
|
|
1968
|
+
U32 dictID;
|
|
1969
|
+
U32 entropyPresent;
|
|
1970
|
+
ZSTD_customMem cMem;
|
|
1447
1971
|
}; /* typedef'd to ZSTD_DDict within "zstd.h" */
|
|
1448
1972
|
|
|
1449
|
-
|
|
1973
|
+
static const void* ZSTD_DDictDictContent(const ZSTD_DDict* ddict)
|
|
1974
|
+
{
|
|
1975
|
+
return ddict->dictContent;
|
|
1976
|
+
}
|
|
1977
|
+
|
|
1978
|
+
static size_t ZSTD_DDictDictSize(const ZSTD_DDict* ddict)
|
|
1979
|
+
{
|
|
1980
|
+
return ddict->dictSize;
|
|
1981
|
+
}
|
|
1982
|
+
|
|
1983
|
+
static void ZSTD_refDDict(ZSTD_DCtx* dstDCtx, const ZSTD_DDict* ddict)
|
|
1984
|
+
{
|
|
1985
|
+
ZSTD_decompressBegin(dstDCtx); /* init */
|
|
1986
|
+
if (ddict) { /* support refDDict on NULL */
|
|
1987
|
+
dstDCtx->dictID = ddict->dictID;
|
|
1988
|
+
dstDCtx->base = ddict->dictContent;
|
|
1989
|
+
dstDCtx->vBase = ddict->dictContent;
|
|
1990
|
+
dstDCtx->dictEnd = (const BYTE*)ddict->dictContent + ddict->dictSize;
|
|
1991
|
+
dstDCtx->previousDstEnd = dstDCtx->dictEnd;
|
|
1992
|
+
if (ddict->entropyPresent) {
|
|
1993
|
+
dstDCtx->litEntropy = 1;
|
|
1994
|
+
dstDCtx->fseEntropy = 1;
|
|
1995
|
+
dstDCtx->LLTptr = ddict->entropy.LLTable;
|
|
1996
|
+
dstDCtx->MLTptr = ddict->entropy.MLTable;
|
|
1997
|
+
dstDCtx->OFTptr = ddict->entropy.OFTable;
|
|
1998
|
+
dstDCtx->HUFptr = ddict->entropy.hufTable;
|
|
1999
|
+
dstDCtx->entropy.rep[0] = ddict->entropy.rep[0];
|
|
2000
|
+
dstDCtx->entropy.rep[1] = ddict->entropy.rep[1];
|
|
2001
|
+
dstDCtx->entropy.rep[2] = ddict->entropy.rep[2];
|
|
2002
|
+
} else {
|
|
2003
|
+
dstDCtx->litEntropy = 0;
|
|
2004
|
+
dstDCtx->fseEntropy = 0;
|
|
2005
|
+
}
|
|
2006
|
+
}
|
|
2007
|
+
}
|
|
2008
|
+
|
|
2009
|
+
static size_t ZSTD_loadEntropy_inDDict(ZSTD_DDict* ddict)
|
|
2010
|
+
{
|
|
2011
|
+
ddict->dictID = 0;
|
|
2012
|
+
ddict->entropyPresent = 0;
|
|
2013
|
+
if (ddict->dictSize < 8) return 0;
|
|
2014
|
+
{ U32 const magic = MEM_readLE32(ddict->dictContent);
|
|
2015
|
+
if (magic != ZSTD_DICT_MAGIC) return 0; /* pure content mode */
|
|
2016
|
+
}
|
|
2017
|
+
ddict->dictID = MEM_readLE32((const char*)ddict->dictContent + 4);
|
|
2018
|
+
|
|
2019
|
+
/* load entropy tables */
|
|
2020
|
+
CHECK_E( ZSTD_loadEntropy(&ddict->entropy, ddict->dictContent, ddict->dictSize), dictionary_corrupted );
|
|
2021
|
+
ddict->entropyPresent = 1;
|
|
2022
|
+
return 0;
|
|
2023
|
+
}
|
|
2024
|
+
|
|
2025
|
+
|
|
2026
|
+
ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize, unsigned byReference, ZSTD_customMem customMem)
|
|
1450
2027
|
{
|
|
1451
2028
|
if (!customMem.customAlloc && !customMem.customFree) customMem = defaultCustomMem;
|
|
1452
2029
|
if (!customMem.customAlloc || !customMem.customFree) return NULL;
|
|
1453
2030
|
|
|
1454
2031
|
{ ZSTD_DDict* const ddict = (ZSTD_DDict*) ZSTD_malloc(sizeof(ZSTD_DDict), customMem);
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
if (!dictContent || !ddict || !dctx) {
|
|
1459
|
-
ZSTD_free(dictContent, customMem);
|
|
1460
|
-
ZSTD_free(ddict, customMem);
|
|
1461
|
-
ZSTD_free(dctx, customMem);
|
|
1462
|
-
return NULL;
|
|
1463
|
-
}
|
|
2032
|
+
if (!ddict) return NULL;
|
|
2033
|
+
ddict->cMem = customMem;
|
|
1464
2034
|
|
|
1465
|
-
if (dictSize) {
|
|
1466
|
-
|
|
2035
|
+
if ((byReference) || (!dict) || (!dictSize)) {
|
|
2036
|
+
ddict->dictBuffer = NULL;
|
|
2037
|
+
ddict->dictContent = dict;
|
|
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;
|
|
1467
2044
|
}
|
|
1468
|
-
|
|
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);
|
|
1469
2049
|
if (ZSTD_isError(errorCode)) {
|
|
1470
|
-
|
|
1471
|
-
ZSTD_free(ddict, customMem);
|
|
1472
|
-
ZSTD_free(dctx, customMem);
|
|
2050
|
+
ZSTD_freeDDict(ddict);
|
|
1473
2051
|
return NULL;
|
|
1474
2052
|
} }
|
|
1475
2053
|
|
|
1476
|
-
ddict->dict = dictContent;
|
|
1477
|
-
ddict->dictSize = dictSize;
|
|
1478
|
-
ddict->refContext = dctx;
|
|
1479
2054
|
return ddict;
|
|
1480
2055
|
}
|
|
1481
2056
|
}
|
|
1482
2057
|
|
|
1483
2058
|
/*! ZSTD_createDDict() :
|
|
1484
|
-
* Create a digested dictionary,
|
|
1485
|
-
* `dict`
|
|
2059
|
+
* Create a digested dictionary, to start decompression without startup delay.
|
|
2060
|
+
* `dict` content is copied inside DDict.
|
|
2061
|
+
* Consequently, `dict` can be released after `ZSTD_DDict` creation */
|
|
1486
2062
|
ZSTD_DDict* ZSTD_createDDict(const void* dict, size_t dictSize)
|
|
1487
2063
|
{
|
|
1488
2064
|
ZSTD_customMem const allocator = { NULL, NULL, NULL };
|
|
1489
|
-
return ZSTD_createDDict_advanced(dict, dictSize, allocator);
|
|
2065
|
+
return ZSTD_createDDict_advanced(dict, dictSize, 0, allocator);
|
|
2066
|
+
}
|
|
2067
|
+
|
|
2068
|
+
|
|
2069
|
+
/*! ZSTD_createDDict_byReference() :
|
|
2070
|
+
* Create a digested dictionary, to start decompression without startup delay.
|
|
2071
|
+
* Dictionary content is simply referenced, it will be accessed during decompression.
|
|
2072
|
+
* Warning : dictBuffer must outlive DDict (DDict must be freed before dictBuffer) */
|
|
2073
|
+
ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize)
|
|
2074
|
+
{
|
|
2075
|
+
ZSTD_customMem const allocator = { NULL, NULL, NULL };
|
|
2076
|
+
return ZSTD_createDDict_advanced(dictBuffer, dictSize, 1, allocator);
|
|
1490
2077
|
}
|
|
1491
2078
|
|
|
2079
|
+
|
|
1492
2080
|
size_t ZSTD_freeDDict(ZSTD_DDict* ddict)
|
|
1493
2081
|
{
|
|
1494
2082
|
if (ddict==NULL) return 0; /* support free on NULL */
|
|
1495
|
-
{ ZSTD_customMem const cMem = ddict->
|
|
1496
|
-
|
|
1497
|
-
ZSTD_free(ddict->dict, cMem);
|
|
2083
|
+
{ ZSTD_customMem const cMem = ddict->cMem;
|
|
2084
|
+
ZSTD_free(ddict->dictBuffer, cMem);
|
|
1498
2085
|
ZSTD_free(ddict, cMem);
|
|
1499
2086
|
return 0;
|
|
1500
2087
|
}
|
|
@@ -1503,7 +2090,46 @@ size_t ZSTD_freeDDict(ZSTD_DDict* ddict)
|
|
|
1503
2090
|
size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict)
|
|
1504
2091
|
{
|
|
1505
2092
|
if (ddict==NULL) return 0; /* support sizeof on NULL */
|
|
1506
|
-
return sizeof(*ddict) +
|
|
2093
|
+
return sizeof(*ddict) + (ddict->dictBuffer ? ddict->dictSize : 0) ;
|
|
2094
|
+
}
|
|
2095
|
+
|
|
2096
|
+
/*! ZSTD_getDictID_fromDict() :
|
|
2097
|
+
* Provides the dictID stored within dictionary.
|
|
2098
|
+
* if @return == 0, the dictionary is not conformant with Zstandard specification.
|
|
2099
|
+
* It can still be loaded, but as a content-only dictionary. */
|
|
2100
|
+
unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize)
|
|
2101
|
+
{
|
|
2102
|
+
if (dictSize < 8) return 0;
|
|
2103
|
+
if (MEM_readLE32(dict) != ZSTD_DICT_MAGIC) return 0;
|
|
2104
|
+
return MEM_readLE32((const char*)dict + 4);
|
|
2105
|
+
}
|
|
2106
|
+
|
|
2107
|
+
/*! ZSTD_getDictID_fromDDict() :
|
|
2108
|
+
* Provides the dictID of the dictionary loaded into `ddict`.
|
|
2109
|
+
* If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.
|
|
2110
|
+
* Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */
|
|
2111
|
+
unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict)
|
|
2112
|
+
{
|
|
2113
|
+
if (ddict==NULL) return 0;
|
|
2114
|
+
return ZSTD_getDictID_fromDict(ddict->dictContent, ddict->dictSize);
|
|
2115
|
+
}
|
|
2116
|
+
|
|
2117
|
+
/*! ZSTD_getDictID_fromFrame() :
|
|
2118
|
+
* Provides the dictID required to decompressed the frame stored within `src`.
|
|
2119
|
+
* If @return == 0, the dictID could not be decoded.
|
|
2120
|
+
* This could for one of the following reasons :
|
|
2121
|
+
* - The frame does not require a dictionary to be decoded (most common case).
|
|
2122
|
+
* - The frame was built with dictID intentionally removed. Whatever dictionary is necessary is a hidden information.
|
|
2123
|
+
* Note : this use case also happens when using a non-conformant dictionary.
|
|
2124
|
+
* - `srcSize` is too small, and as a result, the frame header could not be decoded (only possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`).
|
|
2125
|
+
* - This is not a Zstandard frame.
|
|
2126
|
+
* When identifying the exact failure cause, it's possible to used ZSTD_getFrameParams(), which will provide a more precise error code. */
|
|
2127
|
+
unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize)
|
|
2128
|
+
{
|
|
2129
|
+
ZSTD_frameParams zfp = { 0 , 0 , 0 , 0 };
|
|
2130
|
+
size_t const hError = ZSTD_getFrameParams(&zfp, src, srcSize);
|
|
2131
|
+
if (ZSTD_isError(hError)) return 0;
|
|
2132
|
+
return zfp.dictID;
|
|
1507
2133
|
}
|
|
1508
2134
|
|
|
1509
2135
|
|
|
@@ -1515,12 +2141,10 @@ size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
|
|
|
1515
2141
|
const void* src, size_t srcSize,
|
|
1516
2142
|
const ZSTD_DDict* ddict)
|
|
1517
2143
|
{
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
ZSTD_checkContinuity(dctx, dst);
|
|
1523
|
-
return ZSTD_decompressFrame(dctx, dst, dstCapacity, src, srcSize);
|
|
2144
|
+
/* pass content and size in case legacy frames are encountered */
|
|
2145
|
+
return ZSTD_decompressMultiFrame(dctx, dst, dstCapacity, src, srcSize,
|
|
2146
|
+
NULL, 0,
|
|
2147
|
+
ddict);
|
|
1524
2148
|
}
|
|
1525
2149
|
|
|
1526
2150
|
|
|
@@ -1608,7 +2232,7 @@ size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t di
|
|
|
1608
2232
|
zds->stage = zdss_loadHeader;
|
|
1609
2233
|
zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
|
|
1610
2234
|
ZSTD_freeDDict(zds->ddictLocal);
|
|
1611
|
-
if (dict) {
|
|
2235
|
+
if (dict && dictSize >= 8) {
|
|
1612
2236
|
zds->ddictLocal = ZSTD_createDDict(dict, dictSize);
|
|
1613
2237
|
if (zds->ddictLocal == NULL) return ERROR(memory_allocation);
|
|
1614
2238
|
} else zds->ddictLocal = NULL;
|
|
@@ -1645,7 +2269,7 @@ size_t ZSTD_setDStreamParameter(ZSTD_DStream* zds,
|
|
|
1645
2269
|
switch(paramType)
|
|
1646
2270
|
{
|
|
1647
2271
|
default : return ERROR(parameter_unknown);
|
|
1648
|
-
case
|
|
2272
|
+
case DStream_p_maxWindowSize : zds->maxWindowSize = paramValue ? paramValue : (U32)(-1); break;
|
|
1649
2273
|
}
|
|
1650
2274
|
return 0;
|
|
1651
2275
|
}
|
|
@@ -1687,7 +2311,8 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1687
2311
|
switch(zds->stage)
|
|
1688
2312
|
{
|
|
1689
2313
|
case zdss_init :
|
|
1690
|
-
|
|
2314
|
+
ZSTD_resetDStream(zds); /* transparent reset on starting decoding a new frame */
|
|
2315
|
+
/* fall-through */
|
|
1691
2316
|
|
|
1692
2317
|
case zdss_loadHeader :
|
|
1693
2318
|
{ size_t const hSize = ZSTD_getFrameParams(&zds->fParams, zds->headerBuffer, zds->lhSize);
|
|
@@ -1695,7 +2320,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1695
2320
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
|
1696
2321
|
{ U32 const legacyVersion = ZSTD_isLegacy(istart, iend-istart);
|
|
1697
2322
|
if (legacyVersion) {
|
|
1698
|
-
const void* const dict = zds->ddict ? zds->ddict->
|
|
2323
|
+
const void* const dict = zds->ddict ? zds->ddict->dictContent : NULL;
|
|
1699
2324
|
size_t const dictSize = zds->ddict ? zds->ddict->dictSize : 0;
|
|
1700
2325
|
CHECK_F(ZSTD_initLegacyStream(&zds->legacyContext, zds->previousLegacyVersion, legacyVersion,
|
|
1701
2326
|
dict, dictSize));
|
|
@@ -1719,10 +2344,23 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1719
2344
|
break;
|
|
1720
2345
|
} }
|
|
1721
2346
|
|
|
2347
|
+
/* check for single-pass mode opportunity */
|
|
2348
|
+
if (zds->fParams.frameContentSize && zds->fParams.windowSize /* skippable frame if == 0 */
|
|
2349
|
+
&& (U64)(size_t)(oend-op) >= zds->fParams.frameContentSize) {
|
|
2350
|
+
size_t const cSize = ZSTD_findFrameCompressedSize(istart, iend-istart);
|
|
2351
|
+
if (cSize <= (size_t)(iend-istart)) {
|
|
2352
|
+
size_t const decompressedSize = ZSTD_decompress_usingDDict(zds->dctx, op, oend-op, istart, cSize, zds->ddict);
|
|
2353
|
+
if (ZSTD_isError(decompressedSize)) return decompressedSize;
|
|
2354
|
+
ip = istart + cSize;
|
|
2355
|
+
op += decompressedSize;
|
|
2356
|
+
zds->dctx->expected = 0;
|
|
2357
|
+
zds->stage = zdss_init;
|
|
2358
|
+
someMoreWork = 0;
|
|
2359
|
+
break;
|
|
2360
|
+
} }
|
|
2361
|
+
|
|
1722
2362
|
/* Consume header */
|
|
1723
|
-
|
|
1724
|
-
ZSTD_refDCtx(zds->dctx, refContext);
|
|
1725
|
-
}
|
|
2363
|
+
ZSTD_refDDict(zds->dctx, zds->ddict);
|
|
1726
2364
|
{ size_t const h1Size = ZSTD_nextSrcSizeToDecompress(zds->dctx); /* == ZSTD_frameHeaderSize_prefix */
|
|
1727
2365
|
CHECK_F(ZSTD_decompressContinue(zds->dctx, NULL, 0, zds->headerBuffer, h1Size));
|
|
1728
2366
|
{ size_t const h2Size = ZSTD_nextSrcSizeToDecompress(zds->dctx);
|
|
@@ -1734,7 +2372,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
|
1734
2372
|
|
|
1735
2373
|
/* Adapt buffer sizes to frame header instructions */
|
|
1736
2374
|
{ size_t const blockSize = MIN(zds->fParams.windowSize, ZSTD_BLOCKSIZE_ABSOLUTEMAX);
|
|
1737
|
-
size_t const neededOutSize = zds->fParams.windowSize + blockSize;
|
|
2375
|
+
size_t const neededOutSize = zds->fParams.windowSize + blockSize + WILDCOPY_OVERLENGTH * 2;
|
|
1738
2376
|
zds->blockSize = blockSize;
|
|
1739
2377
|
if (zds->inBuffSize < blockSize) {
|
|
1740
2378
|
ZSTD_free(zds->inBuff, zds->customMem);
|