zstd-ruby 1.1.3.0 → 1.1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/ext/zstdruby/libzstd/Makefile +9 -6
- data/ext/zstdruby/libzstd/common/bitstream.h +3 -0
- data/ext/zstdruby/libzstd/common/entropy_common.c +13 -19
- data/ext/zstdruby/libzstd/common/fse.h +48 -22
- data/ext/zstdruby/libzstd/common/fse_decompress.c +0 -1
- data/ext/zstdruby/libzstd/common/huf.h +27 -5
- data/ext/zstdruby/libzstd/common/mem.h +14 -12
- data/ext/zstdruby/libzstd/common/threading.c +5 -4
- data/ext/zstdruby/libzstd/common/threading.h +1 -1
- data/ext/zstdruby/libzstd/common/xxhash.c +3 -1
- data/ext/zstdruby/libzstd/common/xxhash.h +11 -15
- data/ext/zstdruby/libzstd/common/zstd_common.c +1 -1
- data/ext/zstdruby/libzstd/common/zstd_internal.h +4 -0
- data/ext/zstdruby/libzstd/compress/fse_compress.c +16 -9
- data/ext/zstdruby/libzstd/compress/huf_compress.c +103 -28
- data/ext/zstdruby/libzstd/compress/zstd_compress.c +90 -37
- data/ext/zstdruby/libzstd/compress/zstd_opt.h +1 -1
- data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +7 -8
- data/ext/zstdruby/libzstd/decompress/huf_decompress.c +20 -17
- data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +429 -120
- data/ext/zstdruby/libzstd/deprecated/zbuff.h +3 -1
- data/ext/zstdruby/libzstd/dictBuilder/cover.c +16 -8
- data/ext/zstdruby/libzstd/dictBuilder/zdict.h +1 -1
- data/ext/zstdruby/libzstd/dll/example/build_package.bat +1 -0
- data/ext/zstdruby/libzstd/dll/libzstd.def +2 -0
- data/ext/zstdruby/libzstd/legacy/zstd_legacy.h +122 -7
- data/ext/zstdruby/libzstd/legacy/zstd_v01.c +31 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v01.h +8 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v02.c +37 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v02.h +8 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v03.c +37 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v03.h +8 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v04.c +33 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v04.h +8 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v05.c +29 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v05.h +7 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v06.c +32 -1
- data/ext/zstdruby/libzstd/legacy/zstd_v06.h +7 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v07.c +44 -6
- data/ext/zstdruby/libzstd/legacy/zstd_v07.h +8 -0
- data/ext/zstdruby/libzstd/zstd.h +87 -13
- data/lib/zstd-ruby/version.rb +1 -1
- metadata +2 -2
@@ -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
|
@@ -87,22 +85,26 @@ typedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader,
|
|
87
85
|
ZSTDds_decompressLastBlock, ZSTDds_checkChecksum,
|
88
86
|
ZSTDds_decodeSkippableHeader, ZSTDds_skipFrame } ZSTD_dStage;
|
89
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
|
+
|
90
96
|
struct ZSTD_DCtx_s
|
91
97
|
{
|
92
98
|
const FSE_DTable* LLTptr;
|
93
99
|
const FSE_DTable* MLTptr;
|
94
100
|
const FSE_DTable* OFTptr;
|
95
101
|
const HUF_DTable* HUFptr;
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
const void*
|
101
|
-
const void* base;
|
102
|
-
const void* vBase;
|
103
|
-
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 */
|
104
107
|
size_t expected;
|
105
|
-
U32 rep[ZSTD_REP_NUM];
|
106
108
|
ZSTD_frameParams fParams;
|
107
109
|
blockType_e bType; /* used in ZSTD_decompressContinue(), to transfer blockType between header decoding and block decoding stages */
|
108
110
|
ZSTD_dStage stage;
|
@@ -131,15 +133,15 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
|
|
131
133
|
dctx->base = NULL;
|
132
134
|
dctx->vBase = NULL;
|
133
135
|
dctx->dictEnd = NULL;
|
134
|
-
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 */
|
135
137
|
dctx->litEntropy = dctx->fseEntropy = 0;
|
136
138
|
dctx->dictID = 0;
|
137
|
-
MEM_STATIC_ASSERT(sizeof(dctx->rep) == sizeof(repStartValue));
|
138
|
-
memcpy(dctx->rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */
|
139
|
-
dctx->LLTptr = dctx->LLTable;
|
140
|
-
dctx->MLTptr = dctx->MLTable;
|
141
|
-
dctx->OFTptr = dctx->OFTable;
|
142
|
-
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;
|
143
145
|
return 0;
|
144
146
|
}
|
145
147
|
|
@@ -175,6 +177,8 @@ void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
|
|
175
177
|
memcpy(dstDCtx, srcDCtx, sizeof(ZSTD_DCtx) - workSpaceSize); /* no need to copy workspace */
|
176
178
|
}
|
177
179
|
|
180
|
+
#if 0
|
181
|
+
/* deprecated */
|
178
182
|
static void ZSTD_refDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
|
179
183
|
{
|
180
184
|
ZSTD_decompressBegin(dstDCtx); /* init */
|
@@ -186,15 +190,18 @@ static void ZSTD_refDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
|
|
186
190
|
dstDCtx->dictID = srcDCtx->dictID;
|
187
191
|
dstDCtx->litEntropy = srcDCtx->litEntropy;
|
188
192
|
dstDCtx->fseEntropy = srcDCtx->fseEntropy;
|
189
|
-
dstDCtx->LLTptr = srcDCtx->LLTable;
|
190
|
-
dstDCtx->MLTptr = srcDCtx->MLTable;
|
191
|
-
dstDCtx->OFTptr = srcDCtx->OFTable;
|
192
|
-
dstDCtx->HUFptr = srcDCtx->hufTable;
|
193
|
-
dstDCtx->rep[0] = srcDCtx->rep[0];
|
194
|
-
dstDCtx->rep[1] = srcDCtx->rep[1];
|
195
|
-
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];
|
196
200
|
}
|
197
201
|
}
|
202
|
+
#endif
|
203
|
+
|
204
|
+
static void ZSTD_refDDict(ZSTD_DCtx* dstDCtx, const ZSTD_DDict* ddict);
|
198
205
|
|
199
206
|
|
200
207
|
/*-*************************************************************
|
@@ -306,6 +313,86 @@ size_t ZSTD_getFrameParams(ZSTD_frameParams* fparamsPtr, const void* src, size_t
|
|
306
313
|
return 0;
|
307
314
|
}
|
308
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
|
+
}
|
309
396
|
|
310
397
|
/** ZSTD_getDecompressedSize() :
|
311
398
|
* compatible with legacy mode
|
@@ -316,14 +403,8 @@ size_t ZSTD_getFrameParams(ZSTD_frameParams* fparamsPtr, const void* src, size_t
|
|
316
403
|
- frame header not complete (`srcSize` too small) */
|
317
404
|
unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize)
|
318
405
|
{
|
319
|
-
|
320
|
-
|
321
|
-
#endif
|
322
|
-
{ ZSTD_frameParams fparams;
|
323
|
-
size_t const frResult = ZSTD_getFrameParams(&fparams, src, srcSize);
|
324
|
-
if (frResult!=0) return 0;
|
325
|
-
return fparams.frameContentSize;
|
326
|
-
}
|
406
|
+
unsigned long long const ret = ZSTD_getFrameContentSize(src, srcSize);
|
407
|
+
return ret >= ZSTD_CONTENTSIZE_ERROR ? 0 : ret;
|
327
408
|
}
|
328
409
|
|
329
410
|
|
@@ -432,14 +513,14 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
|
|
432
513
|
HUF_decompress1X_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->HUFptr) :
|
433
514
|
HUF_decompress4X_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->HUFptr) ) :
|
434
515
|
( singleStream ?
|
435
|
-
HUF_decompress1X2_DCtx(dctx->hufTable, dctx->litBuffer, litSize, istart+lhSize, litCSize) :
|
436
|
-
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)) ))
|
437
518
|
return ERROR(corruption_detected);
|
438
519
|
|
439
520
|
dctx->litPtr = dctx->litBuffer;
|
440
521
|
dctx->litSize = litSize;
|
441
522
|
dctx->litEntropy = 1;
|
442
|
-
if (litEncType==set_compressed) dctx->HUFptr = dctx->hufTable;
|
523
|
+
if (litEncType==set_compressed) dctx->HUFptr = dctx->entropy.hufTable;
|
443
524
|
memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);
|
444
525
|
return litCSize + lhSize;
|
445
526
|
}
|
@@ -756,19 +837,19 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
|
|
756
837
|
ip++;
|
757
838
|
|
758
839
|
/* Build DTables */
|
759
|
-
{ size_t const llhSize = ZSTD_buildSeqTable(dctx->LLTable, &dctx->LLTptr,
|
840
|
+
{ size_t const llhSize = ZSTD_buildSeqTable(dctx->entropy.LLTable, &dctx->LLTptr,
|
760
841
|
LLtype, MaxLL, LLFSELog,
|
761
842
|
ip, iend-ip, LL_defaultDTable, dctx->fseEntropy);
|
762
843
|
if (ZSTD_isError(llhSize)) return ERROR(corruption_detected);
|
763
844
|
ip += llhSize;
|
764
845
|
}
|
765
|
-
{ size_t const ofhSize = ZSTD_buildSeqTable(dctx->OFTable, &dctx->OFTptr,
|
846
|
+
{ size_t const ofhSize = ZSTD_buildSeqTable(dctx->entropy.OFTable, &dctx->OFTptr,
|
766
847
|
OFtype, MaxOff, OffFSELog,
|
767
848
|
ip, iend-ip, OF_defaultDTable, dctx->fseEntropy);
|
768
849
|
if (ZSTD_isError(ofhSize)) return ERROR(corruption_detected);
|
769
850
|
ip += ofhSize;
|
770
851
|
}
|
771
|
-
{ size_t const mlhSize = ZSTD_buildSeqTable(dctx->MLTable, &dctx->MLTptr,
|
852
|
+
{ size_t const mlhSize = ZSTD_buildSeqTable(dctx->entropy.MLTable, &dctx->MLTptr,
|
772
853
|
MLtype, MaxML, MLFSELog,
|
773
854
|
ip, iend-ip, ML_defaultDTable, dctx->fseEntropy);
|
774
855
|
if (ZSTD_isError(mlhSize)) return ERROR(corruption_detected);
|
@@ -795,7 +876,7 @@ typedef struct {
|
|
795
876
|
size_t prevOffset[ZSTD_REP_NUM];
|
796
877
|
const BYTE* base;
|
797
878
|
size_t pos;
|
798
|
-
|
879
|
+
uPtrDiff gotoDict;
|
799
880
|
} seqState_t;
|
800
881
|
|
801
882
|
|
@@ -925,9 +1006,9 @@ static seq_t ZSTD_decodeSequence(seqState_t* seqState)
|
|
925
1006
|
|
926
1007
|
FORCE_INLINE
|
927
1008
|
size_t ZSTD_execSequence(BYTE* op,
|
928
|
-
|
929
|
-
|
930
|
-
|
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)
|
931
1012
|
{
|
932
1013
|
BYTE* const oLitEnd = op + sequence.litLength;
|
933
1014
|
size_t const sequenceLength = sequence.litLength + sequence.matchLength;
|
@@ -952,7 +1033,7 @@ size_t ZSTD_execSequence(BYTE* op,
|
|
952
1033
|
if (sequence.offset > (size_t)(oLitEnd - base)) {
|
953
1034
|
/* offset beyond prefix */
|
954
1035
|
if (sequence.offset > (size_t)(oLitEnd - vBase)) return ERROR(corruption_detected);
|
955
|
-
match
|
1036
|
+
match = dictEnd + (match - base);
|
956
1037
|
if (match + sequence.matchLength <= dictEnd) {
|
957
1038
|
memmove(oLitEnd, match, sequence.matchLength);
|
958
1039
|
return sequenceLength;
|
@@ -975,7 +1056,7 @@ size_t ZSTD_execSequence(BYTE* op,
|
|
975
1056
|
if (sequence.offset < 8) {
|
976
1057
|
/* close range match, overlap */
|
977
1058
|
static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
|
978
|
-
static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /*
|
1059
|
+
static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* subtracted */
|
979
1060
|
int const sub2 = dec64table[sequence.offset];
|
980
1061
|
op[0] = match[0];
|
981
1062
|
op[1] = match[1];
|
@@ -1030,7 +1111,7 @@ static size_t ZSTD_decompressSequences(
|
|
1030
1111
|
if (nbSeq) {
|
1031
1112
|
seqState_t seqState;
|
1032
1113
|
dctx->fseEntropy = 1;
|
1033
|
-
{ U32 i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->rep[i]; }
|
1114
|
+
{ U32 i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }
|
1034
1115
|
CHECK_E(BIT_initDStream(&seqState.DStream, ip, iend-ip), corruption_detected);
|
1035
1116
|
FSE_initDState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
|
1036
1117
|
FSE_initDState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
|
@@ -1047,7 +1128,7 @@ static size_t ZSTD_decompressSequences(
|
|
1047
1128
|
/* check if reached exact end */
|
1048
1129
|
if (nbSeq) return ERROR(corruption_detected);
|
1049
1130
|
/* save reps for next block */
|
1050
|
-
{ U32 i; for (i=0; i<ZSTD_REP_NUM; i++) dctx->rep[i] = (U32)(seqState.prevOffset[i]); }
|
1131
|
+
{ U32 i; for (i=0; i<ZSTD_REP_NUM; i++) dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]); }
|
1051
1132
|
}
|
1052
1133
|
|
1053
1134
|
/* last literal segment */
|
@@ -1061,7 +1142,7 @@ static size_t ZSTD_decompressSequences(
|
|
1061
1142
|
}
|
1062
1143
|
|
1063
1144
|
|
1064
|
-
|
1145
|
+
FORCE_INLINE seq_t ZSTD_decodeSequenceLong_generic(seqState_t* seqState, int const longOffsets)
|
1065
1146
|
{
|
1066
1147
|
seq_t seq;
|
1067
1148
|
|
@@ -1096,8 +1177,15 @@ static seq_t ZSTD_decodeSequenceLong(seqState_t* seqState)
|
|
1096
1177
|
if (!ofCode)
|
1097
1178
|
offset = 0;
|
1098
1179
|
else {
|
1099
|
-
|
1100
|
-
|
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
|
+
}
|
1101
1189
|
}
|
1102
1190
|
|
1103
1191
|
if (ofCode <= 1) {
|
@@ -1141,6 +1229,14 @@ static seq_t ZSTD_decodeSequenceLong(seqState_t* seqState)
|
|
1141
1229
|
return seq;
|
1142
1230
|
}
|
1143
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
|
+
|
1144
1240
|
FORCE_INLINE
|
1145
1241
|
size_t ZSTD_execSequenceLong(BYTE* op,
|
1146
1242
|
BYTE* const oend, seq_t sequence,
|
@@ -1196,7 +1292,7 @@ size_t ZSTD_execSequenceLong(BYTE* op,
|
|
1196
1292
|
if (sequence.offset < 8) {
|
1197
1293
|
/* close range match, overlap */
|
1198
1294
|
static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
|
1199
|
-
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 */
|
1200
1296
|
int const sub2 = dec64table[sequence.offset];
|
1201
1297
|
op[0] = match[0];
|
1202
1298
|
op[1] = match[1];
|
@@ -1238,6 +1334,7 @@ static size_t ZSTD_decompressSequencesLong(
|
|
1238
1334
|
const BYTE* const base = (const BYTE*) (dctx->base);
|
1239
1335
|
const BYTE* const vBase = (const BYTE*) (dctx->vBase);
|
1240
1336
|
const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);
|
1337
|
+
unsigned const windowSize = dctx->fParams.windowSize;
|
1241
1338
|
int nbSeq;
|
1242
1339
|
|
1243
1340
|
/* Build Decoding Tables */
|
@@ -1256,10 +1353,10 @@ static size_t ZSTD_decompressSequencesLong(
|
|
1256
1353
|
seqState_t seqState;
|
1257
1354
|
int seqNb;
|
1258
1355
|
dctx->fseEntropy = 1;
|
1259
|
-
{ 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]; }
|
1260
1357
|
seqState.base = base;
|
1261
1358
|
seqState.pos = (size_t)(op-base);
|
1262
|
-
seqState.gotoDict = (
|
1359
|
+
seqState.gotoDict = (uPtrDiff)dictEnd - (uPtrDiff)base; /* cast to avoid undefined behaviour */
|
1263
1360
|
CHECK_E(BIT_initDStream(&seqState.DStream, ip, iend-ip), corruption_detected);
|
1264
1361
|
FSE_initDState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
|
1265
1362
|
FSE_initDState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
|
@@ -1267,13 +1364,13 @@ static size_t ZSTD_decompressSequencesLong(
|
|
1267
1364
|
|
1268
1365
|
/* prepare in advance */
|
1269
1366
|
for (seqNb=0; (BIT_reloadDStream(&seqState.DStream) <= BIT_DStream_completed) && seqNb<seqAdvance; seqNb++) {
|
1270
|
-
sequences[seqNb] = ZSTD_decodeSequenceLong(&seqState);
|
1367
|
+
sequences[seqNb] = ZSTD_decodeSequenceLong(&seqState, windowSize);
|
1271
1368
|
}
|
1272
1369
|
if (seqNb<seqAdvance) return ERROR(corruption_detected);
|
1273
1370
|
|
1274
1371
|
/* decode and decompress */
|
1275
1372
|
for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && seqNb<nbSeq ; seqNb++) {
|
1276
|
-
seq_t const sequence = ZSTD_decodeSequenceLong(&seqState);
|
1373
|
+
seq_t const sequence = ZSTD_decodeSequenceLong(&seqState, windowSize);
|
1277
1374
|
size_t const oneSeqSize = ZSTD_execSequenceLong(op, oend, sequences[(seqNb-ADVANCED_SEQS) & STOSEQ_MASK], &litPtr, litEnd, base, vBase, dictEnd);
|
1278
1375
|
if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
|
1279
1376
|
ZSTD_PREFETCH(sequence.match);
|
@@ -1291,7 +1388,7 @@ static size_t ZSTD_decompressSequencesLong(
|
|
1291
1388
|
}
|
1292
1389
|
|
1293
1390
|
/* save reps for next block */
|
1294
|
-
{ 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]); }
|
1295
1392
|
}
|
1296
1393
|
|
1297
1394
|
/* last literal segment */
|
@@ -1313,13 +1410,18 @@ static size_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
|
|
1313
1410
|
|
1314
1411
|
if (srcSize >= ZSTD_BLOCKSIZE_ABSOLUTEMAX) return ERROR(srcSize_wrong);
|
1315
1412
|
|
1316
|
-
/* Decode literals
|
1413
|
+
/* Decode literals section */
|
1317
1414
|
{ size_t const litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize);
|
1318
1415
|
if (ZSTD_isError(litCSize)) return litCSize;
|
1319
1416
|
ip += litCSize;
|
1320
1417
|
srcSize -= litCSize;
|
1321
1418
|
}
|
1322
|
-
if (
|
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);
|
1323
1425
|
return ZSTD_decompressSequences(dctx, dst, dstCapacity, ip, srcSize);
|
1324
1426
|
}
|
1325
1427
|
|
@@ -1363,27 +1465,81 @@ size_t ZSTD_generateNxBytes(void* dst, size_t dstCapacity, BYTE byte, size_t len
|
|
1363
1465
|
return length;
|
1364
1466
|
}
|
1365
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
|
+
}
|
1366
1522
|
|
1367
1523
|
/*! ZSTD_decompressFrame() :
|
1368
|
-
*
|
1524
|
+
* @dctx must be properly initialized */
|
1369
1525
|
static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
1370
1526
|
void* dst, size_t dstCapacity,
|
1371
|
-
const void
|
1527
|
+
const void** srcPtr, size_t *srcSizePtr)
|
1372
1528
|
{
|
1373
|
-
const BYTE* ip = (const BYTE*)
|
1529
|
+
const BYTE* ip = (const BYTE*)(*srcPtr);
|
1374
1530
|
BYTE* const ostart = (BYTE* const)dst;
|
1375
1531
|
BYTE* const oend = ostart + dstCapacity;
|
1376
1532
|
BYTE* op = ostart;
|
1377
|
-
size_t remainingSize =
|
1533
|
+
size_t remainingSize = *srcSizePtr;
|
1378
1534
|
|
1379
1535
|
/* check */
|
1380
|
-
if (
|
1536
|
+
if (remainingSize < ZSTD_frameHeaderSize_min+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
|
1381
1537
|
|
1382
1538
|
/* Frame Header */
|
1383
|
-
{ size_t const frameHeaderSize = ZSTD_frameHeaderSize(
|
1539
|
+
{ size_t const frameHeaderSize = ZSTD_frameHeaderSize(ip, ZSTD_frameHeaderSize_prefix);
|
1384
1540
|
if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;
|
1385
|
-
if (
|
1386
|
-
CHECK_F(ZSTD_decodeFrameHeader(dctx,
|
1541
|
+
if (remainingSize < frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
|
1542
|
+
CHECK_F(ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize));
|
1387
1543
|
ip += frameHeaderSize; remainingSize -= frameHeaderSize;
|
1388
1544
|
}
|
1389
1545
|
|
@@ -1428,25 +1584,109 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|
1428
1584
|
if (remainingSize<4) return ERROR(checksum_wrong);
|
1429
1585
|
checkRead = MEM_readLE32(ip);
|
1430
1586
|
if (checkRead != checkCalc) return ERROR(checksum_wrong);
|
1587
|
+
ip += 4;
|
1431
1588
|
remainingSize -= 4;
|
1432
1589
|
}
|
1433
1590
|
|
1434
|
-
|
1591
|
+
/* Allow caller to get size read */
|
1592
|
+
*srcPtr = ip;
|
1593
|
+
*srcSizePtr = remainingSize;
|
1435
1594
|
return op-ostart;
|
1436
1595
|
}
|
1437
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
|
+
}
|
1438
1683
|
|
1439
1684
|
size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
|
1440
1685
|
void* dst, size_t dstCapacity,
|
1441
1686
|
const void* src, size_t srcSize,
|
1442
1687
|
const void* dict, size_t dictSize)
|
1443
1688
|
{
|
1444
|
-
|
1445
|
-
if (ZSTD_isLegacy(src, srcSize)) return ZSTD_decompressLegacy(dst, dstCapacity, src, srcSize, dict, dictSize);
|
1446
|
-
#endif
|
1447
|
-
CHECK_F(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize));
|
1448
|
-
ZSTD_checkContinuity(dctx, dst);
|
1449
|
-
return ZSTD_decompressFrame(dctx, dst, dstCapacity, src, srcSize);
|
1689
|
+
return ZSTD_decompressMultiFrame(dctx, dst, dstCapacity, src, srcSize, dict, dictSize, NULL);
|
1450
1690
|
}
|
1451
1691
|
|
1452
1692
|
|
@@ -1633,22 +1873,29 @@ static size_t ZSTD_refDictContent(ZSTD_DCtx* dctx, const void* dict, size_t dict
|
|
1633
1873
|
return 0;
|
1634
1874
|
}
|
1635
1875
|
|
1636
|
-
|
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)
|
1637
1880
|
{
|
1638
1881
|
const BYTE* dictPtr = (const BYTE*)dict;
|
1639
1882
|
const BYTE* const dictEnd = dictPtr + dictSize;
|
1640
1883
|
|
1641
|
-
|
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);
|
1642
1889
|
if (HUF_isError(hSize)) return ERROR(dictionary_corrupted);
|
1643
1890
|
dictPtr += hSize;
|
1644
1891
|
}
|
1645
1892
|
|
1646
1893
|
{ short offcodeNCount[MaxOff+1];
|
1647
|
-
U32 offcodeMaxValue=MaxOff, offcodeLog;
|
1894
|
+
U32 offcodeMaxValue = MaxOff, offcodeLog;
|
1648
1895
|
size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
|
1649
1896
|
if (FSE_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);
|
1650
1897
|
if (offcodeLog > OffFSELog) return ERROR(dictionary_corrupted);
|
1651
|
-
CHECK_E(FSE_buildDTable(
|
1898
|
+
CHECK_E(FSE_buildDTable(entropy->OFTable, offcodeNCount, offcodeMaxValue, offcodeLog), dictionary_corrupted);
|
1652
1899
|
dictPtr += offcodeHeaderSize;
|
1653
1900
|
}
|
1654
1901
|
|
@@ -1657,7 +1904,7 @@ static size_t ZSTD_loadEntropy(ZSTD_DCtx* dctx, const void* const dict, size_t c
|
|
1657
1904
|
size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
|
1658
1905
|
if (FSE_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted);
|
1659
1906
|
if (matchlengthLog > MLFSELog) return ERROR(dictionary_corrupted);
|
1660
|
-
CHECK_E(FSE_buildDTable(
|
1907
|
+
CHECK_E(FSE_buildDTable(entropy->MLTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog), dictionary_corrupted);
|
1661
1908
|
dictPtr += matchlengthHeaderSize;
|
1662
1909
|
}
|
1663
1910
|
|
@@ -1666,17 +1913,19 @@ static size_t ZSTD_loadEntropy(ZSTD_DCtx* dctx, const void* const dict, size_t c
|
|
1666
1913
|
size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
|
1667
1914
|
if (FSE_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted);
|
1668
1915
|
if (litlengthLog > LLFSELog) return ERROR(dictionary_corrupted);
|
1669
|
-
CHECK_E(FSE_buildDTable(
|
1916
|
+
CHECK_E(FSE_buildDTable(entropy->LLTable, litlengthNCount, litlengthMaxValue, litlengthLog), dictionary_corrupted);
|
1670
1917
|
dictPtr += litlengthHeaderSize;
|
1671
1918
|
}
|
1672
1919
|
|
1673
1920
|
if (dictPtr+12 > dictEnd) return ERROR(dictionary_corrupted);
|
1674
|
-
|
1675
|
-
|
1676
|
-
|
1677
|
-
|
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
|
+
} }
|
1678
1928
|
|
1679
|
-
dctx->litEntropy = dctx->fseEntropy = 1;
|
1680
1929
|
return dictPtr - (const BYTE*)dict;
|
1681
1930
|
}
|
1682
1931
|
|
@@ -1690,13 +1939,12 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
|
|
1690
1939
|
dctx->dictID = MEM_readLE32((const char*)dict + 4);
|
1691
1940
|
|
1692
1941
|
/* load entropy tables */
|
1693
|
-
|
1694
|
-
dictSize -= 8;
|
1695
|
-
{ size_t const eSize = ZSTD_loadEntropy(dctx, dict, dictSize);
|
1942
|
+
{ size_t const eSize = ZSTD_loadEntropy(&dctx->entropy, dict, dictSize);
|
1696
1943
|
if (ZSTD_isError(eSize)) return ERROR(dictionary_corrupted);
|
1697
1944
|
dict = (const char*)dict + eSize;
|
1698
1945
|
dictSize -= eSize;
|
1699
1946
|
}
|
1947
|
+
dctx->litEntropy = dctx->fseEntropy = 1;
|
1700
1948
|
|
1701
1949
|
/* reference dictionary content */
|
1702
1950
|
return ZSTD_refDictContent(dctx, dict, dictSize);
|
@@ -1716,50 +1964,101 @@ struct ZSTD_DDict_s {
|
|
1716
1964
|
void* dictBuffer;
|
1717
1965
|
const void* dictContent;
|
1718
1966
|
size_t dictSize;
|
1719
|
-
|
1967
|
+
ZSTD_entropyTables_t entropy;
|
1968
|
+
U32 dictID;
|
1969
|
+
U32 entropyPresent;
|
1970
|
+
ZSTD_customMem cMem;
|
1720
1971
|
}; /* typedef'd to ZSTD_DDict within "zstd.h" */
|
1721
1972
|
|
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
|
+
|
1722
2026
|
ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize, unsigned byReference, ZSTD_customMem customMem)
|
1723
2027
|
{
|
1724
2028
|
if (!customMem.customAlloc && !customMem.customFree) customMem = defaultCustomMem;
|
1725
2029
|
if (!customMem.customAlloc || !customMem.customFree) return NULL;
|
1726
2030
|
|
1727
2031
|
{ ZSTD_DDict* const ddict = (ZSTD_DDict*) ZSTD_malloc(sizeof(ZSTD_DDict), customMem);
|
1728
|
-
|
1729
|
-
|
1730
|
-
if (!ddict || !dctx) {
|
1731
|
-
ZSTD_free(ddict, customMem);
|
1732
|
-
ZSTD_free(dctx, customMem);
|
1733
|
-
return NULL;
|
1734
|
-
}
|
2032
|
+
if (!ddict) return NULL;
|
2033
|
+
ddict->cMem = customMem;
|
1735
2034
|
|
1736
2035
|
if ((byReference) || (!dict) || (!dictSize)) {
|
1737
2036
|
ddict->dictBuffer = NULL;
|
1738
2037
|
ddict->dictContent = dict;
|
1739
2038
|
} else {
|
1740
2039
|
void* const internalBuffer = ZSTD_malloc(dictSize, customMem);
|
1741
|
-
if (!internalBuffer) {
|
2040
|
+
if (!internalBuffer) { ZSTD_freeDDict(ddict); return NULL; }
|
1742
2041
|
memcpy(internalBuffer, dict, dictSize);
|
1743
2042
|
ddict->dictBuffer = internalBuffer;
|
1744
2043
|
ddict->dictContent = internalBuffer;
|
1745
2044
|
}
|
1746
|
-
|
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);
|
1747
2049
|
if (ZSTD_isError(errorCode)) {
|
1748
|
-
|
1749
|
-
ZSTD_free(ddict, customMem);
|
1750
|
-
ZSTD_free(dctx, customMem);
|
2050
|
+
ZSTD_freeDDict(ddict);
|
1751
2051
|
return NULL;
|
1752
2052
|
} }
|
1753
2053
|
|
1754
|
-
ddict->dictSize = dictSize;
|
1755
|
-
ddict->refContext = dctx;
|
1756
2054
|
return ddict;
|
1757
2055
|
}
|
1758
2056
|
}
|
1759
2057
|
|
1760
2058
|
/*! ZSTD_createDDict() :
|
1761
|
-
* Create a digested dictionary,
|
1762
|
-
* `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 */
|
1763
2062
|
ZSTD_DDict* ZSTD_createDDict(const void* dict, size_t dictSize)
|
1764
2063
|
{
|
1765
2064
|
ZSTD_customMem const allocator = { NULL, NULL, NULL };
|
@@ -1768,9 +2067,9 @@ ZSTD_DDict* ZSTD_createDDict(const void* dict, size_t dictSize)
|
|
1768
2067
|
|
1769
2068
|
|
1770
2069
|
/*! ZSTD_createDDict_byReference() :
|
1771
|
-
* Create a digested dictionary,
|
1772
|
-
* Dictionary content is simply referenced,
|
1773
|
-
*
|
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) */
|
1774
2073
|
ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize)
|
1775
2074
|
{
|
1776
2075
|
ZSTD_customMem const allocator = { NULL, NULL, NULL };
|
@@ -1781,8 +2080,7 @@ ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize
|
|
1781
2080
|
size_t ZSTD_freeDDict(ZSTD_DDict* ddict)
|
1782
2081
|
{
|
1783
2082
|
if (ddict==NULL) return 0; /* support free on NULL */
|
1784
|
-
{ ZSTD_customMem const cMem = ddict->
|
1785
|
-
ZSTD_freeDCtx(ddict->refContext);
|
2083
|
+
{ ZSTD_customMem const cMem = ddict->cMem;
|
1786
2084
|
ZSTD_free(ddict->dictBuffer, cMem);
|
1787
2085
|
ZSTD_free(ddict, cMem);
|
1788
2086
|
return 0;
|
@@ -1792,7 +2090,7 @@ size_t ZSTD_freeDDict(ZSTD_DDict* ddict)
|
|
1792
2090
|
size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict)
|
1793
2091
|
{
|
1794
2092
|
if (ddict==NULL) return 0; /* support sizeof on NULL */
|
1795
|
-
return sizeof(*ddict) +
|
2093
|
+
return sizeof(*ddict) + (ddict->dictBuffer ? ddict->dictSize : 0) ;
|
1796
2094
|
}
|
1797
2095
|
|
1798
2096
|
/*! ZSTD_getDictID_fromDict() :
|
@@ -1843,12 +2141,10 @@ size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
|
|
1843
2141
|
const void* src, size_t srcSize,
|
1844
2142
|
const ZSTD_DDict* ddict)
|
1845
2143
|
{
|
1846
|
-
|
1847
|
-
|
1848
|
-
|
1849
|
-
|
1850
|
-
ZSTD_checkContinuity(dctx, dst);
|
1851
|
-
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);
|
1852
2148
|
}
|
1853
2149
|
|
1854
2150
|
|
@@ -2048,10 +2344,23 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
2048
2344
|
break;
|
2049
2345
|
} }
|
2050
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
|
+
|
2051
2362
|
/* Consume header */
|
2052
|
-
|
2053
|
-
ZSTD_refDCtx(zds->dctx, refContext);
|
2054
|
-
}
|
2363
|
+
ZSTD_refDDict(zds->dctx, zds->ddict);
|
2055
2364
|
{ size_t const h1Size = ZSTD_nextSrcSizeToDecompress(zds->dctx); /* == ZSTD_frameHeaderSize_prefix */
|
2056
2365
|
CHECK_F(ZSTD_decompressContinue(zds->dctx, NULL, 0, zds->headerBuffer, h1Size));
|
2057
2366
|
{ size_t const h2Size = ZSTD_nextSrcSizeToDecompress(zds->dctx);
|
@@ -2063,7 +2372,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|
2063
2372
|
|
2064
2373
|
/* Adapt buffer sizes to frame header instructions */
|
2065
2374
|
{ size_t const blockSize = MIN(zds->fParams.windowSize, ZSTD_BLOCKSIZE_ABSOLUTEMAX);
|
2066
|
-
size_t const neededOutSize = zds->fParams.windowSize + blockSize;
|
2375
|
+
size_t const neededOutSize = zds->fParams.windowSize + blockSize + WILDCOPY_OVERLENGTH * 2;
|
2067
2376
|
zds->blockSize = blockSize;
|
2068
2377
|
if (zds->inBuffSize < blockSize) {
|
2069
2378
|
ZSTD_free(zds->inBuff, zds->customMem);
|