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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/ext/zstdruby/libzstd/Makefile +9 -6
  4. data/ext/zstdruby/libzstd/common/bitstream.h +3 -0
  5. data/ext/zstdruby/libzstd/common/entropy_common.c +13 -19
  6. data/ext/zstdruby/libzstd/common/fse.h +48 -22
  7. data/ext/zstdruby/libzstd/common/fse_decompress.c +0 -1
  8. data/ext/zstdruby/libzstd/common/huf.h +27 -5
  9. data/ext/zstdruby/libzstd/common/mem.h +14 -12
  10. data/ext/zstdruby/libzstd/common/threading.c +5 -4
  11. data/ext/zstdruby/libzstd/common/threading.h +1 -1
  12. data/ext/zstdruby/libzstd/common/xxhash.c +3 -1
  13. data/ext/zstdruby/libzstd/common/xxhash.h +11 -15
  14. data/ext/zstdruby/libzstd/common/zstd_common.c +1 -1
  15. data/ext/zstdruby/libzstd/common/zstd_internal.h +4 -0
  16. data/ext/zstdruby/libzstd/compress/fse_compress.c +16 -9
  17. data/ext/zstdruby/libzstd/compress/huf_compress.c +103 -28
  18. data/ext/zstdruby/libzstd/compress/zstd_compress.c +90 -37
  19. data/ext/zstdruby/libzstd/compress/zstd_opt.h +1 -1
  20. data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +7 -8
  21. data/ext/zstdruby/libzstd/decompress/huf_decompress.c +20 -17
  22. data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +429 -120
  23. data/ext/zstdruby/libzstd/deprecated/zbuff.h +3 -1
  24. data/ext/zstdruby/libzstd/dictBuilder/cover.c +16 -8
  25. data/ext/zstdruby/libzstd/dictBuilder/zdict.h +1 -1
  26. data/ext/zstdruby/libzstd/dll/example/build_package.bat +1 -0
  27. data/ext/zstdruby/libzstd/dll/libzstd.def +2 -0
  28. data/ext/zstdruby/libzstd/legacy/zstd_legacy.h +122 -7
  29. data/ext/zstdruby/libzstd/legacy/zstd_v01.c +31 -0
  30. data/ext/zstdruby/libzstd/legacy/zstd_v01.h +8 -0
  31. data/ext/zstdruby/libzstd/legacy/zstd_v02.c +37 -0
  32. data/ext/zstdruby/libzstd/legacy/zstd_v02.h +8 -0
  33. data/ext/zstdruby/libzstd/legacy/zstd_v03.c +37 -0
  34. data/ext/zstdruby/libzstd/legacy/zstd_v03.h +8 -0
  35. data/ext/zstdruby/libzstd/legacy/zstd_v04.c +33 -0
  36. data/ext/zstdruby/libzstd/legacy/zstd_v04.h +8 -0
  37. data/ext/zstdruby/libzstd/legacy/zstd_v05.c +29 -0
  38. data/ext/zstdruby/libzstd/legacy/zstd_v05.h +7 -0
  39. data/ext/zstdruby/libzstd/legacy/zstd_v06.c +32 -1
  40. data/ext/zstdruby/libzstd/legacy/zstd_v06.h +7 -0
  41. data/ext/zstdruby/libzstd/legacy/zstd_v07.c +44 -6
  42. data/ext/zstdruby/libzstd/legacy/zstd_v07.h +8 -0
  43. data/ext/zstdruby/libzstd/zstd.h +87 -13
  44. data/lib/zstd-ruby/version.rb +1 -1
  45. 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
