zstd-ruby 1.3.3.0 → 1.3.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +1 -1
  3. data/ext/zstdruby/libzstd/BUCK +13 -0
  4. data/ext/zstdruby/libzstd/README.md +32 -25
  5. data/ext/zstdruby/libzstd/common/bitstream.h +1 -1
  6. data/ext/zstdruby/libzstd/common/compiler.h +25 -0
  7. data/ext/zstdruby/libzstd/common/cpu.h +216 -0
  8. data/ext/zstdruby/libzstd/common/error_private.c +1 -0
  9. data/ext/zstdruby/libzstd/common/fse.h +1 -1
  10. data/ext/zstdruby/libzstd/common/fse_decompress.c +2 -2
  11. data/ext/zstdruby/libzstd/common/huf.h +114 -89
  12. data/ext/zstdruby/libzstd/common/pool.c +46 -17
  13. data/ext/zstdruby/libzstd/common/pool.h +18 -9
  14. data/ext/zstdruby/libzstd/common/threading.h +12 -12
  15. data/ext/zstdruby/libzstd/common/zstd_errors.h +16 -7
  16. data/ext/zstdruby/libzstd/common/zstd_internal.h +4 -5
  17. data/ext/zstdruby/libzstd/compress/fse_compress.c +19 -11
  18. data/ext/zstdruby/libzstd/compress/huf_compress.c +160 -62
  19. data/ext/zstdruby/libzstd/compress/zstd_compress.c +973 -644
  20. data/ext/zstdruby/libzstd/compress/zstd_compress_internal.h +281 -34
  21. data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +80 -62
  22. data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +11 -4
  23. data/ext/zstdruby/libzstd/compress/zstd_fast.c +87 -71
  24. data/ext/zstdruby/libzstd/compress/zstd_fast.h +10 -6
  25. data/ext/zstdruby/libzstd/compress/zstd_lazy.c +333 -274
  26. data/ext/zstdruby/libzstd/compress/zstd_lazy.h +33 -16
  27. data/ext/zstdruby/libzstd/compress/zstd_ldm.c +305 -359
  28. data/ext/zstdruby/libzstd/compress/zstd_ldm.h +64 -21
  29. data/ext/zstdruby/libzstd/compress/zstd_opt.c +194 -56
  30. data/ext/zstdruby/libzstd/compress/zstd_opt.h +17 -5
  31. data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +1131 -449
  32. data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +32 -16
  33. data/ext/zstdruby/libzstd/decompress/huf_decompress.c +390 -290
  34. data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +777 -439
  35. data/ext/zstdruby/libzstd/dictBuilder/cover.c +11 -8
  36. data/ext/zstdruby/libzstd/dictBuilder/zdict.c +83 -50
  37. data/ext/zstdruby/libzstd/dictBuilder/zdict.h +44 -43
  38. data/ext/zstdruby/libzstd/legacy/zstd_legacy.h +2 -0
  39. data/ext/zstdruby/libzstd/legacy/zstd_v04.c +42 -118
  40. data/ext/zstdruby/libzstd/legacy/zstd_v06.c +2 -2
  41. data/ext/zstdruby/libzstd/legacy/zstd_v07.c +2 -2
  42. data/ext/zstdruby/libzstd/zstd.h +254 -254
  43. data/lib/zstd-ruby/version.rb +1 -1
  44. metadata +4 -3
@@ -30,8 +30,14 @@ extern "C" {
30
30
  /*-*************************************
31
31
  * Constants
32
32
  ***************************************/
33
- static const U32 g_searchStrength = 8;
34
- #define HASH_READ_SIZE 8
33
+ #define kSearchStrength 8
34
+ #define HASH_READ_SIZE 8
35
+ #define ZSTD_DUBT_UNSORTED_MARK 1 /* For btlazy2 strategy, index 1 now means "unsorted".
36
+ It could be confused for a real successor at index "1", if sorted as larger than its predecessor.
37
+ It's not a big deal though : candidate will just be sorted again.
38
+ Additionnally, candidate position 1 will be lost.
39
+ But candidate 1 cannot hide a large tree of candidates, so it's a minimal loss.
40
+ The benefit is that ZSTD_DUBT_UNSORTED_MARK cannot be misdhandled after table re-use with a different strategy */
35
41
 
36
42
 
37
43
  /*-*************************************
@@ -43,7 +49,7 @@ typedef enum { zcss_init=0, zcss_load, zcss_flush } ZSTD_cStreamStage;
43
49
  typedef struct ZSTD_prefixDict_s {
44
50
  const void* dict;
45
51
  size_t dictSize;
46
- ZSTD_dictMode_e dictMode;
52
+ ZSTD_dictContentType_e dictContentType;
47
53
  } ZSTD_prefixDict;
48
54
 
49
55
  typedef struct {
@@ -51,7 +57,6 @@ typedef struct {
51
57
  FSE_CTable offcodeCTable[FSE_CTABLE_SIZE_U32(OffFSELog, MaxOff)];
52
58
  FSE_CTable matchlengthCTable[FSE_CTABLE_SIZE_U32(MLFSELog, MaxML)];
53
59
  FSE_CTable litlengthCTable[FSE_CTABLE_SIZE_U32(LLFSELog, MaxLL)];
54
- U32 workspace[HUF_WORKSPACE_SIZE_U32];
55
60
  HUF_repeat hufCTable_repeatMode;
56
61
  FSE_repeat offcode_repeatMode;
57
62
  FSE_repeat matchlength_repeatMode;
@@ -93,12 +98,44 @@ typedef struct {
93
98
  U32 staticPrices; /* prices follow a pre-defined cost structure, statistics are irrelevant */
94
99
  } optState_t;
