extzstd 0.1 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/HISTORY.ja +5 -0
  3. data/README.md +5 -5
  4. data/contrib/zstd/CONTRIBUTING.md +42 -0
  5. data/contrib/zstd/LICENSE-examples +11 -0
  6. data/contrib/zstd/Makefile +315 -0
  7. data/contrib/zstd/NEWS +261 -0
  8. data/contrib/zstd/PATENTS +33 -0
  9. data/contrib/zstd/README.md +121 -41
  10. data/contrib/zstd/TESTING.md +44 -0
  11. data/contrib/zstd/appveyor.yml +178 -0
  12. data/contrib/zstd/circle.yml +75 -0
  13. data/contrib/zstd/lib/BUCK +186 -0
  14. data/contrib/zstd/lib/Makefile +163 -0
  15. data/contrib/zstd/lib/README.md +77 -0
  16. data/contrib/zstd/{common → lib/common}/bitstream.h +7 -4
  17. data/contrib/zstd/{common → lib/common}/entropy_common.c +19 -23
  18. data/contrib/zstd/{common → lib/common}/error_private.c +0 -0
  19. data/contrib/zstd/{common → lib/common}/error_private.h +0 -0
  20. data/contrib/zstd/{common → lib/common}/fse.h +94 -34
  21. data/contrib/zstd/{common → lib/common}/fse_decompress.c +18 -19
  22. data/contrib/zstd/{common → lib/common}/huf.h +52 -20
  23. data/contrib/zstd/{common → lib/common}/mem.h +17 -13
  24. data/contrib/zstd/lib/common/pool.c +194 -0
  25. data/contrib/zstd/lib/common/pool.h +56 -0
  26. data/contrib/zstd/lib/common/threading.c +80 -0
  27. data/contrib/zstd/lib/common/threading.h +104 -0
  28. data/contrib/zstd/{common → lib/common}/xxhash.c +3 -1
  29. data/contrib/zstd/{common → lib/common}/xxhash.h +11 -15
  30. data/contrib/zstd/{common → lib/common}/zstd_common.c +1 -11
  31. data/contrib/zstd/{common → lib/common}/zstd_errors.h +16 -2
  32. data/contrib/zstd/{common → lib/common}/zstd_internal.h +17 -1
  33. data/contrib/zstd/{compress → lib/compress}/fse_compress.c +138 -91
  34. data/contrib/zstd/{compress → lib/compress}/huf_compress.c +218 -67
  35. data/contrib/zstd/{compress → lib/compress}/zstd_compress.c +231 -108
  36. data/contrib/zstd/{compress → lib/compress}/zstd_opt.h +44 -25
  37. data/contrib/zstd/lib/compress/zstdmt_compress.c +739 -0
  38. data/contrib/zstd/lib/compress/zstdmt_compress.h +78 -0
  39. data/contrib/zstd/{decompress → lib/decompress}/huf_decompress.c +28 -23
  40. data/contrib/zstd/{decompress → lib/decompress}/zstd_decompress.c +814 -176
  41. data/contrib/zstd/{common → lib/deprecated}/zbuff.h +60 -39
  42. data/contrib/zstd/lib/deprecated/zbuff_common.c +26 -0
  43. data/contrib/zstd/lib/deprecated/zbuff_compress.c +145 -0
  44. data/contrib/zstd/lib/deprecated/zbuff_decompress.c +74 -0
  45. data/contrib/zstd/lib/dictBuilder/cover.c +1029 -0
  46. data/contrib/zstd/{dictBuilder → lib/dictBuilder}/divsufsort.c +0 -0
  47. data/contrib/zstd/{dictBuilder → lib/dictBuilder}/divsufsort.h +0 -0
  48. data/contrib/zstd/{dictBuilder → lib/dictBuilder}/zdict.c +68 -18
  49. data/contrib/zstd/lib/dictBuilder/zdict.h +201 -0
  50. data/contrib/zstd/{legacy → lib/legacy}/zstd_legacy.h +122 -7
  51. data/contrib/zstd/{legacy → lib/legacy}/zstd_v01.c +34 -3
  52. data/contrib/zstd/{legacy → lib/legacy}/zstd_v01.h +8 -0
  53. data/contrib/zstd/{legacy → lib/legacy}/zstd_v02.c +45 -12
  54. data/contrib/zstd/{legacy → lib/legacy}/zstd_v02.h +8 -0
  55. data/contrib/zstd/{legacy → lib/legacy}/zstd_v03.c +45 -12
  56. data/contrib/zstd/{legacy → lib/legacy}/zstd_v03.h +8 -0
  57. data/contrib/zstd/{legacy → lib/legacy}/zstd_v04.c +56 -33
  58. data/contrib/zstd/{legacy → lib/legacy}/zstd_v04.h +8 -0
  59. data/contrib/zstd/{legacy → lib/legacy}/zstd_v05.c +45 -18
  60. data/contrib/zstd/{legacy → lib/legacy}/zstd_v05.h +7 -0
  61. data/contrib/zstd/{legacy → lib/legacy}/zstd_v06.c +43 -16
  62. data/contrib/zstd/{legacy → lib/legacy}/zstd_v06.h +7 -0
  63. data/contrib/zstd/{legacy → lib/legacy}/zstd_v07.c +57 -23
  64. data/contrib/zstd/{legacy → lib/legacy}/zstd_v07.h +8 -0
  65. data/contrib/zstd/lib/libzstd.pc.in +14 -0
  66. data/contrib/zstd/{zstd.h → lib/zstd.h} +206 -71
  67. data/ext/depend +2 -0
  68. data/ext/extconf.rb +4 -4
  69. data/ext/extzstd.c +1 -1
  70. data/ext/zstd_common.c +5 -5
  71. data/ext/zstd_compress.c +3 -3
  72. data/ext/zstd_decompress.c +2 -2
  73. data/ext/zstd_dictbuilder.c +2 -2
  74. data/ext/zstd_legacy_v01.c +1 -1
  75. data/ext/zstd_legacy_v02.c +1 -1
  76. data/ext/zstd_legacy_v03.c +1 -1
  77. data/ext/zstd_legacy_v04.c +1 -1
  78. data/ext/zstd_legacy_v05.c +1 -1
  79. data/ext/zstd_legacy_v06.c +1 -1
  80. data/ext/zstd_legacy_v07.c +1 -1
  81. data/gemstub.rb +9 -5
  82. data/lib/extzstd/version.rb +1 -1
  83. metadata +73 -51
  84. data/contrib/zstd/compress/zbuff_compress.c +0 -319
  85. data/contrib/zstd/decompress/zbuff_decompress.c +0 -252
  86. 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