- FSE_DTable LLTable[FSE_DTABLE_SIZE_U32(LLFSELog)];
97
- FSE_DTable OFTable[FSE_DTABLE_SIZE_U32(OffFSELog)];
98
- FSE_DTable MLTable[FSE_DTABLE_SIZE_U32(MLFSELog)];
99
- HUF_DTable hufTable[HUF_DTABLE_SIZE(HufLog)]; /* can accommodate HUF_decompress4X */
100
- const void* previousDstEnd;
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
- #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT==1)
320
- if (ZSTD_isLegacy(src, srcSize)) return ZSTD_getDecompressedSize_legacy(src, srcSize);
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
- iPtrDiff gotoDict;
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
- BYTE* const oend, seq_t sequence,
929
- const BYTE** litPtr, const BYTE* const litLimit,
930
- const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)
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 += (dictEnd-base);
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 }; /* substracted */
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
- static seq_t ZSTD_decodeSequenceLong(seqState_t* seqState)
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
- offset = OF_base[ofCode] + BIT_readBitsFast(&seqState->DStream, ofBits); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */
1100
- if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream);
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 }; /* substracted */
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 = (iPtrDiff)(dictEnd - base);
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 sub-block */
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 (dctx->fParams.windowSize > (1<<23)) return ZSTD_decompressSequencesLong(dctx, dst, dstCapacity, ip, srcSize);
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
- * `dctx` must be properly initialized */
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* src, size_t srcSize)
1527
+ const void** srcPtr, size_t *srcSizePtr)
1372
1528
  {
1373
- const BYTE* ip = (const BYTE*)src;
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 = srcSize;
1533
+ size_t remainingSize = *srcSizePtr;
1378
1534
 
1379
1535
  /* check */
1380
- if (srcSize < ZSTD_frameHeaderSize_min+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
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(src, ZSTD_frameHeaderSize_prefix);
1539
+ { size_t const frameHeaderSize = ZSTD_frameHeaderSize(ip, ZSTD_frameHeaderSize_prefix);
1384
1540
  if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;
1385
- if (srcSize < frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
1386
- CHECK_F(ZSTD_decodeFrameHeader(dctx, src, frameHeaderSize));
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
- if (remainingSize) return ERROR(srcSize_wrong);
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
- #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT==1)
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
- static size_t ZSTD_loadEntropy(ZSTD_DCtx* dctx, const void* const dict, size_t const dictSize)
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
- { size_t const hSize = HUF_readDTableX4(dctx->hufTable, dict, dictSize);
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(dctx->OFTable, offcodeNCount, offcodeMaxValue, offcodeLog), dictionary_corrupted);
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(dctx->MLTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog), dictionary_corrupted);
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(dctx->LLTable, litlengthNCount, litlengthMaxValue, litlengthLog), dictionary_corrupted);
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
- dctx->rep[0] = MEM_readLE32(dictPtr+0); if (dctx->rep[0] == 0 || dctx->rep[0] >= dictSize) return ERROR(dictionary_corrupted);
1675
- dctx->rep[1] = MEM_readLE32(dictPtr+4); if (dctx->rep[1] == 0 || dctx->rep[1] >= dictSize) return ERROR(dictionary_corrupted);
1676
- dctx->rep[2] = MEM_readLE32(dictPtr+8); if (dctx->rep[2] == 0 || dctx->rep[2] >= dictSize) return ERROR(dictionary_corrupted);
1677
- dictPtr += 12;
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
- dict = (const char*)dict + 8;
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
- ZSTD_DCtx* refContext;
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
- ZSTD_DCtx* const dctx = ZSTD_createDCtx_advanced(customMem);
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) { ZSTD_free(dctx, customMem); ZSTD_free(ddict, customMem); return NULL; }
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
- { size_t const errorCode = ZSTD_decompressBegin_usingDict(dctx, ddict->dictContent, dictSize);
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
- ZSTD_free(ddict->dictBuffer, customMem);
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, ready to start decompression without startup delay.
1762
- * `dict` can be released after `ZSTD_DDict` creation */
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, ready to start decompression operation without startup delay.
1772
- * Dictionary content is simply referenced, and therefore stays in dictBuffer.
1773
- * It is important that dictBuffer outlives DDict, it must remain read accessible throughout the lifetime of DDict */
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->refContext->customMem;
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) + ZSTD_sizeof_DCtx(ddict->refContext) + (ddict->dictBuffer ? ddict->dictSize : 0) ;
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
- #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT==1)
1847
- if (ZSTD_isLegacy(src, srcSize)) return ZSTD_decompressLegacy(dst, dstCapacity, src, srcSize, ddict->dictContent, ddict->dictSize);
1848
- #endif
1849
- ZSTD_refDCtx(dctx, ddict->refContext);
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
- { const ZSTD_DCtx* refContext = zds->ddict ? zds->ddict->refContext : NULL;
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);