95
100
 
101
+ typedef struct {
102
+ ZSTD_entropyCTables_t entropy;
103
+ U32 rep[ZSTD_REP_NUM];
104
+ } ZSTD_compressedBlockState_t;
105
+
106
+ typedef struct {
107
+ BYTE const* nextSrc; /* next block here to continue on current prefix */
108
+ BYTE const* base; /* All regular indexes relative to this position */
109
+ BYTE const* dictBase; /* extDict indexes relative to this position */
110
+ U32 dictLimit; /* below that point, need extDict */
111
+ U32 lowLimit; /* below that point, no more data */
112
+ } ZSTD_window_t;
113
+
114
+ typedef struct {
115
+ ZSTD_window_t window; /* State for window round buffer management */
116
+ U32 loadedDictEnd; /* index of end of dictionary */
117
+ U32 nextToUpdate; /* index from which to continue table update */
118
+ U32 nextToUpdate3; /* index from which to continue table update */
119
+ U32 hashLog3; /* dispatch table : larger == faster, more memory */
120
+ U32* hashTable;
121
+ U32* hashTable3;
122
+ U32* chainTable;
123
+ optState_t opt; /* optimal parser state */
124
+ } ZSTD_matchState_t;
125
+
126
+ typedef struct {
127
+ ZSTD_compressedBlockState_t* prevCBlock;
128
+ ZSTD_compressedBlockState_t* nextCBlock;
129
+ ZSTD_matchState_t matchState;
130
+ } ZSTD_blockState_t;
131
+
96
132
  typedef struct {
97
133
  U32 offset;
98
134
  U32 checksum;
99
135
  } ldmEntry_t;
100
136
 
101
137
  typedef struct {
138
+ ZSTD_window_t window; /* State for the window round buffer management */
102
139
  ldmEntry_t* hashTable;
103
140
  BYTE* bucketOffsets; /* Next position in bucket to insert entry */
104
141
  U64 hashPower; /* Used to compute the rolling hash.
@@ -111,60 +148,68 @@ typedef struct {
111
148
  U32 bucketSizeLog; /* Log bucket size for collision resolution, at most 8 */
112
149
  U32 minMatchLength; /* Minimum match length */
113
150
  U32 hashEveryLog; /* Log number of entries to skip */
151
+ U32 windowLog; /* Window log for the LDM */
114
152
  } ldmParams_t;
115
153
 
154
+ typedef struct {
155
+ U32 offset;
156
+ U32 litLength;
157
+ U32 matchLength;
158
+ } rawSeq;
159
+
160
+ typedef struct {
161
+ rawSeq* seq; /* The start of the sequences */
162
+ size_t pos; /* The position where reading stopped. <= size. */
163
+ size_t size; /* The number of sequences. <= capacity. */
164
+ size_t capacity; /* The capacity of the `seq` pointer */
165
+ } rawSeqStore_t;
166
+
116
167
  struct ZSTD_CCtx_params_s {
117
168
  ZSTD_format_e format;
118
169
  ZSTD_compressionParameters cParams;
119
170
  ZSTD_frameParameters fParams;
120
171
 
121
172
  int compressionLevel;
122
- U32 forceWindow; /* force back-references to respect limit of
173
+ int disableLiteralCompression;
174
+ int forceWindow; /* force back-references to respect limit of
123
175
  * 1<<wLog, even for dictionary */
124
176
 
125
177
  /* Multithreading: used to pass parameters to mtctx */
126
- U32 nbThreads;
178
+ unsigned nbWorkers;
127
179
  unsigned jobSize;
128
180
  unsigned overlapSizeLog;
129
181
 
130
182
  /* Long distance matching parameters */
131
183
  ldmParams_t ldmParams;
132
184
 
133
- /* For use with createCCtxParams() and freeCCtxParams() only */
185
+ /* Internal use, for createCCtxParams() and freeCCtxParams() only */
134
186
  ZSTD_customMem customMem;
135
-
136
187
  }; /* typedef'd to ZSTD_CCtx_params within "zstd.h" */
137
188
 
