2 * LZ4 HC - High Compression Mode of LZ4
3 * Copyright (C) 2011-2015, Yann Collet.
5 * BSD 2 - Clause License (http://www.opensource.org/licenses/bsd - license.php)
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 * You can contact the author at :
27 * - LZ4 homepage : http://www.lz4.org
28 * - LZ4 source repository : https://github.com/lz4/lz4
30 * Changed for kernel usage by:
31 * Sven Schmidt <4sschmid@informatik.uni-hamburg.de>
34 /*-************************************
36 **************************************/
37 #include <linux/lz4.h>
39 #include <linux/module.h>
40 #include <linux/kernel.h>
41 #include <linux/string.h> /* memset */
43 /* *************************************
44 * Local Constants and types
45 ***************************************/
47 #define OPTIMAL_ML (int)((ML_MASK - 1) + MINMATCH)
49 #define HASH_FUNCTION(i) (((i) * 2654435761U) \
50 >> ((MINMATCH*8) - LZ4HC_HASH_LOG))
51 #define DELTANEXTU16(p) chainTable[(U16)(p)] /* faster */
53 static U32
LZ4HC_hashPtr(const void *ptr
)
55 return HASH_FUNCTION(LZ4_read32(ptr
));
58 /**************************************
60 **************************************/
61 static void LZ4HC_init(LZ4HC_CCtx_internal
*hc4
, const BYTE
*start
)
63 memset((void *)hc4
->hashTable
, 0, sizeof(hc4
->hashTable
));
64 memset(hc4
->chainTable
, 0xFF, sizeof(hc4
->chainTable
));
65 hc4
->nextToUpdate
= 64 * KB
;
66 hc4
->base
= start
- 64 * KB
;
68 hc4
->dictBase
= start
- 64 * KB
;
69 hc4
->dictLimit
= 64 * KB
;
70 hc4
->lowLimit
= 64 * KB
;
73 /* Update chains up to ip (excluded) */
74 static FORCE_INLINE
void LZ4HC_Insert(LZ4HC_CCtx_internal
*hc4
,
77 U16
* const chainTable
= hc4
->chainTable
;
78 U32
* const hashTable
= hc4
->hashTable
;
79 const BYTE
* const base
= hc4
->base
;
80 U32
const target
= (U32
)(ip
- base
);
81 U32 idx
= hc4
->nextToUpdate
;
83 while (idx
< target
) {
84 U32
const h
= LZ4HC_hashPtr(base
+ idx
);
85 size_t delta
= idx
- hashTable
[h
];
87 if (delta
> MAX_DISTANCE
)
90 DELTANEXTU16(idx
) = (U16
)delta
;
96 hc4
->nextToUpdate
= target
;
99 static FORCE_INLINE
int LZ4HC_InsertAndFindBestMatch(
100 LZ4HC_CCtx_internal
*hc4
, /* Index table will be updated */
102 const BYTE
* const iLimit
,
103 const BYTE
**matchpos
,
104 const int maxNbAttempts
)
106 U16
* const chainTable
= hc4
->chainTable
;
107 U32
* const HashTable
= hc4
->hashTable
;
108 const BYTE
* const base
= hc4
->base
;
109 const BYTE
* const dictBase
= hc4
->dictBase
;
110 const U32 dictLimit
= hc4
->dictLimit
;
111 const U32 lowLimit
= (hc4
->lowLimit
+ 64 * KB
> (U32
)(ip
- base
))
113 : (U32
)(ip
- base
) - (64 * KB
- 1);
115 int nbAttempts
= maxNbAttempts
;
118 /* HC4 match finder */
119 LZ4HC_Insert(hc4
, ip
);
120 matchIndex
= HashTable
[LZ4HC_hashPtr(ip
)];
122 while ((matchIndex
>= lowLimit
)
125 if (matchIndex
>= dictLimit
) {
126 const BYTE
* const match
= base
+ matchIndex
;
128 if (*(match
+ ml
) == *(ip
+ ml
)
129 && (LZ4_read32(match
) == LZ4_read32(ip
))) {
130 size_t const mlt
= LZ4_count(ip
+ MINMATCH
,
131 match
+ MINMATCH
, iLimit
) + MINMATCH
;
139 const BYTE
* const match
= dictBase
+ matchIndex
;
141 if (LZ4_read32(match
) == LZ4_read32(ip
)) {
143 const BYTE
*vLimit
= ip
144 + (dictLimit
- matchIndex
);
148 mlt
= LZ4_count(ip
+ MINMATCH
,
149 match
+ MINMATCH
, vLimit
) + MINMATCH
;
150 if ((ip
+ mlt
== vLimit
)
151 && (vLimit
< iLimit
))
152 mlt
+= LZ4_count(ip
+ mlt
,
156 /* virtual matchpos */
158 *matchpos
= base
+ matchIndex
;
162 matchIndex
-= DELTANEXTU16(matchIndex
);
168 static 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
,
174 const BYTE
**matchpos
,
175 const BYTE
**startpos
,
176 const int maxNbAttempts
)
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
))
185 : (U32
)(ip
- base
) - (64 * KB
- 1);
186 const BYTE
* const dictBase
= hc4
->dictBase
;
188 int nbAttempts
= maxNbAttempts
;
189 int delta
= (int)(ip
- iLowLimit
);
192 LZ4HC_Insert(hc4
, ip
);
193 matchIndex
= HashTable
[LZ4HC_hashPtr(ip
)];
195 while ((matchIndex
>= lowLimit
)
198 if (matchIndex
>= dictLimit
) {
199 const BYTE
*matchPtr
= base
+ matchIndex
;
201 if (*(iLowLimit
+ longest
)
202 == *(matchPtr
- delta
+ longest
)) {
203 if (LZ4_read32(matchPtr
) == LZ4_read32(ip
)) {
204 int mlt
= MINMATCH
+ LZ4_count(
210 while ((ip
+ back
> iLowLimit
)
211 && (matchPtr
+ back
> lowPrefixPtr
)
212 && (ip
[back
- 1] == matchPtr
[back
- 1]))
219 *matchpos
= matchPtr
+ back
;
220 *startpos
= ip
+ back
;
225 const BYTE
* const matchPtr
= dictBase
+ matchIndex
;
227 if (LZ4_read32(matchPtr
) == LZ4_read32(ip
)) {
230 const BYTE
*vLimit
= ip
+ (dictLimit
- matchIndex
);
232 if (vLimit
> iHighLimit
)
235 mlt
= LZ4_count(ip
+ MINMATCH
,
236 matchPtr
+ MINMATCH
, vLimit
) + MINMATCH
;
238 if ((ip
+ mlt
== vLimit
) && (vLimit
< iHighLimit
))
239 mlt
+= LZ4_count(ip
+ mlt
, base
+ dictLimit
,
241 while ((ip
+ back
> iLowLimit
)
242 && (matchIndex
+ back
> lowLimit
)
243 && (ip
[back
- 1] == matchPtr
[back
- 1]))
248 if ((int)mlt
> longest
) {
250 *matchpos
= base
+ matchIndex
+ back
;
251 *startpos
= ip
+ back
;
256 matchIndex
-= DELTANEXTU16(matchIndex
);
262 static FORCE_INLINE
int LZ4HC_encodeSequence(
267 const BYTE
* const match
,
268 limitedOutput_directive limitedOutputBuffer
,
274 /* Encode Literal length */
275 length
= (int)(*ip
- *anchor
);
278 if ((limitedOutputBuffer
)
279 && ((*op
+ (length
>>8)
280 + length
+ (2 + 1 + LASTLITERALS
)) > oend
)) {
281 /* Check output limit */
284 if (length
>= (int)RUN_MASK
) {
287 *token
= (RUN_MASK
<<ML_BITS
);
288 len
= length
- RUN_MASK
;
289 for (; len
> 254 ; len
-= 255)
291 *(*op
)++ = (BYTE
)len
;
293 *token
= (BYTE
)(length
<<ML_BITS
);
296 LZ4_wildCopy(*op
, *anchor
, (*op
) + length
);
300 LZ4_writeLE16(*op
, (U16
)(*ip
- match
));
303 /* Encode MatchLength */
304 length
= (int)(matchLength
- MINMATCH
);
306 if ((limitedOutputBuffer
)
307 && (*op
+ (length
>>8)
308 + (1 + LASTLITERALS
) > oend
)) {
309 /* Check output limit */
313 if (length
>= (int)ML_MASK
) {
317 for (; length
> 509 ; length
-= 510) {
327 *(*op
)++ = (BYTE
)length
;
329 *token
+= (BYTE
)(length
);
331 /* Prepare next loop */
338 static int LZ4HC_compress_generic(
339 LZ4HC_CCtx_internal
*const ctx
,
340 const char * const source
,
343 int const maxOutputSize
,
344 int compressionLevel
,
345 limitedOutput_directive limit
348 const BYTE
*ip
= (const BYTE
*) source
;
349 const BYTE
*anchor
= ip
;
350 const BYTE
* const iend
= ip
+ inputSize
;
351 const BYTE
* const mflimit
= iend
- MFLIMIT
;
352 const BYTE
* const matchlimit
= (iend
- LASTLITERALS
);
354 BYTE
*op
= (BYTE
*) dest
;
355 BYTE
* const oend
= op
+ maxOutputSize
;
357 unsigned int maxNbAttempts
;
358 int ml
, ml2
, ml3
, ml0
;
359 const BYTE
*ref
= NULL
;
360 const BYTE
*start2
= NULL
;
361 const BYTE
*ref2
= NULL
;
362 const BYTE
*start3
= NULL
;
363 const BYTE
*ref3
= NULL
;
368 if (compressionLevel
> LZ4HC_MAX_CLEVEL
)
369 compressionLevel
= LZ4HC_MAX_CLEVEL
;
370 if (compressionLevel
< 1)
371 compressionLevel
= LZ4HC_DEFAULT_CLEVEL
;
372 maxNbAttempts
= 1 << (compressionLevel
- 1);
373 ctx
->end
+= inputSize
;
378 while (ip
< mflimit
) {
379 ml
= LZ4HC_InsertAndFindBestMatch(ctx
, ip
,
380 matchlimit
, (&ref
), maxNbAttempts
);
386 /* saved, in case we would skip too much */
392 if (ip
+ ml
< mflimit
)
393 ml2
= LZ4HC_InsertAndGetWiderMatch(ctx
,
395 matchlimit
, ml
, &ref2
,
396 &start2
, maxNbAttempts
);
401 /* No better match */
402 if (LZ4HC_encodeSequence(&ip
, &op
,
403 &anchor
, ml
, ref
, limit
, oend
))
409 if (start2
< ip
+ ml0
) {
417 /* Here, start0 == ip */
418 if ((start2
- ip
) < 3) {
419 /* First Match too small : removed */
428 * Currently we have :
430 * ip1 + 3 <= ip2 (usually < ip1 + ml1)
432 if ((start2
- ip
) < OPTIMAL_ML
) {
436 if (new_ml
> OPTIMAL_ML
)
438 if (ip
+ new_ml
> start2
+ ml2
- MINMATCH
)
439 new_ml
= (int)(start2
- ip
) + ml2
- MINMATCH
;
441 correction
= new_ml
- (int)(start2
- ip
);
443 if (correction
> 0) {
444 start2
+= correction
;
450 * Now, we have start2 = ip + new_ml,
451 * with new_ml = min(ml, OPTIMAL_ML = 18)
454 if (start2
+ ml2
< mflimit
)
455 ml3
= LZ4HC_InsertAndGetWiderMatch(ctx
,
456 start2
+ ml2
- 3, start2
,
457 matchlimit
, ml2
, &ref3
, &start3
,
463 /* No better match : 2 sequences to encode */
464 /* ip & ref are known; Now for ml */
465 if (start2
< ip
+ ml
)
466 ml
= (int)(start2
- ip
);
467 /* Now, encode 2 sequences */
468 if (LZ4HC_encodeSequence(&ip
, &op
, &anchor
,
469 ml
, ref
, limit
, oend
))
472 if (LZ4HC_encodeSequence(&ip
, &op
, &anchor
,
473 ml2
, ref2
, limit
, oend
))
478 if (start3
< ip
+ ml
+ 3) {
479 /* Not enough space for match 2 : remove it */
480 if (start3
>= (ip
+ ml
)) {
481 /* can write Seq1 immediately
482 * ==> Seq2 is removed,
483 * so Seq3 becomes Seq1
485 if (start2
< ip
+ ml
) {
486 int correction
= (int)(ip
+ ml
- start2
);
488 start2
+= correction
;
491 if (ml2
< MINMATCH
) {
498 if (LZ4HC_encodeSequence(&ip
, &op
, &anchor
,
499 ml
, ref
, limit
, oend
))
518 * OK, now we have 3 ascending matches;
519 * let's write at least the first one
520 * ip & ref are known; Now for ml
522 if (start2
< ip
+ ml
) {
523 if ((start2
- ip
) < (int)ML_MASK
) {
528 if (ip
+ ml
> start2
+ ml2
- MINMATCH
)
529 ml
= (int)(start2
- ip
) + ml2
- MINMATCH
;
530 correction
= ml
- (int)(start2
- ip
);
531 if (correction
> 0) {
532 start2
+= correction
;
537 ml
= (int)(start2
- ip
);
539 if (LZ4HC_encodeSequence(&ip
, &op
, &anchor
, ml
,
554 /* Encode Last Literals */
556 int lastRun
= (int)(iend
- anchor
);
559 && (((char *)op
- dest
) + lastRun
+ 1
560 + ((lastRun
+ 255 - RUN_MASK
)/255)
561 > (U32
)maxOutputSize
)) {
562 /* Check output limit */
565 if (lastRun
>= (int)RUN_MASK
) {
566 *op
++ = (RUN_MASK
<<ML_BITS
);
568 for (; lastRun
> 254 ; lastRun
-= 255)
570 *op
++ = (BYTE
) lastRun
;
572 *op
++ = (BYTE
)(lastRun
<<ML_BITS
);
573 memcpy(op
, anchor
, iend
- anchor
);
578 return (int) (((char *)op
) - dest
);
581 static int LZ4_compress_HC_extStateHC(
587 int compressionLevel
)
589 LZ4HC_CCtx_internal
*ctx
= &((LZ4_streamHC_t
*)state
)->internal_donotuse
;
591 if (((size_t)(state
)&(sizeof(void *) - 1)) != 0) {
592 /* Error : state is not aligned
593 * for pointers (32 or 64 bits)
598 LZ4HC_init(ctx
, (const BYTE
*)src
);
600 if (maxDstSize
< LZ4_compressBound(srcSize
))
601 return LZ4HC_compress_generic(ctx
, src
, dst
,
602 srcSize
, maxDstSize
, compressionLevel
, limitedOutput
);
604 return LZ4HC_compress_generic(ctx
, src
, dst
,
605 srcSize
, maxDstSize
, compressionLevel
, noLimit
);
608 int LZ4_compress_HC(const char *src
, char *dst
, int srcSize
,
609 int maxDstSize
, int compressionLevel
, void *wrkmem
)
611 return LZ4_compress_HC_extStateHC(wrkmem
, src
, dst
,
612 srcSize
, maxDstSize
, compressionLevel
);
614 EXPORT_SYMBOL(LZ4_compress_HC
);
616 /**************************************
617 * Streaming Functions
618 **************************************/
619 void LZ4_resetStreamHC(LZ4_streamHC_t
*LZ4_streamHCPtr
, int compressionLevel
)
621 LZ4_streamHCPtr
->internal_donotuse
.base
= NULL
;
622 LZ4_streamHCPtr
->internal_donotuse
.compressionLevel
= (unsigned int)compressionLevel
;
625 int LZ4_loadDictHC(LZ4_streamHC_t
*LZ4_streamHCPtr
,
626 const char *dictionary
,
629 LZ4HC_CCtx_internal
*ctxPtr
= &LZ4_streamHCPtr
->internal_donotuse
;
631 if (dictSize
> 64 * KB
) {
632 dictionary
+= dictSize
- 64 * KB
;
635 LZ4HC_init(ctxPtr
, (const BYTE
*)dictionary
);
637 LZ4HC_Insert(ctxPtr
, (const BYTE
*)dictionary
+ (dictSize
- 3));
638 ctxPtr
->end
= (const BYTE
*)dictionary
+ dictSize
;
641 EXPORT_SYMBOL(LZ4_loadDictHC
);
645 static void LZ4HC_setExternalDict(
646 LZ4HC_CCtx_internal
*ctxPtr
,
647 const BYTE
*newBlock
)
649 if (ctxPtr
->end
>= ctxPtr
->base
+ 4) {
650 /* Referencing remaining dictionary content */
651 LZ4HC_Insert(ctxPtr
, ctxPtr
->end
- 3);
655 * Only one memory segment for extDict,
656 * so any previous extDict is lost at this stage
658 ctxPtr
->lowLimit
= ctxPtr
->dictLimit
;
659 ctxPtr
->dictLimit
= (U32
)(ctxPtr
->end
- ctxPtr
->base
);
660 ctxPtr
->dictBase
= ctxPtr
->base
;
661 ctxPtr
->base
= newBlock
- ctxPtr
->dictLimit
;
662 ctxPtr
->end
= newBlock
;
663 /* match referencing will resume from there */
664 ctxPtr
->nextToUpdate
= ctxPtr
->dictLimit
;
666 EXPORT_SYMBOL(LZ4HC_setExternalDict
);
668 static int LZ4_compressHC_continue_generic(
669 LZ4_streamHC_t
*LZ4_streamHCPtr
,
674 limitedOutput_directive limit
)
676 LZ4HC_CCtx_internal
*ctxPtr
= &LZ4_streamHCPtr
->internal_donotuse
;
678 /* auto - init if forgotten */
679 if (ctxPtr
->base
== NULL
)
680 LZ4HC_init(ctxPtr
, (const BYTE
*) source
);
683 if ((size_t)(ctxPtr
->end
- ctxPtr
->base
) > 2 * GB
) {
684 size_t dictSize
= (size_t)(ctxPtr
->end
- ctxPtr
->base
)
686 if (dictSize
> 64 * KB
)
688 LZ4_loadDictHC(LZ4_streamHCPtr
,
689 (const char *)(ctxPtr
->end
) - dictSize
, (int)dictSize
);
692 /* Check if blocks follow each other */
693 if ((const BYTE
*)source
!= ctxPtr
->end
)
694 LZ4HC_setExternalDict(ctxPtr
, (const BYTE
*)source
);
696 /* Check overlapping input/dictionary space */
698 const BYTE
*sourceEnd
= (const BYTE
*) source
+ inputSize
;
699 const BYTE
* const dictBegin
= ctxPtr
->dictBase
+ ctxPtr
->lowLimit
;
700 const BYTE
* const dictEnd
= ctxPtr
->dictBase
+ ctxPtr
->dictLimit
;
702 if ((sourceEnd
> dictBegin
)
703 && ((const BYTE
*)source
< dictEnd
)) {
704 if (sourceEnd
> dictEnd
)
706 ctxPtr
->lowLimit
= (U32
)(sourceEnd
- ctxPtr
->dictBase
);
708 if (ctxPtr
->dictLimit
- ctxPtr
->lowLimit
< 4)
709 ctxPtr
->lowLimit
= ctxPtr
->dictLimit
;
713 return LZ4HC_compress_generic(ctxPtr
, source
, dest
,
714 inputSize
, maxOutputSize
, ctxPtr
->compressionLevel
, limit
);
717 int LZ4_compress_HC_continue(
718 LZ4_streamHC_t
*LZ4_streamHCPtr
,
724 if (maxOutputSize
< LZ4_compressBound(inputSize
))
725 return LZ4_compressHC_continue_generic(LZ4_streamHCPtr
,
726 source
, dest
, inputSize
, maxOutputSize
, limitedOutput
);
728 return LZ4_compressHC_continue_generic(LZ4_streamHCPtr
,
729 source
, dest
, inputSize
, maxOutputSize
, noLimit
);
731 EXPORT_SYMBOL(LZ4_compress_HC_continue
);
733 /* dictionary saving */
736 LZ4_streamHC_t
*LZ4_streamHCPtr
,
740 LZ4HC_CCtx_internal
*const streamPtr
= &LZ4_streamHCPtr
->internal_donotuse
;
741 int const prefixSize
= (int)(streamPtr
->end
742 - (streamPtr
->base
+ streamPtr
->dictLimit
));
744 if (dictSize
> 64 * KB
)
748 if (dictSize
> prefixSize
)
749 dictSize
= prefixSize
;
751 memmove(safeBuffer
, streamPtr
->end
- dictSize
, dictSize
);
754 U32
const endIndex
= (U32
)(streamPtr
->end
- streamPtr
->base
);
756 streamPtr
->end
= (const BYTE
*)safeBuffer
+ dictSize
;
757 streamPtr
->base
= streamPtr
->end
- endIndex
;
758 streamPtr
->dictLimit
= endIndex
- dictSize
;
759 streamPtr
->lowLimit
= endIndex
- dictSize
;
761 if (streamPtr
->nextToUpdate
< streamPtr
->dictLimit
)
762 streamPtr
->nextToUpdate
= streamPtr
->dictLimit
;
766 EXPORT_SYMBOL(LZ4_saveDictHC
);
768 MODULE_LICENSE("Dual BSD/GPL");
769 MODULE_DESCRIPTION("LZ4 HC compressor");