extzstd 0.1 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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);