138
189
  struct ZSTD_CCtx_s {
139
- const BYTE* nextSrc; /* next block here to continue on current prefix */
140
- const BYTE* base; /* All regular indexes relative to this position */
141
- const BYTE* dictBase; /* extDict indexes relative to this position */
142
- U32 dictLimit; /* below that point, need extDict */
143
- U32 lowLimit; /* below that point, no more data */
144
- U32 nextToUpdate; /* index from which to continue dictionary update */
145
- U32 nextToUpdate3; /* index from which to continue dictionary update */
146
- U32 hashLog3; /* dispatch table : larger == faster, more memory */
147
- U32 loadedDictEnd; /* index of end of dictionary */
148
190
  ZSTD_compressionStage_e stage;
149
- U32 dictID;
191
+ int cParamsChanged; /* == 1 if cParams(except wlog) or compression level are changed in requestedParams. Triggers transmission of new params to ZSTDMT (if available) then reset to 0. */
192
+ int bmi2; /* == 1 if the CPU supports BMI2 and 0 otherwise. CPU support is determined dynamically once per context lifetime. */
150
193
  ZSTD_CCtx_params requestedParams;
151
194
  ZSTD_CCtx_params appliedParams;
195
+ U32 dictID;
152
196
  void* workSpace;
153
197
  size_t workSpaceSize;
154
198
  size_t blockSize;
155
- U64 pledgedSrcSizePlusOne; /* this way, 0 (default) == unknown */
156
- U64 consumedSrcSize;
199
+ unsigned long long pledgedSrcSizePlusOne; /* this way, 0 (default) == unknown */
200
+ unsigned long long consumedSrcSize;
201
+ unsigned long long producedCSize;
157
202
  XXH64_state_t xxhState;
158
203
  ZSTD_customMem customMem;
159
204
  size_t staticSize;
160
205
 
161
- seqStore_t seqStore; /* sequences storage ptrs */
162
- optState_t optState;
163
- ldmState_t ldmState; /* long distance matching state */
164
- U32* hashTable;
165
- U32* hashTable3;
166
- U32* chainTable;
167
- ZSTD_entropyCTables_t* entropy;
206
+ seqStore_t seqStore; /* sequences storage ptrs */
207
+ ldmState_t ldmState; /* long distance matching state */
208
+ rawSeq* ldmSequences; /* Storage for the ldm output sequences */
209
+ size_t maxNbLdmSequences;
210
+ rawSeqStore_t externSeqStore; /* Mutable reference to external sequences */
211
+ ZSTD_blockState_t blockState;
212
+ U32* entropyWorkspace; /* entropy workspace of HUF_WORKSPACE_SIZE bytes */
168
213
 
169
214
  /* streaming */
170
215
  char* inBuff;
@@ -191,6 +236,12 @@ struct ZSTD_CCtx_s {
191
236
  };
192
237
 
193
238
 
239
+ typedef size_t (*ZSTD_blockCompressor) (
240
+ ZSTD_matchState_t* bs, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
241
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize);
242
+ ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, int extDict);
243
+
244
+
194
245
  MEM_STATIC U32 ZSTD_LLcode(U32 litLength)
