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.
- checksums.yaml +5 -5
- data/README.md +1 -1
- data/ext/zstdruby/libzstd/BUCK +13 -0
- data/ext/zstdruby/libzstd/README.md +32 -25
- data/ext/zstdruby/libzstd/common/bitstream.h +1 -1
- data/ext/zstdruby/libzstd/common/compiler.h +25 -0
- data/ext/zstdruby/libzstd/common/cpu.h +216 -0
- data/ext/zstdruby/libzstd/common/error_private.c +1 -0
- data/ext/zstdruby/libzstd/common/fse.h +1 -1
- data/ext/zstdruby/libzstd/common/fse_decompress.c +2 -2
- data/ext/zstdruby/libzstd/common/huf.h +114 -89
- data/ext/zstdruby/libzstd/common/pool.c +46 -17
- data/ext/zstdruby/libzstd/common/pool.h +18 -9
- data/ext/zstdruby/libzstd/common/threading.h +12 -12
- data/ext/zstdruby/libzstd/common/zstd_errors.h +16 -7
- data/ext/zstdruby/libzstd/common/zstd_internal.h +4 -5
- data/ext/zstdruby/libzstd/compress/fse_compress.c +19 -11
- data/ext/zstdruby/libzstd/compress/huf_compress.c +160 -62
- data/ext/zstdruby/libzstd/compress/zstd_compress.c +973 -644
- data/ext/zstdruby/libzstd/compress/zstd_compress_internal.h +281 -34
- data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +80 -62
- data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +11 -4
- data/ext/zstdruby/libzstd/compress/zstd_fast.c +87 -71
- data/ext/zstdruby/libzstd/compress/zstd_fast.h +10 -6
- data/ext/zstdruby/libzstd/compress/zstd_lazy.c +333 -274
- data/ext/zstdruby/libzstd/compress/zstd_lazy.h +33 -16
- data/ext/zstdruby/libzstd/compress/zstd_ldm.c +305 -359
- data/ext/zstdruby/libzstd/compress/zstd_ldm.h +64 -21
- data/ext/zstdruby/libzstd/compress/zstd_opt.c +194 -56
- data/ext/zstdruby/libzstd/compress/zstd_opt.h +17 -5
- data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +1131 -449
- data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +32 -16
- data/ext/zstdruby/libzstd/decompress/huf_decompress.c +390 -290
- data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +777 -439
- data/ext/zstdruby/libzstd/dictBuilder/cover.c +11 -8
- data/ext/zstdruby/libzstd/dictBuilder/zdict.c +83 -50
- data/ext/zstdruby/libzstd/dictBuilder/zdict.h +44 -43
- data/ext/zstdruby/libzstd/legacy/zstd_legacy.h +2 -0
- data/ext/zstdruby/libzstd/legacy/zstd_v04.c +42 -118
- data/ext/zstdruby/libzstd/legacy/zstd_v06.c +2 -2
- data/ext/zstdruby/libzstd/legacy/zstd_v07.c +2 -2
- data/ext/zstdruby/libzstd/zstd.h +254 -254
- data/lib/zstd-ruby/version.rb +1 -1
- metadata +4 -3
@@ -30,8 +30,14 @@ extern "C" {
|
|
30
30
|
/*-*************************************
|
31
31
|
* Constants
|
32
32
|
***************************************/
|
33
|
-
|
34
|
-
#define HASH_READ_SIZE
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
/*
|
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
|
-
|
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
|
-
|
156
|
-
|
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;
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
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
|
-
*
|
363
|
-
*
|
364
|
-
*/
|
365
|
-
MEM_STATIC size_t
|
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
|
-
|
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(
|
15
|
+
void ZSTD_fillDoubleHashTable(ZSTD_matchState_t* ms,
|
16
|
+
ZSTD_compressionParameters const* cParams,
|
17
|
+
void const* end)
|
16
18
|
{
|
17
|
-
U32* const hashLarge =
|
18
|
-
U32 const hBitsL =
|
19
|
-
U32
|
20
|
-
U32
|
21
|
-
const
|
22
|
-
const BYTE*
|
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
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
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(
|
36
|
-
|
37
|
-
|
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 =
|
40
|
-
const U32 hBitsL =
|
41
|
-
U32* const hashSmall =
|
42
|
-
const U32 hBitsS =
|
43
|
-
|
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 =
|
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=
|
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(
|
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) >>
|
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(
|
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(
|
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
|
-
|
140
|
-
|
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(
|
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 =
|
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(
|
170
|
+
return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, cParams, src, srcSize, 4);
|
155
171
|
case 5 :
|
156
|
-
return ZSTD_compressBlock_doubleFast_generic(
|
172
|
+
return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, cParams, src, srcSize, 5);
|
157
173
|
case 6 :
|
158
|
-
return ZSTD_compressBlock_doubleFast_generic(
|
174
|
+
return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, cParams, src, srcSize, 6);
|
159
175
|
case 7 :
|
160
|
-
return ZSTD_compressBlock_doubleFast_generic(
|
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(
|
166
|
-
|
167
|
-
|
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 =
|
170
|
-
U32 const hBitsL =
|
171
|
-
U32* const hashSmall =
|
172
|
-
U32 const hBitsS =
|
173
|
-
|
174
|
-
const BYTE* const
|
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 =
|
195
|
+
const U32 lowestIndex = ms->window.lowLimit;
|
180
196
|
const BYTE* const dictStart = dictBase + lowestIndex;
|
181
|
-
const U32 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=
|
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(
|
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(
|
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(
|
264
|
+
ZSTD_storeSeq(seqStore, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
|
249
265
|
|
250
266
|
} else {
|
251
|
-
ip += ((ip-anchor) >>
|
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(
|
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
|
-
|
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(
|
294
|
-
|
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 =
|
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(
|
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(
|
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(
|
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(
|
325
|
+
return ZSTD_compressBlock_doubleFast_extDict_generic(ms, seqStore, rep, cParams, src, srcSize, 7);
|
308
326
|
}
|
309
327
|
}
|