extlz4 0.2.4.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,807 @@
1
+ /*
2
+ LZ4 HC - High Compression Mode of LZ4
3
+ Copyright (C) 2011-2017, Yann Collet.
4
+
5
+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
6
+
7
+ Redistribution and use in source and binary forms, with or without
8
+ modification, are permitted provided that the following conditions are
9
+ met:
10
+
11
+ * Redistributions of source code must retain the above copyright
12
+ notice, this list of conditions and the following disclaimer.
13
+ * Redistributions in binary form must reproduce the above
14
+ copyright notice, this list of conditions and the following disclaimer
15
+ in the documentation and/or other materials provided with the
16
+ distribution.
17
+
18
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+
30
+ You can contact the author at :
31
+ - LZ4 source repository : https://github.com/lz4/lz4
32
+ - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
33
+ */
34
+ /* note : lz4hc is not an independent module, it requires lz4.h/lz4.c for proper compilation */
35
+
36
+
37
+ /* *************************************
38
+ * Tuning Parameter
39
+ ***************************************/
40
+
41
+ /*! HEAPMODE :
42
+ * Select how default compression function will allocate workplace memory,
43
+ * in stack (0:fastest), or in heap (1:requires malloc()).
44
+ * Since workplace is rather large, heap mode is recommended.
45
+ */
46
+ #ifndef LZ4HC_HEAPMODE
47
+ # define LZ4HC_HEAPMODE 1
48
+ #endif
49
+
50
+
51
+ /*=== Dependency ===*/
52
+ #include "lz4hc.h"
53
+
54
+
55
+ /*=== Common LZ4 definitions ===*/
56
+ #if defined(__GNUC__)
57
+ # pragma GCC diagnostic ignored "-Wunused-function"
58
+ #endif
59
+ #if defined (__clang__)
60
+ # pragma clang diagnostic ignored "-Wunused-function"
61
+ #endif
62
+
63
+ #define LZ4_COMMONDEFS_ONLY
64
+ #include "lz4.c" /* LZ4_count, constants, mem */
65
+
66
+
67
+ /*=== Constants ===*/
68
+ #define OPTIMAL_ML (int)((ML_MASK-1)+MINMATCH)
69
+
70
+
71
+ /*=== Macros ===*/
72
+ #define MIN(a,b) ( (a) < (b) ? (a) : (b) )
73
+ #define MAX(a,b) ( (a) > (b) ? (a) : (b) )
74
+ #define HASH_FUNCTION(i) (((i) * 2654435761U) >> ((MINMATCH*8)-LZ4HC_HASH_LOG))
75
+ #define DELTANEXTMAXD(p) chainTable[(p) & LZ4HC_MAXD_MASK] /* flexible, LZ4HC_MAXD dependent */
76
+ #define DELTANEXTU16(table, pos) table[(U16)(pos)] /* faster */
77
+
78
+ static U32 LZ4HC_hashPtr(const void* ptr) { return HASH_FUNCTION(LZ4_read32(ptr)); }
79
+
80
+
81
+
82
+ /**************************************
83
+ * HC Compression
84
+ **************************************/
85
+ static void LZ4HC_init (LZ4HC_CCtx_internal* hc4, const BYTE* start)
86
+ {
87
+ MEM_INIT((void*)hc4->hashTable, 0, sizeof(hc4->hashTable));
88
+ MEM_INIT(hc4->chainTable, 0xFF, sizeof(hc4->chainTable));
89
+ hc4->nextToUpdate = 64 KB;
90
+ hc4->base = start - 64 KB;
91
+ hc4->end = start;
92
+ hc4->dictBase = start - 64 KB;
93
+ hc4->dictLimit = 64 KB;
94
+ hc4->lowLimit = 64 KB;
95
+ }
96
+
97
+
98
+ /* Update chains up to ip (excluded) */
99
+ FORCE_INLINE void LZ4HC_Insert (LZ4HC_CCtx_internal* hc4, const BYTE* ip)
100
+ {
101
+ U16* const chainTable = hc4->chainTable;
102
+ U32* const hashTable = hc4->hashTable;
103
+ const BYTE* const base = hc4->base;
104
+ U32 const target = (U32)(ip - base);
105
+ U32 idx = hc4->nextToUpdate;
106
+
107
+ while (idx < target) {
108
+ U32 const h = LZ4HC_hashPtr(base+idx);
109
+ size_t delta = idx - hashTable[h];
110
+ if (delta>MAX_DISTANCE) delta = MAX_DISTANCE;
111
+ DELTANEXTU16(chainTable, idx) = (U16)delta;
112
+ hashTable[h] = idx;
113
+ idx++;
114
+ }
115
+
116
+ hc4->nextToUpdate = target;
117
+ }
118
+
119
+
120
+ FORCE_INLINE int LZ4HC_InsertAndFindBestMatch (LZ4HC_CCtx_internal* const hc4, /* Index table will be updated */
121
+ const BYTE* const ip, const BYTE* const iLimit,
122
+ const BYTE** matchpos,
123
+ const int maxNbAttempts)
124
+ {
125
+ U16* const chainTable = hc4->chainTable;
126
+ U32* const HashTable = hc4->hashTable;
127
+ const BYTE* const base = hc4->base;
128
+ const BYTE* const dictBase = hc4->dictBase;
129
+ const U32 dictLimit = hc4->dictLimit;
130
+ const U32 lowLimit = (hc4->lowLimit + 64 KB > (U32)(ip-base)) ? hc4->lowLimit : (U32)(ip - base) - (64 KB - 1);
131
+ U32 matchIndex;
132
+ int nbAttempts = maxNbAttempts;
133
+ size_t ml = 0;
134
+
135
+ /* HC4 match finder */
136
+ LZ4HC_Insert(hc4, ip);
137
+ matchIndex = HashTable[LZ4HC_hashPtr(ip)];
138
+
139
+ while ((matchIndex>=lowLimit) && (nbAttempts)) {
140
+ nbAttempts--;
141
+ if (matchIndex >= dictLimit) {
142
+ const BYTE* const match = base + matchIndex;
143
+ if ( (*(match+ml) == *(ip+ml)) /* can be longer */
144
+ && (LZ4_read32(match) == LZ4_read32(ip)) )
145
+ {
146
+ size_t const mlt = LZ4_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;
147
+ if (mlt > ml) { ml = mlt; *matchpos = match; }
148
+ }
149
+ } else {
150
+ const BYTE* const match = dictBase + matchIndex;
151
+ if (LZ4_read32(match) == LZ4_read32(ip)) {
152
+ size_t mlt;
153
+ const BYTE* vLimit = ip + (dictLimit - matchIndex);
154
+ if (vLimit > iLimit) vLimit = iLimit;
155
+ mlt = LZ4_count(ip+MINMATCH, match+MINMATCH, vLimit) + MINMATCH;
156
+ if ((ip+mlt == vLimit) && (vLimit < iLimit))
157
+ mlt += LZ4_count(ip+mlt, base+dictLimit, iLimit);
158
+ if (mlt > ml) { ml = mlt; *matchpos = base + matchIndex; } /* virtual matchpos */
159
+ }
160
+ }
161
+ matchIndex -= DELTANEXTU16(chainTable, matchIndex);
162
+ }
163
+
164
+ return (int)ml;
165
+ }
166
+
167
+
168
+ FORCE_INLINE int LZ4HC_InsertAndGetWiderMatch (
169
+ LZ4HC_CCtx_internal* hc4,
170
+ const BYTE* const ip,
171
+ const BYTE* const iLowLimit,
172
+ const BYTE* const iHighLimit,
173
+ int longest,
174
+ const BYTE** matchpos,
175
+ const BYTE** startpos,
176
+ const int maxNbAttempts)
177
+ {
178
+ U16* const chainTable = hc4->chainTable;
179
+ U32* const HashTable = hc4->hashTable;
180
+ const BYTE* const base = hc4->base;
181
+ const U32 dictLimit = hc4->dictLimit;
182
+ const BYTE* const lowPrefixPtr = base + dictLimit;
183
+ const U32 lowLimit = (hc4->lowLimit + 64 KB > (U32)(ip-base)) ? hc4->lowLimit : (U32)(ip - base) - (64 KB - 1);
184
+ const BYTE* const dictBase = hc4->dictBase;
185
+ int const delta = (int)(ip-iLowLimit);
186
+ int nbAttempts = maxNbAttempts;
187
+ U32 matchIndex;
188
+
189
+
190
+ /* First Match */
191
+ LZ4HC_Insert(hc4, ip);
192
+ matchIndex = HashTable[LZ4HC_hashPtr(ip)];
193
+
194
+ while ((matchIndex>=lowLimit) && (nbAttempts)) {
195
+ nbAttempts--;
196
+ if (matchIndex >= dictLimit) {
197
+ const BYTE* const matchPtr = base + matchIndex;
198
+ if (*(iLowLimit + longest) == *(matchPtr - delta + longest)) {
199
+ if (LZ4_read32(matchPtr) == LZ4_read32(ip)) {
200
+ int mlt = MINMATCH + LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, iHighLimit);
201
+ int back = 0;
202
+
203
+ while ( (ip+back > iLowLimit)
204
+ && (matchPtr+back > lowPrefixPtr)
205
+ && (ip[back-1] == matchPtr[back-1])) {
206
+ back--;
207
+ }
208
+
209
+ mlt -= back;
210
+
211
+ if (mlt > longest) {
212
+ longest = mlt;
213
+ *matchpos = matchPtr+back;
214
+ *startpos = ip+back;
215
+ } } }
216
+ } else {
217
+ const BYTE* const matchPtr = dictBase + matchIndex;
218
+ if (LZ4_read32(matchPtr) == LZ4_read32(ip)) {
219
+ int mlt;
220
+ int back=0;
221
+ const BYTE* vLimit = ip + (dictLimit - matchIndex);
222
+ if (vLimit > iHighLimit) vLimit = iHighLimit;
223
+ mlt = LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, vLimit) + MINMATCH;
224
+ if ((ip+mlt == vLimit) && (vLimit < iHighLimit))
225
+ mlt += LZ4_count(ip+mlt, base+dictLimit, iHighLimit);
226
+ while ((ip+back > iLowLimit) && (matchIndex+back > lowLimit) && (ip[back-1] == matchPtr[back-1])) back--;
227
+ mlt -= back;
228
+ if (mlt > longest) { longest = mlt; *matchpos = base + matchIndex + back; *startpos = ip+back; }
229
+ }
230
+ }
231
+ matchIndex -= DELTANEXTU16(chainTable, matchIndex);
232
+ }
233
+
234
+ return longest;
235
+ }
236
+
237
+
238
+ typedef enum {
239
+ noLimit = 0,
240
+ limitedOutput = 1,
241
+ limitedDestSize = 2,
242
+ } limitedOutput_directive;
243
+
244
+ #ifndef LZ4HC_DEBUG
245
+ # define LZ4HC_DEBUG 0
246
+ #endif
247
+
248
+ /* LZ4HC_encodeSequence() :
249
+ * @return : 0 if ok,
250
+ * 1 if buffer issue detected */
251
+ FORCE_INLINE int LZ4HC_encodeSequence (
252
+ const BYTE** ip,
253
+ BYTE** op,
254
+ const BYTE** anchor,
255
+ int matchLength,
256
+ const BYTE* const match,
257
+ limitedOutput_directive limit,
258
+ BYTE* oend)
259
+ {
260
+ size_t length;
261
+ BYTE* const token = (*op)++;
262
+
263
+ #if LZ4HC_DEBUG
264
+ printf("literal : %u -- match : %u -- offset : %u\n",
265
+ (U32)(*ip - *anchor), (U32)matchLength, (U32)(*ip-match));
266
+ #endif
267
+
268
+ /* Encode Literal length */
269
+ length = (size_t)(*ip - *anchor);
270
+ if ((limit) && ((*op + (length >> 8) + length + (2 + 1 + LASTLITERALS)) > oend)) return 1; /* Check output limit */
271
+ if (length >= RUN_MASK) {
272
+ size_t len = length - RUN_MASK;
273
+ *token = (RUN_MASK << ML_BITS);
274
+ for(; len >= 255 ; len -= 255) *(*op)++ = 255;
275
+ *(*op)++ = (BYTE)len;
276
+ } else {
277
+ *token = (BYTE)(length << ML_BITS);
278
+ }
279
+
280
+ /* Copy Literals */
281
+ LZ4_wildCopy(*op, *anchor, (*op) + length);
282
+ *op += length;
283
+
284
+ /* Encode Offset */
285
+ LZ4_writeLE16(*op, (U16)(*ip-match)); *op += 2;
286
+
287
+ /* Encode MatchLength */
288
+ length = (size_t)(matchLength - MINMATCH);
289
+ if ((limit) && (*op + (length >> 8) + (1 + LASTLITERALS) > oend)) return 1; /* Check output limit */
290
+ if (length >= ML_MASK) {
291
+ *token += ML_MASK;
292
+ length -= ML_MASK;
293
+ for(; length >= 510 ; length -= 510) { *(*op)++ = 255; *(*op)++ = 255; }
294
+ if (length >= 255) { length -= 255; *(*op)++ = 255; }
295
+ *(*op)++ = (BYTE)length;
296
+ } else {
297
+ *token += (BYTE)(length);
298
+ }
299
+
300
+ /* Prepare next loop */
301
+ *ip += matchLength;
302
+ *anchor = *ip;
303
+
304
+ return 0;
305
+ }
306
+
307
+ /* btopt */
308
+ #include "lz4opt.h"
309
+
310
+
311
+ static int LZ4HC_compress_hashChain (
312
+ LZ4HC_CCtx_internal* const ctx,
313
+ const char* const source,
314
+ char* const dest,
315
+ int* srcSizePtr,
316
+ int const maxOutputSize,
317
+ unsigned maxNbAttempts,
318
+ limitedOutput_directive limit
319
+ )
320
+ {
321
+ const int inputSize = *srcSizePtr;
322
+
323
+ const BYTE* ip = (const BYTE*) source;
324
+ const BYTE* anchor = ip;
325
+ const BYTE* const iend = ip + inputSize;
326
+ const BYTE* const mflimit = iend - MFLIMIT;
327
+ const BYTE* const matchlimit = (iend - LASTLITERALS);
328
+
329
+ BYTE* optr = (BYTE*) dest;
330
+ BYTE* op = (BYTE*) dest;
331
+ BYTE* oend = op + maxOutputSize;
332
+
333
+ int ml, ml2, ml3, ml0;
334
+ const BYTE* ref = NULL;
335
+ const BYTE* start2 = NULL;
336
+ const BYTE* ref2 = NULL;
337
+ const BYTE* start3 = NULL;
338
+ const BYTE* ref3 = NULL;
339
+ const BYTE* start0;
340
+ const BYTE* ref0;
341
+
342
+ /* init */
343
+ *srcSizePtr = 0;
344
+ if (limit == limitedDestSize && maxOutputSize < 1) return 0; /* Impossible to store anything */
345
+ if ((U32)inputSize > (U32)LZ4_MAX_INPUT_SIZE) return 0; /* Unsupported input size, too large (or negative) */
346
+
347
+ ctx->end += inputSize;
348
+ if (limit == limitedDestSize) oend -= LASTLITERALS; /* Hack for support limitations LZ4 decompressor */
349
+ if (inputSize < LZ4_minLength) goto _last_literals; /* Input too small, no compression (all literals) */
350
+
351
+ ip++;
352
+
353
+ /* Main Loop */
354
+ while (ip < mflimit) {
355
+ ml = LZ4HC_InsertAndFindBestMatch (ctx, ip, matchlimit, (&ref), maxNbAttempts);
356
+ if (!ml) { ip++; continue; }
357
+
358
+ /* saved, in case we would skip too much */
359
+ start0 = ip;
360
+ ref0 = ref;
361
+ ml0 = ml;
362
+
363
+ _Search2:
364
+ if (ip+ml < mflimit)
365
+ ml2 = LZ4HC_InsertAndGetWiderMatch(ctx, ip + ml - 2, ip + 0, matchlimit, ml, &ref2, &start2, maxNbAttempts);
366
+ else
367
+ ml2 = ml;
368
+
369
+ if (ml2 == ml) { /* No better match */
370
+ optr = op;
371
+ if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml, ref, limit, oend)) goto _dest_overflow;
372
+ continue;
373
+ }
374
+
375
+ if (start0 < ip) {
376
+ if (start2 < ip + ml0) { /* empirical */
377
+ ip = start0;
378
+ ref = ref0;
379
+ ml = ml0;
380
+ }
381
+ }
382
+
383
+ /* Here, start0==ip */
384
+ if ((start2 - ip) < 3) { /* First Match too small : removed */
385
+ ml = ml2;
386
+ ip = start2;
387
+ ref =ref2;
388
+ goto _Search2;
389
+ }
390
+
391
+ _Search3:
392
+ /* At this stage, we have :
393
+ * ml2 > ml1, and
394
+ * ip1+3 <= ip2 (usually < ip1+ml1) */
395
+ if ((start2 - ip) < OPTIMAL_ML) {
396
+ int correction;
397
+ int new_ml = ml;
398
+ if (new_ml > OPTIMAL_ML) new_ml = OPTIMAL_ML;
399
+ if (ip+new_ml > start2 + ml2 - MINMATCH) new_ml = (int)(start2 - ip) + ml2 - MINMATCH;
400
+ correction = new_ml - (int)(start2 - ip);
401
+ if (correction > 0) {
402
+ start2 += correction;
403
+ ref2 += correction;
404
+ ml2 -= correction;
405
+ }
406
+ }
407
+ /* Now, we have start2 = ip+new_ml, with new_ml = min(ml, OPTIMAL_ML=18) */
408
+
409
+ if (start2 + ml2 < mflimit)
410
+ ml3 = LZ4HC_InsertAndGetWiderMatch(ctx, start2 + ml2 - 3, start2, matchlimit, ml2, &ref3, &start3, maxNbAttempts);
411
+ else
412
+ ml3 = ml2;
413
+
414
+ if (ml3 == ml2) { /* No better match : 2 sequences to encode */
415
+ /* ip & ref are known; Now for ml */
416
+ if (start2 < ip+ml) ml = (int)(start2 - ip);
417
+ /* Now, encode 2 sequences */
418
+ optr = op;
419
+ if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml, ref, limit, oend)) goto _dest_overflow;
420
+ ip = start2;
421
+ optr = op;
422
+ if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml2, ref2, limit, oend)) goto _dest_overflow;
423
+ continue;
424
+ }
425
+
426
+ if (start3 < ip+ml+3) { /* Not enough space for match 2 : remove it */
427
+ if (start3 >= (ip+ml)) { /* can write Seq1 immediately ==> Seq2 is removed, so Seq3 becomes Seq1 */
428
+ if (start2 < ip+ml) {
429
+ int correction = (int)(ip+ml - start2);
430
+ start2 += correction;
431
+ ref2 += correction;
432
+ ml2 -= correction;
433
+ if (ml2 < MINMATCH) {
434
+ start2 = start3;
435
+ ref2 = ref3;
436
+ ml2 = ml3;
437
+ }
438
+ }
439
+
440
+ optr = op;
441
+ if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml, ref, limit, oend)) goto _dest_overflow;
442
+ ip = start3;
443
+ ref = ref3;
444
+ ml = ml3;
445
+
446
+ start0 = start2;
447
+ ref0 = ref2;
448
+ ml0 = ml2;
449
+ goto _Search2;
450
+ }
451
+
452
+ start2 = start3;
453
+ ref2 = ref3;
454
+ ml2 = ml3;
455
+ goto _Search3;
456
+ }
457
+
458
+ /*
459
+ * OK, now we have 3 ascending matches; let's write at least the first one
460
+ * ip & ref are known; Now for ml
461
+ */
462
+ if (start2 < ip+ml) {
463
+ if ((start2 - ip) < (int)ML_MASK) {
464
+ int correction;
465
+ if (ml > OPTIMAL_ML) ml = OPTIMAL_ML;
466
+ if (ip + ml > start2 + ml2 - MINMATCH) ml = (int)(start2 - ip) + ml2 - MINMATCH;
467
+ correction = ml - (int)(start2 - ip);
468
+ if (correction > 0) {
469
+ start2 += correction;
470
+ ref2 += correction;
471
+ ml2 -= correction;
472
+ }
473
+ } else {
474
+ ml = (int)(start2 - ip);
475
+ }
476
+ }
477
+ optr = op;
478
+ if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml, ref, limit, oend)) goto _dest_overflow;
479
+
480
+ ip = start2;
481
+ ref = ref2;
482
+ ml = ml2;
483
+
484
+ start2 = start3;
485
+ ref2 = ref3;
486
+ ml2 = ml3;
487
+
488
+ goto _Search3;
489
+ }
490
+
491
+ _last_literals:
492
+ /* Encode Last Literals */
493
+ { size_t lastRunSize = (size_t)(iend - anchor); /* literals */
494
+ size_t litLength = (lastRunSize + 255 - RUN_MASK) / 255;
495
+ size_t const totalSize = 1 + litLength + lastRunSize;
496
+ if (limit == limitedDestSize) oend += LASTLITERALS; /* restore correct value */
497
+ if (limit && (op + totalSize > oend)) {
498
+ if (limit == limitedOutput) return 0; /* Check output limit */
499
+ /* adapt lastRunSize to fill 'dest' */
500
+ lastRunSize = (size_t)(oend - op) - 1;
501
+ litLength = (lastRunSize + 255 - RUN_MASK) / 255;
502
+ lastRunSize -= litLength;
503
+ }
504
+ ip = anchor + lastRunSize;
505
+
506
+ if (lastRunSize >= RUN_MASK) {
507
+ size_t accumulator = lastRunSize - RUN_MASK;
508
+ *op++ = (RUN_MASK << ML_BITS);
509
+ for(; accumulator >= 255 ; accumulator -= 255) *op++ = 255;
510
+ *op++ = (BYTE) accumulator;
511
+ } else {
512
+ *op++ = (BYTE)(lastRunSize << ML_BITS);
513
+ }
514
+ memcpy(op, anchor, lastRunSize);
515
+ op += lastRunSize;
516
+ }
517
+
518
+ /* End */
519
+ *srcSizePtr = (int) (((const char*)ip) - source);
520
+ return (int) (((char*)op)-dest);
521
+
522
+ _dest_overflow:
523
+ if (limit == limitedDestSize) {
524
+ op = optr; /* restore correct out pointer */
525
+ goto _last_literals;
526
+ }
527
+ return 0;
528
+ }
529
+
530
+ static int LZ4HC_getSearchNum(int compressionLevel)
531
+ {
532
+ switch (compressionLevel) {
533
+ default: return 0; /* unused */
534
+ case 11: return 128;
535
+ case 12: return 1<<10;
536
+ }
537
+ }
538
+
539
+ static int LZ4HC_compress_generic (
540
+ LZ4HC_CCtx_internal* const ctx,
541
+ const char* const src,
542
+ char* const dst,
543
+ int* const srcSizePtr,
544
+ int const dstCapacity,
545
+ int cLevel,
546
+ limitedOutput_directive limit
547
+ )
548
+ {
549
+ if (cLevel < 1) cLevel = LZ4HC_CLEVEL_DEFAULT; /* note : convention is different from lz4frame, maybe to reconsider */
550
+ if (cLevel > 9) {
551
+ if (limit == limitedDestSize) cLevel = 10;
552
+ switch (cLevel) {
553
+ case 10:
554
+ return LZ4HC_compress_hashChain(ctx, src, dst, srcSizePtr, dstCapacity, 1 << 12, limit);
555
+ case 11:
556
+ ctx->searchNum = LZ4HC_getSearchNum(cLevel);
557
+ return LZ4HC_compress_optimal(ctx, src, dst, *srcSizePtr, dstCapacity, limit, 128, 0);
558
+ default:
559
+ cLevel = 12;
560
+ /* fall-through */
561
+ case 12:
562
+ ctx->searchNum = LZ4HC_getSearchNum(cLevel);
563
+ return LZ4HC_compress_optimal(ctx, src, dst, *srcSizePtr, dstCapacity, limit, LZ4_OPT_NUM, 1);
564
+ }
565
+ }
566
+ return LZ4HC_compress_hashChain(ctx, src, dst, srcSizePtr, dstCapacity, 1 << (cLevel-1), limit); /* levels 1-9 */
567
+ }
568
+
569
+
570
+ int LZ4_sizeofStateHC(void) { return sizeof(LZ4_streamHC_t); }
571
+
572
+ int LZ4_compress_HC_extStateHC (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int compressionLevel)
573
+ {
574
+ LZ4HC_CCtx_internal* const ctx = &((LZ4_streamHC_t*)state)->internal_donotuse;
575
+ if (((size_t)(state)&(sizeof(void*)-1)) != 0) return 0; /* Error : state is not aligned for pointers (32 or 64 bits) */
576
+ LZ4HC_init (ctx, (const BYTE*)src);
577
+ if (dstCapacity < LZ4_compressBound(srcSize))
578
+ return LZ4HC_compress_generic (ctx, src, dst, &srcSize, dstCapacity, compressionLevel, limitedOutput);
579
+ else
580
+ return LZ4HC_compress_generic (ctx, src, dst, &srcSize, dstCapacity, compressionLevel, noLimit);
581
+ }
582
+
583
+ int LZ4_compress_HC(const char* src, char* dst, int srcSize, int dstCapacity, int compressionLevel)
584
+ {
585
+ #if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1
586
+ LZ4_streamHC_t* const statePtr = (LZ4_streamHC_t*)malloc(sizeof(LZ4_streamHC_t));
587
+ #else
588
+ LZ4_streamHC_t state;
589
+ LZ4_streamHC_t* const statePtr = &state;
590
+ #endif
591
+ int const cSize = LZ4_compress_HC_extStateHC(statePtr, src, dst, srcSize, dstCapacity, compressionLevel);
592
+ #if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1
593
+ free(statePtr);
594
+ #endif
595
+ return cSize;
596
+ }
597
+
598
+ /* LZ4_compress_HC_destSize() :
599
+ * currently, only compatible with Hash Chain implementation,
600
+ * hence limit compression level to LZ4HC_CLEVEL_OPT_MIN-1*/
601
+ int LZ4_compress_HC_destSize(void* LZ4HC_Data, const char* source, char* dest, int* sourceSizePtr, int targetDestSize, int cLevel)
602
+ {
603
+ LZ4HC_CCtx_internal* const ctx = &((LZ4_streamHC_t*)LZ4HC_Data)->internal_donotuse;
604
+ LZ4HC_init(ctx, (const BYTE*) source);
605
+ return LZ4HC_compress_generic(ctx, source, dest, sourceSizePtr, targetDestSize, cLevel, limitedDestSize);
606
+ }
607
+
608
+
609
+
610
+ /**************************************
611
+ * Streaming Functions
612
+ **************************************/
613
+ /* allocation */
614
+ LZ4_streamHC_t* LZ4_createStreamHC(void) { return (LZ4_streamHC_t*)malloc(sizeof(LZ4_streamHC_t)); }
615
+ int LZ4_freeStreamHC (LZ4_streamHC_t* LZ4_streamHCPtr) {
616
+ if (!LZ4_streamHCPtr) return 0; /* support free on NULL */
617
+ free(LZ4_streamHCPtr);
618
+ return 0;
619
+ }
620
+
621
+
622
+ /* initialization */
623
+ void LZ4_resetStreamHC (LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel)
624
+ {
625
+ LZ4_STATIC_ASSERT(sizeof(LZ4HC_CCtx_internal) <= sizeof(size_t) * LZ4_STREAMHCSIZE_SIZET); /* if compilation fails here, LZ4_STREAMHCSIZE must be increased */
626
+ LZ4_streamHCPtr->internal_donotuse.base = NULL;
627
+ if (compressionLevel > LZ4HC_CLEVEL_MAX) compressionLevel = LZ4HC_CLEVEL_MAX; /* cap compression level */
628
+ LZ4_streamHCPtr->internal_donotuse.compressionLevel = compressionLevel;
629
+ LZ4_streamHCPtr->internal_donotuse.searchNum = LZ4HC_getSearchNum(compressionLevel);
630
+ }
631
+
632
+ void LZ4_setCompressionLevel(LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel)
633
+ {
634
+ int const currentCLevel = LZ4_streamHCPtr->internal_donotuse.compressionLevel;
635
+ int const minCLevel = currentCLevel < LZ4HC_CLEVEL_OPT_MIN ? 1 : LZ4HC_CLEVEL_OPT_MIN;
636
+ int const maxCLevel = currentCLevel < LZ4HC_CLEVEL_OPT_MIN ? LZ4HC_CLEVEL_OPT_MIN-1 : LZ4HC_CLEVEL_MAX;
637
+ compressionLevel = MIN(compressionLevel, minCLevel);
638
+ compressionLevel = MAX(compressionLevel, maxCLevel);
639
+ LZ4_streamHCPtr->internal_donotuse.compressionLevel = compressionLevel;
640
+ }
641
+
642
+ int LZ4_loadDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, const char* dictionary, int dictSize)
643
+ {
644
+ LZ4HC_CCtx_internal* const ctxPtr = &LZ4_streamHCPtr->internal_donotuse;
645
+ if (dictSize > 64 KB) {
646
+ dictionary += dictSize - 64 KB;
647
+ dictSize = 64 KB;
648
+ }
649
+ LZ4HC_init (ctxPtr, (const BYTE*)dictionary);
650
+ ctxPtr->end = (const BYTE*)dictionary + dictSize;
651
+ if (ctxPtr->compressionLevel >= LZ4HC_CLEVEL_OPT_MIN)
652
+ LZ4HC_updateBinTree(ctxPtr, ctxPtr->end - MFLIMIT, ctxPtr->end - LASTLITERALS);
653
+ else
654
+ if (dictSize >= 4) LZ4HC_Insert (ctxPtr, ctxPtr->end-3);
655
+ return dictSize;
656
+ }
657
+
658
+
659
+ /* compression */
660
+
661
+ static void LZ4HC_setExternalDict(LZ4HC_CCtx_internal* ctxPtr, const BYTE* newBlock)
662
+ {
663
+ if (ctxPtr->compressionLevel >= LZ4HC_CLEVEL_OPT_MIN)
664
+ LZ4HC_updateBinTree(ctxPtr, ctxPtr->end - MFLIMIT, ctxPtr->end - LASTLITERALS);
665
+ else
666
+ if (ctxPtr->end >= ctxPtr->base + 4) LZ4HC_Insert (ctxPtr, ctxPtr->end-3); /* Referencing remaining dictionary content */
667
+
668
+ /* Only one memory segment for extDict, so any previous extDict is lost at this stage */
669
+ ctxPtr->lowLimit = ctxPtr->dictLimit;
670
+ ctxPtr->dictLimit = (U32)(ctxPtr->end - ctxPtr->base);
671
+ ctxPtr->dictBase = ctxPtr->base;
672
+ ctxPtr->base = newBlock - ctxPtr->dictLimit;
673
+ ctxPtr->end = newBlock;
674
+ ctxPtr->nextToUpdate = ctxPtr->dictLimit; /* match referencing will resume from there */
675
+ }
676
+
677
+ static int LZ4_compressHC_continue_generic (LZ4_streamHC_t* LZ4_streamHCPtr,
678
+ const char* src, char* dst,
679
+ int* srcSizePtr, int dstCapacity,
680
+ limitedOutput_directive limit)
681
+ {
682
+ LZ4HC_CCtx_internal* const ctxPtr = &LZ4_streamHCPtr->internal_donotuse;
683
+ /* auto-init if forgotten */
684
+ if (ctxPtr->base == NULL) LZ4HC_init (ctxPtr, (const BYTE*) src);
685
+
686
+ /* Check overflow */
687
+ if ((size_t)(ctxPtr->end - ctxPtr->base) > 2 GB) {
688
+ size_t dictSize = (size_t)(ctxPtr->end - ctxPtr->base) - ctxPtr->dictLimit;
689
+ if (dictSize > 64 KB) dictSize = 64 KB;
690
+ LZ4_loadDictHC(LZ4_streamHCPtr, (const char*)(ctxPtr->end) - dictSize, (int)dictSize);
691
+ }
692
+
693
+ /* Check if blocks follow each other */
694
+ if ((const BYTE*)src != ctxPtr->end) LZ4HC_setExternalDict(ctxPtr, (const BYTE*)src);
695
+
696
+ /* Check overlapping input/dictionary space */
697
+ { const BYTE* sourceEnd = (const BYTE*) src + *srcSizePtr;
698
+ const BYTE* const dictBegin = ctxPtr->dictBase + ctxPtr->lowLimit;
699
+ const BYTE* const dictEnd = ctxPtr->dictBase + ctxPtr->dictLimit;
700
+ if ((sourceEnd > dictBegin) && ((const BYTE*)src < dictEnd)) {
701
+ if (sourceEnd > dictEnd) sourceEnd = dictEnd;
702
+ ctxPtr->lowLimit = (U32)(sourceEnd - ctxPtr->dictBase);
703
+ if (ctxPtr->dictLimit - ctxPtr->lowLimit < 4) ctxPtr->lowLimit = ctxPtr->dictLimit;
704
+ }
705
+ }
706
+
707
+ return LZ4HC_compress_generic (ctxPtr, src, dst, srcSizePtr, dstCapacity, ctxPtr->compressionLevel, limit);
708
+ }
709
+
710
+ int LZ4_compress_HC_continue (LZ4_streamHC_t* LZ4_streamHCPtr, const char* src, char* dst, int srcSize, int dstCapacity)
711
+ {
712
+ if (dstCapacity < LZ4_compressBound(srcSize))
713
+ return LZ4_compressHC_continue_generic (LZ4_streamHCPtr, src, dst, &srcSize, dstCapacity, limitedOutput);
714
+ else
715
+ return LZ4_compressHC_continue_generic (LZ4_streamHCPtr, src, dst, &srcSize, dstCapacity, noLimit);
716
+ }
717
+
718
+ int LZ4_compress_HC_continue_destSize (LZ4_streamHC_t* LZ4_streamHCPtr, const char* src, char* dst, int* srcSizePtr, int targetDestSize)
719
+ {
720
+ LZ4HC_CCtx_internal* const ctxPtr = &LZ4_streamHCPtr->internal_donotuse;
721
+ if (ctxPtr->compressionLevel >= LZ4HC_CLEVEL_OPT_MIN) LZ4HC_init(ctxPtr, (const BYTE*)src); /* not compatible with btopt implementation */
722
+ return LZ4_compressHC_continue_generic(LZ4_streamHCPtr, src, dst, srcSizePtr, targetDestSize, limitedDestSize);
723
+ }
724
+
725
+
726
+
727
+ /* dictionary saving */
728
+
729
+ int LZ4_saveDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, char* safeBuffer, int dictSize)
730
+ {
731
+ LZ4HC_CCtx_internal* const streamPtr = &LZ4_streamHCPtr->internal_donotuse;
732
+ int const prefixSize = (int)(streamPtr->end - (streamPtr->base + streamPtr->dictLimit));
733
+ if (dictSize > 64 KB) dictSize = 64 KB;
734
+ if (dictSize < 4) dictSize = 0;
735
+ if (dictSize > prefixSize) dictSize = prefixSize;
736
+ memmove(safeBuffer, streamPtr->end - dictSize, dictSize);
737
+ { U32 const endIndex = (U32)(streamPtr->end - streamPtr->base);
738
+ streamPtr->end = (const BYTE*)safeBuffer + dictSize;
739
+ streamPtr->base = streamPtr->end - endIndex;
740
+ streamPtr->dictLimit = endIndex - dictSize;
741
+ streamPtr->lowLimit = endIndex - dictSize;
742
+ if (streamPtr->nextToUpdate < streamPtr->dictLimit) streamPtr->nextToUpdate = streamPtr->dictLimit;
743
+ }
744
+ return dictSize;
745
+ }
746
+
747
+
748
+ /***********************************
749
+ * Deprecated Functions
750
+ ***********************************/
751
+ /* These functions currently generate deprecation warnings */
752
+ /* Deprecated compression functions */
753
+ int LZ4_compressHC(const char* src, char* dst, int srcSize) { return LZ4_compress_HC (src, dst, srcSize, LZ4_compressBound(srcSize), 0); }
754
+ int LZ4_compressHC_limitedOutput(const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_HC(src, dst, srcSize, maxDstSize, 0); }
755
+ int LZ4_compressHC2(const char* src, char* dst, int srcSize, int cLevel) { return LZ4_compress_HC (src, dst, srcSize, LZ4_compressBound(srcSize), cLevel); }
756
+ int LZ4_compressHC2_limitedOutput(const char* src, char* dst, int srcSize, int maxDstSize, int cLevel) { return LZ4_compress_HC(src, dst, srcSize, maxDstSize, cLevel); }
757
+ int LZ4_compressHC_withStateHC (void* state, const char* src, char* dst, int srcSize) { return LZ4_compress_HC_extStateHC (state, src, dst, srcSize, LZ4_compressBound(srcSize), 0); }
758
+ int LZ4_compressHC_limitedOutput_withStateHC (void* state, const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_HC_extStateHC (state, src, dst, srcSize, maxDstSize, 0); }
759
+ int LZ4_compressHC2_withStateHC (void* state, const char* src, char* dst, int srcSize, int cLevel) { return LZ4_compress_HC_extStateHC(state, src, dst, srcSize, LZ4_compressBound(srcSize), cLevel); }
760
+ int LZ4_compressHC2_limitedOutput_withStateHC (void* state, const char* src, char* dst, int srcSize, int maxDstSize, int cLevel) { return LZ4_compress_HC_extStateHC(state, src, dst, srcSize, maxDstSize, cLevel); }
761
+ int LZ4_compressHC_continue (LZ4_streamHC_t* ctx, const char* src, char* dst, int srcSize) { return LZ4_compress_HC_continue (ctx, src, dst, srcSize, LZ4_compressBound(srcSize)); }
762
+ int LZ4_compressHC_limitedOutput_continue (LZ4_streamHC_t* ctx, const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_HC_continue (ctx, src, dst, srcSize, maxDstSize); }
763
+
764
+
765
+ /* Deprecated streaming functions */
766
+ int LZ4_sizeofStreamStateHC(void) { return LZ4_STREAMHCSIZE; }
767
+
768
+ int LZ4_resetStreamStateHC(void* state, char* inputBuffer)
769
+ {
770
+ LZ4HC_CCtx_internal *ctx = &((LZ4_streamHC_t*)state)->internal_donotuse;
771
+ if ((((size_t)state) & (sizeof(void*)-1)) != 0) return 1; /* Error : pointer is not aligned for pointer (32 or 64 bits) */
772
+ LZ4HC_init(ctx, (const BYTE*)inputBuffer);
773
+ ctx->inputBuffer = (BYTE*)inputBuffer;
774
+ return 0;
775
+ }
776
+
777
+ void* LZ4_createHC (char* inputBuffer)
778
+ {
779
+ LZ4_streamHC_t* hc4 = (LZ4_streamHC_t*)ALLOCATOR(1, sizeof(LZ4_streamHC_t));
780
+ if (hc4 == NULL) return NULL; /* not enough memory */
781
+ LZ4HC_init (&hc4->internal_donotuse, (const BYTE*)inputBuffer);
782
+ hc4->internal_donotuse.inputBuffer = (BYTE*)inputBuffer;
783
+ return hc4;
784
+ }
785
+
786
+ int LZ4_freeHC (void* LZ4HC_Data) {
787
+ if (!LZ4HC_Data) return 0; /* support free on NULL */
788
+ FREEMEM(LZ4HC_Data);
789
+ return 0;
790
+ }
791
+
792
+ int LZ4_compressHC2_continue (void* LZ4HC_Data, const char* src, char* dst, int srcSize, int cLevel)
793
+ {
794
+ return LZ4HC_compress_generic (&((LZ4_streamHC_t*)LZ4HC_Data)->internal_donotuse, src, dst, &srcSize, 0, cLevel, noLimit);
795
+ }
796
+
797
+ int LZ4_compressHC2_limitedOutput_continue (void* LZ4HC_Data, const char* src, char* dst, int srcSize, int dstCapacity, int cLevel)
798
+ {
799
+ return LZ4HC_compress_generic (&((LZ4_streamHC_t*)LZ4HC_Data)->internal_donotuse, src, dst, &srcSize, dstCapacity, cLevel, limitedOutput);
800
+ }
801
+
802
+ char* LZ4_slideInputBufferHC(void* LZ4HC_Data)
803
+ {
804
+ LZ4HC_CCtx_internal* const hc4 = &((LZ4_streamHC_t*)LZ4HC_Data)->internal_donotuse;
805
+ int const dictSize = LZ4_saveDictHC((LZ4_streamHC_t*)LZ4HC_Data, (char*)(hc4->inputBuffer), 64 KB);
806
+ return (char*)(hc4->inputBuffer + dictSize);
807
+ }