195
246
  {
196
247
  static const BYTE LL_Code[64] = { 0, 1, 2, 3, 4, 5, 6, 7,
@@ -359,10 +410,12 @@ MEM_STATIC size_t ZSTD_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* co
359
410
  }
360
411
 
361
412
  /** ZSTD_count_2segments() :
362
- * can count match length with `ip` & `match` in 2 different segments.
363
- * convention : on reaching mEnd, match count continue starting from iStart
364
- */
365
- MEM_STATIC size_t ZSTD_count_2segments(const BYTE* ip, const BYTE* match, const BYTE* iEnd, const BYTE* mEnd, const BYTE* iStart)
413
+ * can count match length with `ip` & `match` in 2 different segments.
414
+ * convention : on reaching mEnd, match count continue starting from iStart
415
+ */
416
+ MEM_STATIC size_t
417
+ ZSTD_count_2segments(const BYTE* ip, const BYTE* match,
418
+ const BYTE* iEnd, const BYTE* mEnd, const BYTE* iStart)
366
419
  {
367
420
  const BYTE* const vEnd = MIN( ip + (mEnd - match), iEnd);
368
421
  size_t const matchLength = ZSTD_count(ip, match, vEnd);
@@ -372,8 +425,8 @@ MEM_STATIC size_t ZSTD_count_2segments(const BYTE* ip, const BYTE* match, const
372
425
 
373
426
 
374
427
  /*-*************************************
375
- * Hashes
376
- ***************************************/
428
+ * Hashes
429
+ ***************************************/
377
430
  static const U32 prime3bytes = 506832829U;
378
431
  static U32 ZSTD_hash3(U32 u, U32 h) { return ((u << (32-24)) * prime3bytes) >> (32-h) ; }
379
432
  MEM_STATIC size_t ZSTD_hash3Ptr(const void* ptr, U32 h) { return ZSTD_hash3(MEM_readLE32(ptr), h); } /* only in zstd_opt.h */
@@ -411,6 +464,171 @@ MEM_STATIC size_t ZSTD_hashPtr(const void* p, U32 hBits, U32 mls)
411
464
  }
412
465
  }
413
466
 
467
+ /*-*************************************
468
+ * Round buffer management
469
+ ***************************************/
470
+ /* Max current allowed */
471
+ #define ZSTD_CURRENT_MAX ((3U << 29) + (1U << ZSTD_WINDOWLOG_MAX))
472
+ /* Maximum chunk size before overflow correction needs to be called again */
473
+ #define ZSTD_CHUNKSIZE_MAX \
474
+ ( ((U32)-1) /* Maximum ending current index */ \
475
+ - ZSTD_CURRENT_MAX) /* Maximum beginning lowLimit */
476
+
477
+ /**
478
+ * ZSTD_window_clear():
479
+ * Clears the window containing the history by simply setting it to empty.
480
+ */
481
+ MEM_STATIC void ZSTD_window_clear(ZSTD_window_t* window)
482
+ {
483
+ size_t const endT = (size_t)(window->nextSrc - window->base);
484
+ U32 const end = (U32)endT;
485
+
486
+ window->lowLimit = end;
487
+ window->dictLimit = end;
488
+ }
489
+
490
+ /**
491
+ * ZSTD_window_hasExtDict():
492
+ * Returns non-zero if the window has a non-empty extDict.
493
+ */
494
+ MEM_STATIC U32 ZSTD_window_hasExtDict(ZSTD_window_t const window)
495
+ {
496
+ return window.lowLimit < window.dictLimit;
497
+ }
498
+
499
+ /**
500
+ * ZSTD_window_needOverflowCorrection():
501
+ * Returns non-zero if the indices are getting too large and need overflow
502
+ * protection.
503
+ */
504
+ MEM_STATIC U32 ZSTD_window_needOverflowCorrection(ZSTD_window_t const window,
505
+ void const* srcEnd)
506
+ {
507
+ U32 const current = (U32)((BYTE const*)srcEnd - window.base);
508
+ return current > ZSTD_CURRENT_MAX;
509
+ }
510
+
511
+ /**
512
+ * ZSTD_window_correctOverflow():
513
+ * Reduces the indices to protect from index overflow.
514
+ * Returns the correction made to the indices, which must be applied to every
515
+ * stored index.
516
+ *
517
+ * The least significant cycleLog bits of the indices must remain the same,
518
+ * which may be 0. Every index up to maxDist in the past must be valid.
519
+ * NOTE: (maxDist & cycleMask) must be zero.
520
+ */
521
+ MEM_STATIC U32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog,
522
+ U32 maxDist, void const* src)
523
+ {
524
+ /* preemptive overflow correction:
525
+ * 1. correction is large enough:
526
+ * lowLimit > (3<<29) ==> current > 3<<29 + 1<<windowLog
527
+ * 1<<windowLog <= newCurrent < 1<<chainLog + 1<<windowLog
528
+ *
529
+ * current - newCurrent
530
+ * > (3<<29 + 1<<windowLog) - (1<<windowLog + 1<<chainLog)
531
+ * > (3<<29) - (1<<chainLog)
532
+ * > (3<<29) - (1<<30) (NOTE: chainLog <= 30)
533
+ * > 1<<29
534
+ *
535
+ * 2. (ip+ZSTD_CHUNKSIZE_MAX - cctx->base) doesn't overflow:
536
+ * After correction, current is less than (1<<chainLog + 1<<windowLog).
537
+ * In 64-bit mode we are safe, because we have 64-bit ptrdiff_t.
538
+ * In 32-bit mode we are safe, because (chainLog <= 29), so
539
+ * ip+ZSTD_CHUNKSIZE_MAX - cctx->base < 1<<32.
540
+ * 3. (cctx->lowLimit + 1<<windowLog) < 1<<32:
541
+ * windowLog <= 31 ==> 3<<29 + 1<<windowLog < 7<<29 < 1<<32.
542
+ */
543
+ U32 const cycleMask = (1U << cycleLog) - 1;
544
+ U32 const current = (U32)((BYTE const*)src - window->base);
545
+ U32 const newCurrent = (current & cycleMask) + maxDist;
546
+ U32 const correction = current - newCurrent;
547
+ assert((maxDist & cycleMask) == 0);
548
+ assert(current > newCurrent);
549
+ /* Loose bound, should be around 1<<29 (see above) */
550
+ assert(correction > 1<<28);
551
+
552
+ window->base += correction;
553
+ window->dictBase += correction;
554
+ window->lowLimit -= correction;
555
+ window->dictLimit -= correction;
556
+
557
+ DEBUGLOG(4, "Correction of 0x%x bytes to lowLimit=0x%x", correction,
558
+ window->lowLimit);
559
+ return correction;
560
+ }
561
+
562
+ /**
563
+ * ZSTD_window_enforceMaxDist():
564
+ * Updates lowLimit so that:
565
+ * (srcEnd - base) - lowLimit == maxDist + loadedDictEnd
566
+ * This allows a simple check that index >= lowLimit to see if index is valid.
567
+ * This must be called before a block compression call, with srcEnd as the block
568
+ * source end.
569
+ * If loadedDictEndPtr is not NULL, we set it to zero once we update lowLimit.
570
+ * This is because dictionaries are allowed to be referenced as long as the last
571
+ * byte of the dictionary is in the window, but once they are out of range,
572
+ * they cannot be referenced. If loadedDictEndPtr is NULL, we use
573
+ * loadedDictEnd == 0.
574
+ */
575
+ MEM_STATIC void ZSTD_window_enforceMaxDist(ZSTD_window_t* window,
576
+ void const* srcEnd, U32 maxDist,
577
+ U32* loadedDictEndPtr)
578
+ {
579
+ U32 const current = (U32)((BYTE const*)srcEnd - window->base);
580
+ U32 loadedDictEnd = loadedDictEndPtr != NULL ? *loadedDictEndPtr : 0;
581
+ if (current > maxDist + loadedDictEnd) {
582
+ U32 const newLowLimit = current - maxDist;
583
+ if (window->lowLimit < newLowLimit) window->lowLimit = newLowLimit;
584
+ if (window->dictLimit < window->lowLimit) {
585
+ DEBUGLOG(5, "Update dictLimit from %u to %u", window->dictLimit,
586
+ window->lowLimit);
587
+ window->dictLimit = window->lowLimit;
588
+ }
589
+ if (loadedDictEndPtr)
590
+ *loadedDictEndPtr = 0;
591
+ }
592
+ }
593
+
594
+ /**
595
+ * ZSTD_window_update():
596
+ * Updates the window by appending [src, src + srcSize) to the window.
597
+ * If it is not contiguous, the current prefix becomes the extDict, and we
598
+ * forget about the extDict. Handles overlap of the prefix and extDict.
599
+ * Returns non-zero if the segment is contiguous.
600
+ */
601
+ MEM_STATIC U32 ZSTD_window_update(ZSTD_window_t* window,
602
+ void const* src, size_t srcSize)
603
+ {
604
+ BYTE const* const ip = (BYTE const*)src;
605
+ U32 contiguous = 1;
606
+ /* Check if blocks follow each other */
607
+ if (src != window->nextSrc) {
608
+ /* not contiguous */
609
+ size_t const distanceFromBase = (size_t)(window->nextSrc - window->base);
610
+ DEBUGLOG(5, "Non contiguous blocks, new segment starts at %u",
611
+ window->dictLimit);
612
+ window->lowLimit = window->dictLimit;
613
+ assert(distanceFromBase == (size_t)(U32)distanceFromBase); /* should never overflow */
614
+ window->dictLimit = (U32)distanceFromBase;
615
+ window->dictBase = window->base;
616
+ window->base = ip - distanceFromBase;
617
+ // ms->nextToUpdate = window->dictLimit;
618
+ if (window->dictLimit - window->lowLimit < HASH_READ_SIZE) window->lowLimit = window->dictLimit; /* too small extDict */
619
+ contiguous = 0;
620
+ }
621
+ window->nextSrc = ip + srcSize;
622
+ /* if input and dictionary overlap : reduce dictionary (area presumed modified by input) */
623
+ if ( (ip+srcSize > window->dictBase + window->lowLimit)
624
+ & (ip < window->dictBase + window->dictLimit)) {
625
+ ptrdiff_t const highInputIdx = (ip + srcSize) - window->dictBase;
626
+ U32 const lowLimitMax = (highInputIdx > (ptrdiff_t)window->dictLimit) ? window->dictLimit : (U32)highInputIdx;
627
+ window->lowLimit = lowLimitMax;
628
+ }
629
+ return contiguous;
630
+ }
631
+
414
632
  #if defined (__cplusplus)
