RTEMS 6.3
Loading...
Searching...
No Matches
fastlz.c
1/*
2 FastLZ - lightning-fast lossless compression library
3
4 Copyright (C) 2007 Ariya Hidayat (ariya@kde.org)
5 Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)
6 Copyright (C) 2005 Ariya Hidayat (ariya@kde.org)
7
8 Permission is hereby granted, free of charge, to any person obtaining a copy
9 of this software and associated documentation files (the "Software"), to deal
10 in the Software without restriction, including without limitation the rights
11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 copies of the Software, and to permit persons to whom the Software is
13 furnished to do so, subject to the following conditions:
14
15 The above copyright notice and this permission notice shall be included in
16 all copies or substantial portions of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 THE SOFTWARE.
25*/
26
27#if !defined(FASTLZ__COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR)
28
29/*
30 * Always check for bound when decompressing.
31 * Generally it is best to leave it defined.
32 */
33#define FASTLZ_SAFE
34
35/*
36 * Give hints to the compiler for branch prediction optimization.
37 */
38#if defined(__GNUC__) && (__GNUC__ > 2)
39#define FASTLZ_EXPECT_CONDITIONAL(c) (__builtin_expect((c), 1))
40#define FASTLZ_UNEXPECT_CONDITIONAL(c) (__builtin_expect((c), 0))
41#else
42#define FASTLZ_EXPECT_CONDITIONAL(c) (c)
43#define FASTLZ_UNEXPECT_CONDITIONAL(c) (c)
44#endif
45
46/*
47 * Use inlined functions for supported systems.
48 */
49#if defined(__GNUC__) || defined(__DMC__) || defined(__POCC__) || defined(__WATCOMC__) || defined(__SUNPRO_C)
50#define FASTLZ_INLINE inline
51#elif defined(__BORLANDC__) || defined(_MSC_VER) || defined(__LCC__)
52#define FASTLZ_INLINE __inline
53#else
54#define FASTLZ_INLINE
55#endif
56
57/*
58 * Prevent accessing more than 8-bit at once, except on x86 architectures.
59 */
60#if !defined(FASTLZ_STRICT_ALIGN)
61#define FASTLZ_STRICT_ALIGN
62#if defined(__i386__) || defined(__386) /* GNU C, Sun Studio */
63#undef FASTLZ_STRICT_ALIGN
64#elif defined(__i486__) || defined(__i586__) || defined(__i686__) /* GNU C */
65#undef FASTLZ_STRICT_ALIGN
66#elif defined(_M_IX86) /* Intel, MSVC */
67#undef FASTLZ_STRICT_ALIGN
68#elif defined(__386)
69#undef FASTLZ_STRICT_ALIGN
70#elif defined(_X86_) /* MinGW */
71#undef FASTLZ_STRICT_ALIGN
72#elif defined(__I86__) /* Digital Mars */
73#undef FASTLZ_STRICT_ALIGN
74#endif
75#endif
76
77/*
78 * FIXME: use preprocessor magic to set this on different platforms!
79 */
80typedef unsigned char flzuint8;
81typedef unsigned short flzuint16;
82typedef unsigned int flzuint32;
83
84/* prototypes */
85int fastlz_compress(const void* input, int length, void* output);
86int fastlz_compress_level(int level, const void* input, int length, void* output);
87int fastlz_decompress(const void* input, int length, void* output, int maxout);
88
89#define MAX_COPY 32
90#define MAX_LEN 264 /* 256 + 8 */
91#define MAX_DISTANCE 8192
92
93#if !defined(FASTLZ_STRICT_ALIGN)
94#define FASTLZ_READU16(p) *((const flzuint16*)(p))
95#else
96#define FASTLZ_READU16(p) ((p)[0] | (p)[1]<<8)
97#endif
98
99#define HASH_LOG 13
100#define HASH_SIZE (1<< HASH_LOG)
101#define HASH_MASK (HASH_SIZE-1)
102#define HASH_FUNCTION(v,p) { v = FASTLZ_READU16(p); v ^= FASTLZ_READU16(p+1)^(v>>(16-HASH_LOG));v &= HASH_MASK; }
103
104#undef FASTLZ_LEVEL
105#define FASTLZ_LEVEL 1
106
107#undef FASTLZ_COMPRESSOR
108#undef FASTLZ_DECOMPRESSOR
109#define FASTLZ_COMPRESSOR fastlz1_compress
110#define FASTLZ_DECOMPRESSOR fastlz1_decompress
111static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output);
112static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout);
113#include "fastlz.c"
114
115#undef FASTLZ_LEVEL
116#define FASTLZ_LEVEL 2
117
118#undef MAX_DISTANCE
119#define MAX_DISTANCE 8191
120#define MAX_FARDISTANCE (65535+MAX_DISTANCE-1)
121
122#undef FASTLZ_COMPRESSOR
123#undef FASTLZ_DECOMPRESSOR
124#define FASTLZ_COMPRESSOR fastlz2_compress
125#define FASTLZ_DECOMPRESSOR fastlz2_decompress
126static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output);
127static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout);
128#include "fastlz.c"
129
130int fastlz_compress(const void* input, int length, void* output)
131{
132 /* for short block, choose fastlz1 */
133 if(length < 65536)
134 return fastlz1_compress(input, length, output);
135
136 /* else... */
137 return fastlz2_compress(input, length, output);
138}
139
140int fastlz_decompress(const void* input, int length, void* output, int maxout)
141{
142 /* magic identifier for compression level */
143 int level = ((*(const flzuint8*)input) >> 5) + 1;
144
145 if(level == 1)
146 return fastlz1_decompress(input, length, output, maxout);
147 if(level == 2)
148 return fastlz2_decompress(input, length, output, maxout);
149
150 /* unknown level, trigger error */
151 return 0;
152}
153
154int fastlz_compress_level(int level, const void* input, int length, void* output)
155{
156 if(level == 1)
157 return fastlz1_compress(input, length, output);
158 if(level == 2)
159 return fastlz2_compress(input, length, output);
160
161 return 0;
162}
163
164#else /* !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) */
165
166static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output)
167{
168 const flzuint8* ip = (const flzuint8*) input;
169 const flzuint8* ip_bound = ip + length - 2;
170 const flzuint8* ip_limit = ip + length - 12;
171 flzuint8* op = (flzuint8*) output;
172
173 const flzuint8* htab[HASH_SIZE];
174 const flzuint8** hslot;
175 flzuint32 hval;
176
177 flzuint32 copy;
178
179 /* sanity check */
180 if(FASTLZ_UNEXPECT_CONDITIONAL(length < 4))
181 {
182 if(length)
183 {
184 /* create literal copy only */
185 *op++ = length-1;
186 ip_bound++;
187 while(ip <= ip_bound)
188 *op++ = *ip++;
189 return length+1;
190 }
191 else
192 return 0;
193 }
194
195 /* initializes hash table */
196 for (hslot = htab; hslot < htab + HASH_SIZE; hslot++)
197 *hslot = ip;
198
199 /* we start with literal copy */
200 copy = 2;
201 *op++ = MAX_COPY-1;
202 *op++ = *ip++;
203 *op++ = *ip++;
204
205 /* main loop */
206 while(FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit))
207 {
208 const flzuint8* ref;
209 flzuint32 distance;
210
211 /* minimum match length */
212 flzuint32 len = 3;
213
214 /* comparison starting-point */
215 const flzuint8* anchor = ip;
216
217 /* check for a run */
218#if FASTLZ_LEVEL==2
219 if(ip[0] == ip[-1] && FASTLZ_READU16(ip-1)==FASTLZ_READU16(ip+1))
220 {
221 distance = 1;
222 #ifndef __rtems__
223 /*
224 * ip is assigned a value here, but is immediately assigned another
225 * value when it goes to match (line 269). The value that was initially
226 * assigned is not used, and this results in a Coverity issue. See CID
227 * 1399751
228 */
229 ip += 3;
230 #endif
231 ref = anchor - 1 + 3;
232 goto match;
233 }
234#endif
235
236 /* find potential match */
237 HASH_FUNCTION(hval,ip);
238 hslot = htab + hval;
239 ref = htab[hval];
240
241 /* calculate distance to the match */
242 distance = anchor - ref;
243
244 /* update hash table */
245 *hslot = anchor;
246
247 /* is this a match? check the first 3 bytes */
248 if(distance==0 ||
249#if FASTLZ_LEVEL==1
250 (distance >= MAX_DISTANCE) ||
251#else
252 (distance >= MAX_FARDISTANCE) ||
253#endif
254 *ref++ != *ip++ || *ref++!=*ip++ || *ref++!=*ip++)
255 goto literal;
256
257#if FASTLZ_LEVEL==2
258 /* far, needs at least 5-byte match */
259 if(distance >= MAX_DISTANCE)
260 {
261 if(*ip++ != *ref++ || *ip++!= *ref++)
262 goto literal;
263 len += 2;
264 }
265
266 match:
267#endif
268
269 /* last matched byte */
270 ip = anchor + len;
271
272 /* distance is biased */
273 distance--;
274
275 if(!distance)
276 {
277 /* zero distance means a run */
278 flzuint8 x = ip[-1];
279 while(ip < ip_bound)
280 if(*ref++ != x) break; else ip++;
281 }
282 else
283 for(;;)
284 {
285 /* safe because the outer check against ip limit */
286 if(*ref++ != *ip++) break;
287 if(*ref++ != *ip++) break;
288 if(*ref++ != *ip++) break;
289 if(*ref++ != *ip++) break;
290 if(*ref++ != *ip++) break;
291 if(*ref++ != *ip++) break;
292 if(*ref++ != *ip++) break;
293 if(*ref++ != *ip++) break;
294 while(ip < ip_bound)
295 if(*ref++ != *ip++) break;
296 break;
297 }
298
299 /* if we have copied something, adjust the copy count */
300 if(copy)
301 /* copy is biased, '0' means 1 byte copy */
302 *(op-copy-1) = copy-1;
303 else
304 /* back, to overwrite the copy count */
305 op--;
306
307 /* reset literal counter */
308 copy = 0;
309
310 /* length is biased, '1' means a match of 3 bytes */
311 ip -= 3;
312 len = ip - anchor;
313
314 /* encode the match */
315#if FASTLZ_LEVEL==2
316 if(distance < MAX_DISTANCE)
317 {
318 if(len < 7)
319 {
320 *op++ = (len << 5) + (distance >> 8);
321 *op++ = (distance & 255);
322 }
323 else
324 {
325 *op++ = (7 << 5) + (distance >> 8);
326 for(len-=7; len >= 255; len-= 255)
327 *op++ = 255;
328 *op++ = len;
329 *op++ = (distance & 255);
330 }
331 }
332 else
333 {
334 /* far away, but not yet in the another galaxy... */
335 if(len < 7)
336 {
337 distance -= MAX_DISTANCE;
338 *op++ = (len << 5) + 31;
339 *op++ = 255;
340 *op++ = distance >> 8;
341 *op++ = distance & 255;
342 }
343 else
344 {
345 distance -= MAX_DISTANCE;
346 *op++ = (7 << 5) + 31;
347 for(len-=7; len >= 255; len-= 255)
348 *op++ = 255;
349 *op++ = len;
350 *op++ = 255;
351 *op++ = distance >> 8;
352 *op++ = distance & 255;
353 }
354 }
355#else
356
357 if(FASTLZ_UNEXPECT_CONDITIONAL(len > MAX_LEN-2))
358 while(len > MAX_LEN-2)
359 {
360 *op++ = (7 << 5) + (distance >> 8);
361 *op++ = MAX_LEN - 2 - 7 -2;
362 *op++ = (distance & 255);
363 len -= MAX_LEN-2;
364 }
365
366 if(len < 7)
367 {
368 *op++ = (len << 5) + (distance >> 8);
369 *op++ = (distance & 255);
370 }
371 else
372 {
373 *op++ = (7 << 5) + (distance >> 8);
374 *op++ = len - 7;
375 *op++ = (distance & 255);
376 }
377#endif
378
379 /* update the hash at match boundary */
380 HASH_FUNCTION(hval,ip);
381 htab[hval] = ip++;
382 HASH_FUNCTION(hval,ip);
383 htab[hval] = ip++;
384
385 /* assuming literal copy */
386 *op++ = MAX_COPY-1;
387
388 continue;
389
390 literal:
391 *op++ = *anchor++;
392 ip = anchor;
393 copy++;
394 if(FASTLZ_UNEXPECT_CONDITIONAL(copy == MAX_COPY))
395 {
396 copy = 0;
397 *op++ = MAX_COPY-1;
398 }
399 }
400
401 /* left-over as literal copy */
402 ip_bound++;
403 while(ip <= ip_bound)
404 {
405 *op++ = *ip++;
406 copy++;
407 if(copy == MAX_COPY)
408 {
409 copy = 0;
410 *op++ = MAX_COPY-1;
411 }
412 }
413
414 /* if we have copied something, adjust the copy length */
415 if(copy)
416 *(op-copy-1) = copy-1;
417 else
418 op--;
419
420#if FASTLZ_LEVEL==2
421 /* marker for fastlz2 */
422 *(flzuint8*)output |= (1 << 5);
423#endif
424
425 return op - (flzuint8*)output;
426}
427
428static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout)
429{
430 const flzuint8* ip = (const flzuint8*) input;
431 const flzuint8* ip_limit = ip + length;
432 flzuint8* op = (flzuint8*) output;
433 flzuint8* op_limit = op + maxout;
434 flzuint32 ctrl = (*ip++) & 31;
435 int loop = 1;
436
437 do
438 {
439 const flzuint8* ref = op;
440 flzuint32 len = ctrl >> 5;
441 flzuint32 ofs = (ctrl & 31) << 8;
442
443 if(ctrl >= 32)
444 {
445#if FASTLZ_LEVEL==2
446 flzuint8 code;
447#endif
448 len--;
449 ref -= ofs;
450 if (len == 7-1)
451#if FASTLZ_LEVEL==1
452 len += *ip++;
453 ref -= *ip++;
454#else
455 do
456 {
457 code = *ip++;
458 len += code;
459 } while (code==255);
460 code = *ip++;
461 ref -= code;
462
463 /* match from 16-bit distance */
464 if(FASTLZ_UNEXPECT_CONDITIONAL(code==255))
465 if(FASTLZ_EXPECT_CONDITIONAL(ofs==(31 << 8)))
466 {
467 ofs = (*ip++) << 8;
468 ofs += *ip++;
469 ref = op - ofs - MAX_DISTANCE;
470 }
471#endif
472
473#ifdef FASTLZ_SAFE
474 if (FASTLZ_UNEXPECT_CONDITIONAL(op + len + 3 > op_limit))
475 return 0;
476
477 if (FASTLZ_UNEXPECT_CONDITIONAL(ref-1 < (flzuint8 *)output))
478 return 0;
479#endif
480
481 if(FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit))
482 ctrl = *ip++;
483 else
484 loop = 0;
485
486 if(ref == op)
487 {
488 /* optimize copy for a run */
489 flzuint8 b = ref[-1];
490 *op++ = b;
491 *op++ = b;
492 *op++ = b;
493 for(; len; --len)
494 *op++ = b;
495 }
496 else
497 {
498#if !defined(FASTLZ_STRICT_ALIGN)
499 const flzuint16* p;
500 flzuint16* q;
501#endif
502 /* copy from reference */
503 ref--;
504 *op++ = *ref++;
505 *op++ = *ref++;
506 *op++ = *ref++;
507
508#if !defined(FASTLZ_STRICT_ALIGN)
509 /* copy a byte, so that now it's word aligned */
510 if(len & 1)
511 {
512 *op++ = *ref++;
513 len--;
514 }
515
516 /* copy 16-bit at once */
517 q = (flzuint16*) op;
518 op += len;
519 p = (const flzuint16*) ref;
520 for(len>>=1; len > 4; len-=4)
521 {
522 *q++ = *p++;
523 *q++ = *p++;
524 *q++ = *p++;
525 *q++ = *p++;
526 }
527 for(; len; --len)
528 *q++ = *p++;
529#else
530 for(; len; --len)
531 *op++ = *ref++;
532#endif
533 }
534 }
535 else
536 {
537 ctrl++;
538#ifdef FASTLZ_SAFE
539 if (FASTLZ_UNEXPECT_CONDITIONAL(op + ctrl > op_limit))
540 return 0;
541 if (FASTLZ_UNEXPECT_CONDITIONAL(ip + ctrl > ip_limit))
542 return 0;
543#endif
544
545 *op++ = *ip++;
546 for(--ctrl; ctrl; ctrl--)
547 *op++ = *ip++;
548
549 loop = FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit);
550 if(loop)
551 ctrl = *ip++;
552 }
553 }
554 while(FASTLZ_EXPECT_CONDITIONAL(loop));
555
556 return op - (flzuint8*)output;
557}
558
559#endif /* !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) */
Definition inftrees.h:24
unsigned p
Definition tte.h:17