2 LZ4 Encoder - Part of LZ4 compression algorithm
3 Copyright (C) 2011-2013, Yann Collet.
4 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
10 * Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above
13 copyright notice, this list of conditions and the following disclaimer
14 in the documentation and/or other materials provided with the
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 You can contact the author at :
30 - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html
31 - LZ4 source repository : http://code.google.com/p/lz4/
34 /* lz4_encoder.h must be included into lz4.c
35 The objective of this file is to create a single LZ4 compression function source
36 which will be instanciated multiple times with minor variations
37 depending on a set of #define.
46 LZ4_compress_heap_limitedOutput(
54 LZ4_compress64k_heap_limitedOutput(
62 //****************************
64 //****************************
67 # define HASHLOG (MEMORY_USAGE-1)
68 # define CURRENT_H_TYPE U16
69 # define CURRENTBASE(base) BYTE* base = ip
71 # define HASHLOG (MEMORY_USAGE-2)
72 # define CURRENT_H_TYPE HTYPE
73 # define CURRENTBASE(base) INITBASE(base)
76 #define HASHTABLE_NBCELLS (1U<<HASHLOG)
77 #define LZ4_HASH(i) (((i) * 2654435761U) >> ((MINMATCH*8)-HASHLOG))
78 #define LZ4_HASHVALUE(p) LZ4_HASH(A32(p))
82 //****************************
84 //****************************
87 LZ4_compress_heap_limitedOutput(
94 CURRENT_H_TYPE
* HashTable
= (CURRENT_H_TYPE
*)ctx
;
96 BYTE
* ip
= (BYTE
*) source
;
99 BYTE
* iend
= ip
+ inputSize
;
100 BYTE
* mflimit
= iend
- MFLIMIT
;
101 #define matchlimit (iend - LASTLITERALS)
103 BYTE
* op
= (BYTE
*) dest
;
104 BYTE
* oend
= op
+ maxOutputSize
;
107 int skipStrength
= SKIPSTRENGTH
;
112 if (inputSize
<MINLENGTH
) goto _last_literals
;
114 memset((void*)HashTable
, 0, HASHTABLESIZE
);
117 HashTable
[LZ4_HASHVALUE(ip
)] = (CURRENT_H_TYPE
)(ip
- base
);
119 forwardH
= LZ4_HASHVALUE(ip
);
124 int findMatchAttempts
= (1U << skipStrength
) + 3;
125 BYTE
* forwardIp
= ip
;
132 int step
= findMatchAttempts
++ >> skipStrength
;
134 forwardIp
= ip
+ step
;
136 if unlikely(forwardIp
> mflimit
) {
140 forwardH
= LZ4_HASHVALUE(forwardIp
);
141 ref
= base
+ HashTable
[h
];
142 HashTable
[h
] = (CURRENT_H_TYPE
)(ip
- base
);
144 } while ((ref
< ip
- MAX_DISTANCE
) || (A32(ref
) != A32(ip
)));
147 while ((ip
>anchor
) && (ref
>(BYTE
*)source
) && unlikely(ip
[-1]==ref
[-1])) {
152 // Encode Literal length
153 length
= (int)(ip
- anchor
);
156 if unlikely(op
+ length
+ (2 + 1 + LASTLITERALS
) + (length
>>8) > oend
)
157 return 0; // Check output limit
159 if (length
>=(int)RUN_MASK
)
161 int len
= length
-RUN_MASK
;
162 *token
=(RUN_MASK
<<ML_BITS
);
163 for(; len
>= 255 ; len
-=255)
167 else *token
= (BYTE
)(length
<<ML_BITS
);
170 LZ4_BLINDCOPY(anchor
, op
, length
);
174 LZ4_WRITE_LITTLEENDIAN_16(op
,(U16
)(ip
-ref
));
177 ip
+=MINMATCH
; ref
+=MINMATCH
; // MinMatch already verified
179 while likely(ip
<matchlimit
-(STEPSIZE
-1))
181 UARCH diff
= AARCH(ref
) ^ AARCH(ip
);
187 ip
+= LZ4_NbCommonBytes(diff
);
190 if (LZ4_ARCH64
) if ((ip
<(matchlimit
-3)) && (A32(ref
) == A32(ip
))) {
194 if ((ip
<(matchlimit
-1)) && (A16(ref
) == A16(ip
))) {
198 if ((ip
<matchlimit
) && (*ref
== *ip
))
202 // Encode MatchLength
203 length
= (int)(ip
- anchor
);
205 if unlikely(op
+ (1 + LASTLITERALS
) + (length
>>8) > oend
)
206 return 0; // Check output limit
208 if (length
>=(int)ML_MASK
)
212 for (; length
> 509 ; length
-=510) {
220 *op
++ = (BYTE
)length
;
222 else *token
+= (BYTE
)length
;
231 HashTable
[LZ4_HASHVALUE(ip
-2)] = (CURRENT_H_TYPE
)(ip
- 2 - base
);
233 // Test next position
234 ref
= base
+ HashTable
[LZ4_HASHVALUE(ip
)];
235 HashTable
[LZ4_HASHVALUE(ip
)] = (CURRENT_H_TYPE
)(ip
- base
);
236 if ((ref
>= ip
- MAX_DISTANCE
) && (A32(ref
) == A32(ip
))) {
244 forwardH
= LZ4_HASHVALUE(ip
);
248 // Encode Last Literals
250 int lastRun
= (int)(iend
- anchor
);
252 if (((char*)op
- dest
) + lastRun
+ 1 + ((lastRun
+255-RUN_MASK
)/255) > (U32
)maxOutputSize
)
253 return 0; // Check output limit
255 if (lastRun
>=(int)RUN_MASK
) {
256 *op
++=(RUN_MASK
<<ML_BITS
);
258 for(; lastRun
>= 255 ; lastRun
-=255)
260 *op
++ = (BYTE
) lastRun
;
262 else *op
++ = (BYTE
)(lastRun
<<ML_BITS
);
263 memcpy(op
, anchor
, iend
- anchor
);
268 return (int) (((char*)op
)-dest
);
272 LZ4_compress64k_heap_limitedOutput(
279 CURRENT_H_TYPE
* HashTable
= (CURRENT_H_TYPE
*)ctx
;
281 BYTE
* ip
= (BYTE
*) source
;
284 BYTE
* iend
= ip
+ inputSize
;
285 BYTE
* mflimit
= iend
- MFLIMIT
;
286 #define matchlimit (iend - LASTLITERALS)
288 BYTE
* op
= (BYTE
*) dest
;
289 BYTE
* oend
= op
+ maxOutputSize
;
292 int skipStrength
= SKIPSTRENGTH
;
297 if (inputSize
<MINLENGTH
) goto _last_literals
;
299 memset((void*)HashTable
, 0, HASHTABLESIZE
);
302 HashTable
[LZ4_HASHVALUE(ip
)] = (CURRENT_H_TYPE
)(ip
- base
);
304 forwardH
= LZ4_HASHVALUE(ip
);
309 int findMatchAttempts
= (1U << skipStrength
) + 3;
310 BYTE
* forwardIp
= ip
;
317 int step
= findMatchAttempts
++ >> skipStrength
;
319 forwardIp
= ip
+ step
;
321 if unlikely(forwardIp
> mflimit
) {
325 forwardH
= LZ4_HASHVALUE(forwardIp
);
326 ref
= base
+ HashTable
[h
];
327 HashTable
[h
] = (CURRENT_H_TYPE
)(ip
- base
);
329 } while ((ref
< ip
- MAX_DISTANCE
) || (A32(ref
) != A32(ip
)));
332 while ((ip
>anchor
) && (ref
>(BYTE
*)source
) && unlikely(ip
[-1]==ref
[-1])) {
337 // Encode Literal length
338 length
= (int)(ip
- anchor
);
341 if unlikely(op
+ length
+ (2 + 1 + LASTLITERALS
) + (length
>>8) > oend
)
342 return 0; // Check output limit
344 if (length
>=(int)RUN_MASK
)
346 int len
= length
-RUN_MASK
;
347 *token
=(RUN_MASK
<<ML_BITS
);
348 for(; len
>= 255 ; len
-=255)
352 else *token
= (BYTE
)(length
<<ML_BITS
);
355 LZ4_BLINDCOPY(anchor
, op
, length
);
359 LZ4_WRITE_LITTLEENDIAN_16(op
,(U16
)(ip
-ref
));
362 ip
+=MINMATCH
; ref
+=MINMATCH
; // MinMatch already verified
364 while likely(ip
<matchlimit
-(STEPSIZE
-1))
366 UARCH diff
= AARCH(ref
) ^ AARCH(ip
);
372 ip
+= LZ4_NbCommonBytes(diff
);
375 if (LZ4_ARCH64
) if ((ip
<(matchlimit
-3)) && (A32(ref
) == A32(ip
))) {
379 if ((ip
<(matchlimit
-1)) && (A16(ref
) == A16(ip
))) {
383 if ((ip
<matchlimit
) && (*ref
== *ip
))
387 // Encode MatchLength
388 length
= (int)(ip
- anchor
);
390 if unlikely(op
+ (1 + LASTLITERALS
) + (length
>>8) > oend
)
391 return 0; // Check output limit
393 if (length
>=(int)ML_MASK
)
397 for (; length
> 509 ; length
-=510) {
405 *op
++ = (BYTE
)length
;
407 else *token
+= (BYTE
)length
;
416 HashTable
[LZ4_HASHVALUE(ip
-2)] = (CURRENT_H_TYPE
)(ip
- 2 - base
);
418 // Test next position
419 ref
= base
+ HashTable
[LZ4_HASHVALUE(ip
)];
420 HashTable
[LZ4_HASHVALUE(ip
)] = (CURRENT_H_TYPE
)(ip
- base
);
421 if ((ref
>= ip
- MAX_DISTANCE
) && (A32(ref
) == A32(ip
))) {
429 forwardH
= LZ4_HASHVALUE(ip
);
433 // Encode Last Literals
435 int lastRun
= (int)(iend
- anchor
);
437 if (((char*)op
- dest
) + lastRun
+ 1 +
438 ((lastRun
+255-RUN_MASK
)/255) > (U32
)maxOutputSize
)
439 return 0; // Check output limit
441 if (lastRun
>=(int)RUN_MASK
) {
442 *op
++=(RUN_MASK
<<ML_BITS
);
444 for(; lastRun
>= 255 ; lastRun
-=255)
446 *op
++ = (BYTE
) lastRun
;
448 else *op
++ = (BYTE
)(lastRun
<<ML_BITS
);
449 memcpy(op
, anchor
, iend
- anchor
);
454 return (int) (((char*)op
)-dest
);
457 //****************************
459 //****************************
463 #undef HASHTABLE_NBCELLS
466 #undef CURRENT_H_TYPE