415
633
  }
416
634
  #endif
@@ -421,6 +639,13 @@ MEM_STATIC size_t ZSTD_hashPtr(const void* p, U32 hBits, U32 mls)
421
639
  * These prototypes shall only be called from within lib/compress
422
640
  * ============================================================== */
423
641
 
642
+ /* ZSTD_getCParamsFromCCtxParams() :
643
+ * cParams are built depending on compressionLevel, src size hints,
644
+ * LDM and manually set compression parameters.
645
+ */
646
+ ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
647
+ const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize);
648
+
424
649
  /*! ZSTD_initCStream_internal() :
425
650
  * Private use only. Init streaming operation.
426
651
  * expects params to be valid.
@@ -446,7 +671,7 @@ ZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict);
446
671
  * Private use only. To be called from zstdmt_compress.c. */
447
672
  size_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx,
448
673
  const void* dict, size_t dictSize,
449
- ZSTD_dictMode_e dictMode,
674
+ ZSTD_dictContentType_e dictContentType,
450
675
  const ZSTD_CDict* cdict,
451
676
  ZSTD_CCtx_params params,
452
677
  unsigned long long pledgedSrcSize);
@@ -459,4 +684,26 @@ size_t ZSTD_compress_advanced_internal(ZSTD_CCtx* cctx,
459
684
  const void* dict,size_t dictSize,
460
685
  ZSTD_CCtx_params params);
461
686
 
