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.
- 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
|
}
|