- FSE_DTable LLTable[FSE_DTABLE_SIZE_U32(LLFSELog)];
88
- FSE_DTable OFTable[FSE_DTABLE_SIZE_U32(OffFSELog)];
89
- FSE_DTable MLTable[FSE_DTABLE_SIZE_U32(MLFSELog)];
90
- HUF_DTable hufTable[HUF_DTABLE_SIZE(HufLog)]; /* can accommodate HUF_decompress4X */
91
- const void* previousDstEnd;
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
- /* See compression format details in : doc/zstd_compression_format.md */
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
- #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT==1)
295
- if (ZSTD_isLegacy(src, srcSize)) return ZSTD_getDecompressedSize_legacy(src, srcSize);
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
- 0, 1, 1, 5, 0xD, 0x1D, 0x3D, 0x7D,
801
- 0xFD, 0x1FD, 0x3FD, 0x7FD, 0xFFD, 0x1FFD, 0x3FFD, 0x7FFD,
802
- 0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD,
803
- 0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD };
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] + BIT_readBits(&seqState->DStream, ofBits); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */
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) ? BIT_readBits(&seqState->DStream, mlBits) : 0); /* <= 16 bits */
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) ? BIT_readBits(&seqState->DStream, llBits) : 0); /* <= 16 bits */
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
- FORCE_NOINLINE
851
- size_t ZSTD_execSequenceLast7(BYTE* op,
852
- BYTE* const oend, seq_t sequence,
853
- const BYTE** litPtr, const BYTE* const litLimit_w,
854
- const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)
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 > litLimit_w) return ERROR(corruption_detected); /* over-read beyond lit buffer */
866
- if (oLitEnd <= oend_w) return ERROR(GENERIC); /* Precondition */
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 literals */
869
- if (op < oend_w) {
870
- ZSTD_wildcopy(op, *litPtr, oend_w - op);
871
- *litPtr += oend_w - op;
872
- op = oend_w;
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 - (base-match);
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
- while (op < oMatchEnd) *op++ = *match++;
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 ZSTD_execSequence(BYTE* op,
1241
+ size_t ZSTD_execSequenceLong(BYTE* op,
899
1242
  BYTE* const oend, seq_t sequence,
900
- const BYTE** litPtr, const BYTE* const litLimit_w,
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 = oLitEnd - sequence.offset;
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 > litLimit_w) return ERROR(corruption_detected); /* over-read beyond lit buffer */
913
- if (oLitEnd>oend_w) return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit_w, base, vBase, dictEnd);
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 }; /* substracted */
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
- for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && nbSeq ; ) {
1012
- nbSeq--;
1013
- { seq_t const sequence = ZSTD_decodeSequence(&seqState);
1014
- size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litLimit_w, base, vBase, dictEnd);
1015
- if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
1016
- op += oneSeqSize;
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 sub-block */
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
- * `dctx` must be properly initialized */
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* src, size_t srcSize)
1527
+ const void** srcPtr, size_t *srcSizePtr)
1100
1528
  {
1101
- const BYTE* ip = (const BYTE*)src;
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 = srcSize;
1533
+ size_t remainingSize = *srcSizePtr;
1106
1534
 
1107
1535
  /* check */
1108
- if (srcSize < ZSTD_frameHeaderSize_min+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
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(src, ZSTD_frameHeaderSize_prefix);
1539
+ { size_t const frameHeaderSize = ZSTD_frameHeaderSize(ip, ZSTD_frameHeaderSize_prefix);
1112
1540
  if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;
1113
- if (srcSize < frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
1114
- 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));
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
- if (remainingSize) return ERROR(srcSize_wrong);
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
- #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT==1)
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
- 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)
1365
1880
  {
1366
1881
  const BYTE* dictPtr = (const BYTE*)dict;
1367
1882
  const BYTE* const dictEnd = dictPtr + dictSize;
1368
1883
 
1369
- { 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);
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(dctx->OFTable, offcodeNCount, offcodeMaxValue, offcodeLog), dictionary_corrupted);
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(dctx->MLTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog), dictionary_corrupted);
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(dctx->LLTable, litlengthNCount, litlengthMaxValue, litlengthLog), dictionary_corrupted);
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
- dctx->rep[0] = MEM_readLE32(dictPtr+0); if (dctx->rep[0] >= dictSize) return ERROR(dictionary_corrupted);
1403
- dctx->rep[1] = MEM_readLE32(dictPtr+4); if (dctx->rep[1] >= dictSize) return ERROR(dictionary_corrupted);
1404
- dctx->rep[2] = MEM_readLE32(dictPtr+8); if (dctx->rep[2] >= dictSize) return ERROR(dictionary_corrupted);
1405
- 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
+ } }
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
- dict = (const char*)dict + 8;
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* dict;
1964
+ void* dictBuffer;
1965
+ const void* dictContent;
1445
1966
  size_t dictSize;