687
+
688
+ /* ZSTD_writeLastEmptyBlock() :
689
+ * output an empty Block with end-of-frame mark to complete a frame
690
+ * @return : size of data written into `dst` (== ZSTD_blockHeaderSize (defined in zstd_internal.h))
691
+ * or an error code if `dstCapcity` is too small (<ZSTD_blockHeaderSize)
692
+ */
693
+ size_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity);
694
+
695
+
696
+ /* ZSTD_referenceExternalSequences() :
697
+ * Must be called before starting a compression operation.
698
+ * seqs must parse a prefix of the source.
699
+ * This cannot be used when long range matching is enabled.
700
+ * Zstd will use these sequences, and pass the literals to a secondary block
701
+ * compressor.
702
+ * @return : An error code on failure.
703
+ * NOTE: seqs are not verified! Invalid sequences can cause out-of-bounds memory
704
+ * access and data corruption.
705
+ */
706
+ size_t ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSeq);
707
+
708
+
462
709
  #endif /* ZSTD_COMPRESS_H */
@@ -12,44 +12,58 @@
12
12
  #include "zstd_double_fast.h"
13
13
 
14
14
 
15
- void ZSTD_fillDoubleHashTable(ZSTD_CCtx* cctx, const void* end, const U32 mls)
15
+ void ZSTD_fillDoubleHashTable(ZSTD_matchState_t* ms,
16
+ ZSTD_compressionParameters const* cParams,
17
+ void const* end)
16
18
  {
17
- U32* const hashLarge = cctx->hashTable;
18
- U32 const hBitsL = cctx->appliedParams.cParams.hashLog;
19
- U32* const hashSmall = cctx->chainTable;
20
- U32 const hBitsS = cctx->appliedParams.cParams.chainLog;
21
- const BYTE* const base = cctx->base;
22
- const BYTE* ip = base + cctx->nextToUpdate;
19
+ U32* const hashLarge = ms->hashTable;
20
+ U32 const hBitsL = cParams->hashLog;
21
+ U32 const mls = cParams->searchLength;
22
+ U32* const hashSmall = ms->chainTable;
23
+ U32 const hBitsS = cParams->chainLog;
24
+ const BYTE* const base = ms->window.base;
25
+ const BYTE* ip = base + ms->nextToUpdate;
23
26
  const BYTE* const iend = ((const BYTE*)end) - HASH_READ_SIZE;
24
- const size_t fastHashFillStep = 3;
25
-
26
- while(ip <= iend) {
27
- hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = (U32)(ip - base);
28
- hashLarge[ZSTD_hashPtr(ip, hBitsL, 8)] = (U32)(ip - base);
29
- ip += fastHashFillStep;
27
+ const U32 fastHashFillStep = 3;
28
+
29
+ /* Always insert every fastHashFillStep position into the hash tables.
30
+ * Insert the other positions into the large hash table if their entry
31
+ * is empty.
32
+ */
33
+ for (; ip + fastHashFillStep - 1 <= iend; ip += fastHashFillStep) {
34
+ U32 const current = (U32)(ip - base);
35
+ U32 i;
36
+ for (i = 0; i < fastHashFillStep; ++i) {
37
+ size_t const smHash = ZSTD_hashPtr(ip + i, hBitsS, mls);
38
+ size_t const lgHash = ZSTD_hashPtr(ip + i, hBitsL, 8);
39
+ if (i == 0)
40
+ hashSmall[smHash] = current + i;
41
+ if (i == 0 || hashLarge[lgHash] == 0)
42
+ hashLarge[lgHash] = current + i;
43
+ }
30
44
  }
31
45
  }
32
46
 
33
47
 
34
48
  FORCE_INLINE_TEMPLATE
35
- size_t ZSTD_compressBlock_doubleFast_generic(ZSTD_CCtx* cctx,
36
- const void* src, size_t srcSize,
37
- const U32 mls)
49
+ size_t ZSTD_compressBlock_doubleFast_generic(
50
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
51
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize,
52
+ U32 const mls /* template */)
38
53
  {
39
- U32* const hashLong = cctx->hashTable;
40
- const U32 hBitsL = cctx->appliedParams.cParams.hashLog;
41
- U32* const hashSmall = cctx->chainTable;
42
- const U32 hBitsS = cctx->appliedParams.cParams.chainLog;
43
- seqStore_t* seqStorePtr = &(cctx->seqStore);
44
- const BYTE* const base = cctx->base;
54
+ U32* const hashLong = ms->hashTable;
55
+ const U32 hBitsL = cParams->hashLog;
56
+ U32* const hashSmall = ms->chainTable;
57
+ const U32 hBitsS = cParams->chainLog;
58
+ const BYTE* const base = ms->window.base;
45
59
  const BYTE* const istart = (const BYTE*)src;
46
60
  const BYTE* ip = istart;
47
61
  const BYTE* anchor = istart;
48
- const U32 lowestIndex = cctx->dictLimit;
62
+ const U32 lowestIndex = ms->window.dictLimit;
49
63
  const BYTE* const lowest = base + lowestIndex;
50
64
  const BYTE* const iend = istart + srcSize;
51
65
  const BYTE* const ilimit = iend - HASH_READ_SIZE;
52
- U32 offset_1=seqStorePtr->rep[0], offset_2=seqStorePtr->rep[1];
66
+ U32 offset_1=rep[0], offset_2=rep[1];
53
67
  U32 offsetSaved = 0;
54
68
 
55
69
  /* init */
@@ -76,7 +90,7 @@ size_t ZSTD_compressBlock_doubleFast_generic(ZSTD_CCtx* cctx,
76
90
  /* favor repcode */
77
91
  mLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;
78
92
  ip++;
79
- ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, 0, mLength-MINMATCH);
93
+ ZSTD_storeSeq(seqStore, ip-anchor, anchor, 0, mLength-MINMATCH);
80
94
  } else {
81
95
  U32 offset;
82
96
  if ( (matchIndexL > lowestIndex) && (MEM_read64(matchLong) == MEM_read64(ip)) ) {
@@ -99,14 +113,14 @@ size_t ZSTD_compressBlock_doubleFast_generic(ZSTD_CCtx* cctx,
99
113
  while (((ip>anchor) & (match>lowest)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
100
114
  }
101
115
  } else {
102
- ip += ((ip-anchor) >> g_searchStrength) + 1;
116
+ ip += ((ip-anchor) >> kSearchStrength) + 1;
103
117
  continue;
104
118
  }
105
119
 
106
120
  offset_2 = offset_1;
107
121
  offset_1 = offset;
108
122
 
109
- ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
123
+ ZSTD_storeSeq(seqStore, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
110
124
  }
111
125
 
112
126
  /* match found */
@@ -129,61 +143,63 @@ size_t ZSTD_compressBlock_doubleFast_generic(ZSTD_CCtx* cctx,
129
143
  { U32 const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; } /* swap offset_2 <=> offset_1 */
130
144
  hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = (U32)(ip-base);
131
145
  hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = (U32)(ip-base);
132
- ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, rLength-MINMATCH);
146
+ ZSTD_storeSeq(seqStore, 0, anchor, 0, rLength-MINMATCH);
133
147
  ip += rLength;
134
148
  anchor = ip;
135
149
  continue; /* faster when present ... (?) */
136
150
  } } }
137
151
 
138
152
  /* save reps for next block */
139
- seqStorePtr->repToConfirm[0] = offset_1 ? offset_1 : offsetSaved;
140
- seqStorePtr->repToConfirm[1] = offset_2 ? offset_2 : offsetSaved;
153
+ rep[0] = offset_1 ? offset_1 : offsetSaved;
154
+ rep[1] = offset_2 ? offset_2 : offsetSaved;
141
155
 
142
156
  /* Return the last literals size */
143
157
  return iend - anchor;
144
158
  }
