zstd-ruby 1.3.3.0 → 1.3.4.0

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