1446
- ZSTD_DCtx* refContext;
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
- ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize, ZSTD_customMem customMem)
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
- void* const dictContent = ZSTD_malloc(dictSize, customMem);
1456
- ZSTD_DCtx* const dctx = ZSTD_createDCtx_advanced(customMem);
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
- memcpy(dictContent, dict, dictSize);
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
- { size_t const errorCode = ZSTD_decompressBegin_usingDict(dctx, 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);
1469
2049
  if (ZSTD_isError(errorCode)) {
1470
- ZSTD_free(dictContent, customMem);
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, ready to start decompression without startup delay.
1485
- * `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 */
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->refContext->customMem;
1496
- ZSTD_freeDCtx(ddict->refContext);
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) + sizeof(ddict->refContext) + ddict->dictSize;
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
- #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT==1)
1519
- if (ZSTD_isLegacy(src, srcSize)) return ZSTD_decompressLegacy(dst, dstCapacity, src, srcSize, ddict->dict, ddict->dictSize);
1520
- #endif
1521
- ZSTD_refDCtx(dctx, ddict->refContext);
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 ZSTDdsp_maxWindowSize : zds->maxWindowSize = paramValue ? paramValue : (U32)(-1); break;
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
- return ERROR(init_missing);
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->dict : NULL;
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
- { const ZSTD_DCtx* refContext = zds->ddict ? zds->ddict->refContext : NULL;
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);