145
159
 
146
160
 
147
- size_t ZSTD_compressBlock_doubleFast(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
161
+ size_t ZSTD_compressBlock_doubleFast(
162
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
163
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize)
148
164
  {
149
- const U32 mls = ctx->appliedParams.cParams.searchLength;
165
+ const U32 mls = cParams->searchLength;
150
166
  switch(mls)
151
167
  {
152
168
  default: /* includes case 3 */
153
169
  case 4 :
154
- return ZSTD_compressBlock_doubleFast_generic(ctx, src, srcSize, 4);
170
+ return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, cParams, src, srcSize, 4);
155
171
  case 5 :
156
- return ZSTD_compressBlock_doubleFast_generic(ctx, src, srcSize, 5);
172
+ return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, cParams, src, srcSize, 5);
157
173
  case 6 :
158
- return ZSTD_compressBlock_doubleFast_generic(ctx, src, srcSize, 6);
174
+ return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, cParams, src, srcSize, 6);
159
175
  case 7 :
160
- return ZSTD_compressBlock_doubleFast_generic(ctx, src, srcSize, 7);
176
+ return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, cParams, src, srcSize, 7);
161
177
  }
162
178
  }
163
179
 
164
180
 
165
- static size_t ZSTD_compressBlock_doubleFast_extDict_generic(ZSTD_CCtx* ctx,
166
- const void* src, size_t srcSize,
167
- const U32 mls)
181
+ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
182
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
183
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize,
184
+ U32 const mls /* template */)
168
185
  {
169
- U32* const hashLong = ctx->hashTable;
170
- U32 const hBitsL = ctx->appliedParams.cParams.hashLog;
171
- U32* const hashSmall = ctx->chainTable;
172
- U32 const hBitsS = ctx->appliedParams.cParams.chainLog;
173
- seqStore_t* seqStorePtr = &(ctx->seqStore);
174
- const BYTE* const base = ctx->base;
175
- const BYTE* const dictBase = ctx->dictBase;
186
+ U32* const hashLong = ms->hashTable;
187
+ U32 const hBitsL = cParams->hashLog;
188
+ U32* const hashSmall = ms->chainTable;
189
+ U32 const hBitsS = cParams->chainLog;
190
+ const BYTE* const base = ms->window.base;
191
+ const BYTE* const dictBase = ms->window.dictBase;
176
192
  const BYTE* const istart = (const BYTE*)src;
177
193
  const BYTE* ip = istart;
178
194
  const BYTE* anchor = istart;
179
- const U32 lowestIndex = ctx->lowLimit;
195
+ const U32 lowestIndex = ms->window.lowLimit;
180
196
  const BYTE* const dictStart = dictBase + lowestIndex;
181
- const U32 dictLimit = ctx->dictLimit;
197
+ const U32 dictLimit = ms->window.dictLimit;
182
198
  const BYTE* const lowPrefixPtr = base + dictLimit;
183
199
  const BYTE* const dictEnd = dictBase + dictLimit;
184
200
  const BYTE* const iend = istart + srcSize;
185
201
  const BYTE* const ilimit = iend - 8;
186
- U32 offset_1=seqStorePtr->rep[0], offset_2=seqStorePtr->rep[1];
202
+ U32 offset_1=rep[0], offset_2=rep[1];
187
203
 
188
204
  /* Search Loop */
189
205
  while (ip < ilimit) { /* < instead of <=, because (ip+1) */
@@ -209,7 +225,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(ZSTD_CCtx* ctx,
209
225
  const BYTE* repMatchEnd = repIndex < dictLimit ? dictEnd : iend;
210
226
  mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, lowPrefixPtr) + 4;
211
227
  ip++;
212
- ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, 0, mLength-MINMATCH);
228
+ ZSTD_storeSeq(seqStore, ip-anchor, anchor, 0, mLength-MINMATCH);
213
229
  } else {
214
230
  if ((matchLongIndex > lowestIndex) && (MEM_read64(matchLong) == MEM_read64(ip))) {
215
231
  const BYTE* matchEnd = matchLongIndex < dictLimit ? dictEnd : iend;
@@ -220,7 +236,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(ZSTD_CCtx* ctx,
220
236
  while (((ip>anchor) & (matchLong>lowMatchPtr)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } /* catch up */
221
237
  offset_2 = offset_1;
222
238
  offset_1 = offset;
223
- ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
239
+ ZSTD_storeSeq(seqStore, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
224
240
 
225
241
  } else if ((matchIndex > lowestIndex) && (MEM_read32(match) == MEM_read32(ip))) {
226
242
  size_t const h3 = ZSTD_hashPtr(ip+1, hBitsL, 8);
@@ -245,10 +261,10 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(ZSTD_CCtx* ctx,
245
261
  }
246
262
  offset_2 = offset_1;
247
263
  offset_1 = offset;
248
- ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
264
+ ZSTD_storeSeq(seqStore, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
249
265
 
250
266
  } else {
251
- ip += ((ip-anchor) >> g_searchStrength) + 1;
267
+ ip += ((ip-anchor) >> kSearchStrength) + 1;
252
268
  continue;
253
269
  } }
254
270
 
@@ -272,7 +288,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(ZSTD_CCtx* ctx,
272
288
  const BYTE* const repEnd2 = repIndex2 < dictLimit ? dictEnd : iend;
273
289
  size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, lowPrefixPtr) + 4;
274
290
  U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
275
- ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, repLength2-MINMATCH);
291
+ ZSTD_storeSeq(seqStore, 0, anchor, 0, repLength2-MINMATCH);
276
292
  hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = current2;
277
293
  hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = current2;
278
294
  ip += repLength2;
@@ -283,27 +299,29 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(ZSTD_CCtx* ctx,
283
299
  } } }
284
300
 
285
301
  /* save reps for next block */
286
- seqStorePtr->repToConfirm[0] = offset_1; seqStorePtr->repToConfirm[1] = offset_2;
302
+ rep[0] = offset_1;
303
+ rep[1] = offset_2;
287
304
 
288
305
  /* Return the last literals size */
289
306
  return iend - anchor;
290
307
  }
291
308
 
292
309
 
293
- size_t ZSTD_compressBlock_doubleFast_extDict(ZSTD_CCtx* ctx,
294
- const void* src, size_t srcSize)
310
+ size_t ZSTD_compressBlock_doubleFast_extDict(
311
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
312
+ ZSTD_compressionParameters const* cParams, void const* src, size_t srcSize)
295
313
  {
296
- U32 const mls = ctx->appliedParams.cParams.searchLength;
314
+ U32 const mls = cParams->searchLength;
297
315
  switch(mls)
298
316
  {
299
317
  default: /* includes case 3 */
300
318
  case 4 :
301
- return ZSTD_compressBlock_doubleFast_extDict_generic(ctx, src, srcSize, 4);
319
+ return ZSTD_compressBlock_doubleFast_extDict_generic(ms, seqStore, rep, cParams, src, srcSize, 4);
302
320
  case 5 :
303
- return ZSTD_compressBlock_doubleFast_extDict_generic(ctx, src, srcSize, 5);
321
+ return ZSTD_compressBlock_doubleFast_extDict_generic(ms, seqStore, rep, cParams, src, srcSize, 5);
304
322
  case 6 :
305
- return ZSTD_compressBlock_doubleFast_extDict_generic(ctx, src, srcSize, 6);
323
+ return ZSTD_compressBlock_doubleFast_extDict_generic(ms, seqStore, rep, cParams, src, srcSize, 6);
306
324
  case 7 :
307
- return ZSTD_compressBlock_doubleFast_extDict_generic(ctx, src, srcSize, 7);
325
+ return ZSTD_compressBlock_doubleFast_extDict_generic(ms, seqStore, rep, cParams, src, srcSize, 7);
308
326
  }
309
327
  }