00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #if !defined(FASTLZ__COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR)
00028
00029
00030
00031
00032
00033 #define FASTLZ_SAFE
00034
00035
00036
00037
00038 #if defined(__GNUC__) && (__GNUC__ > 2)
00039 #define FASTLZ_EXPECT_CONDITIONAL(c) (__builtin_expect((c), 1))
00040 #define FASTLZ_UNEXPECT_CONDITIONAL(c) (__builtin_expect((c), 0))
00041 #else
00042 #define FASTLZ_EXPECT_CONDITIONAL(c) (c)
00043 #define FASTLZ_UNEXPECT_CONDITIONAL(c) (c)
00044 #endif
00045
00046
00047
00048
00049 #if defined(__GNUC__) || defined(__DMC__) || defined(__POCC__) || defined(__WATCOMC__) || defined(__SUNPRO_C)
00050 #define FASTLZ_INLINE inline
00051 #elif defined(__BORLANDC__) || defined(_MSC_VER) || defined(__LCC__)
00052 #define FASTLZ_INLINE __inline
00053 #else
00054 #define FASTLZ_INLINE
00055 #endif
00056
00057
00058
00059
00060 #if !defined(FASTLZ_STRICT_ALIGN)
00061 #define FASTLZ_STRICT_ALIGN
00062 #if defined(__i386__) || defined(__386)
00063 #undef FASTLZ_STRICT_ALIGN
00064 #elif defined(__i486__) || defined(__i586__) || defined(__i686__)
00065 #undef FASTLZ_STRICT_ALIGN
00066 #elif defined(_M_IX86)
00067 #undef FASTLZ_STRICT_ALIGN
00068 #elif defined(__386)
00069 #undef FASTLZ_STRICT_ALIGN
00070 #elif defined(_X86_)
00071 #undef FASTLZ_STRICT_ALIGN
00072 #elif defined(__I86__)
00073 #undef FASTLZ_STRICT_ALIGN
00074 #endif
00075 #endif
00076
00077
00078
00079
00080 typedef unsigned char flzuint8;
00081 typedef unsigned short flzuint16;
00082 typedef unsigned int flzuint32;
00083
00084
00085 int fastlz_compress(const void* input, int length, void* output);
00086 int fastlz_compress_level(int level, const void* input, int length, void* output);
00087 int fastlz_decompress(const void* input, int length, void* output, int maxout);
00088
00089 #define MAX_COPY 32
00090 #define MAX_LEN 264
00091 #define MAX_DISTANCE 8192
00092
00093 #if !defined(FASTLZ_STRICT_ALIGN)
00094 #define FASTLZ_READU16(p) *((const flzuint16*)(p))
00095 #else
00096 #define FASTLZ_READU16(p) ((p)[0] | (p)[1]<<8)
00097 #endif
00098
00099 #define HASH_LOG 13
00100 #define HASH_SIZE (1<< HASH_LOG)
00101 #define HASH_MASK (HASH_SIZE-1)
00102 #define HASH_FUNCTION(v,p) { v = FASTLZ_READU16(p); v ^= FASTLZ_READU16(p+1)^(v>>(16-HASH_LOG));v &= HASH_MASK; }
00103
00104 #undef FASTLZ_LEVEL
00105 #define FASTLZ_LEVEL 1
00106
00107 #undef FASTLZ_COMPRESSOR
00108 #undef FASTLZ_DECOMPRESSOR
00109 #define FASTLZ_COMPRESSOR fastlz1_compress
00110 #define FASTLZ_DECOMPRESSOR fastlz1_decompress
00111 static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output);
00112 static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout);
00113 #include "fastlz.c"
00114
00115 #undef FASTLZ_LEVEL
00116 #define FASTLZ_LEVEL 2
00117
00118 #undef MAX_DISTANCE
00119 #define MAX_DISTANCE 8191
00120 #define MAX_FARDISTANCE (65535+MAX_DISTANCE-1)
00121
00122 #undef FASTLZ_COMPRESSOR
00123 #undef FASTLZ_DECOMPRESSOR
00124 #define FASTLZ_COMPRESSOR fastlz2_compress
00125 #define FASTLZ_DECOMPRESSOR fastlz2_decompress
00126 static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output);
00127 static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout);
00128 #include "fastlz.c"
00129
00130 int fastlz_compress(const void* input, int length, void* output)
00131 {
00132
00133 if(length < 65536)
00134 return fastlz1_compress(input, length, output);
00135
00136
00137 return fastlz2_compress(input, length, output);
00138 }
00139
00140 int fastlz_decompress(const void* input, int length, void* output, int maxout)
00141 {
00142
00143 int level = ((*(const flzuint8*)input) >> 5) + 1;
00144
00145 if(level == 1)
00146 return fastlz1_decompress(input, length, output, maxout);
00147 if(level == 2)
00148 return fastlz2_decompress(input, length, output, maxout);
00149
00150
00151 return 0;
00152 }
00153
00154 int fastlz_compress_level(int level, const void* input, int length, void* output)
00155 {
00156 if(level == 1)
00157 return fastlz1_compress(input, length, output);
00158 if(level == 2)
00159 return fastlz2_compress(input, length, output);
00160
00161 return 0;
00162 }
00163
00164 #else
00165
00166 static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output)
00167 {
00168 const flzuint8* ip = (const flzuint8*) input;
00169 const flzuint8* ip_bound = ip + length - 2;
00170 const flzuint8* ip_limit = ip + length - 12;
00171 flzuint8* op = (flzuint8*) output;
00172
00173 const flzuint8* htab[HASH_SIZE];
00174 const flzuint8** hslot;
00175 flzuint32 hval;
00176
00177 flzuint32 copy;
00178
00179
00180 if(FASTLZ_UNEXPECT_CONDITIONAL(length < 4))
00181 {
00182 if(length)
00183 {
00184
00185 *op++ = length-1;
00186 ip_bound++;
00187 while(ip <= ip_bound)
00188 *op++ = *ip++;
00189 return length+1;
00190 }
00191 else
00192 return 0;
00193 }
00194
00195
00196 for (hslot = htab; hslot < htab + HASH_SIZE; hslot++)
00197 *hslot = ip;
00198
00199
00200 copy = 2;
00201 *op++ = MAX_COPY-1;
00202 *op++ = *ip++;
00203 *op++ = *ip++;
00204
00205
00206 while(FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit))
00207 {
00208 const flzuint8* ref;
00209 flzuint32 distance;
00210
00211
00212 flzuint32 len = 3;
00213
00214
00215 const flzuint8* anchor = ip;
00216
00217
00218 #if FASTLZ_LEVEL==2
00219 if(ip[0] == ip[-1] && FASTLZ_READU16(ip-1)==FASTLZ_READU16(ip+1))
00220 {
00221 distance = 1;
00222 ref = anchor - 1 + 3;
00223 goto match;
00224 }
00225 #endif
00226
00227
00228 HASH_FUNCTION(hval,ip);
00229 hslot = htab + hval;
00230 ref = htab[hval];
00231
00232
00233 distance = anchor - ref;
00234
00235
00236 *hslot = anchor;
00237
00238
00239 if(distance==0 ||
00240 #if FASTLZ_LEVEL==1
00241 (distance >= MAX_DISTANCE) ||
00242 #else
00243 (distance >= MAX_FARDISTANCE) ||
00244 #endif
00245 *ref++ != *ip++ || *ref++!=*ip++ || *ref++!=*ip++)
00246 goto literal;
00247
00248 #if FASTLZ_LEVEL==2
00249
00250 if(distance >= MAX_DISTANCE)
00251 {
00252 if(*ip++ != *ref++ || *ip++!= *ref++)
00253 goto literal;
00254 len += 2;
00255 }
00256
00257 match:
00258 #endif
00259
00260
00261 ip = anchor + len;
00262
00263
00264 distance--;
00265
00266 if(!distance)
00267 {
00268
00269 flzuint8 x = ip[-1];
00270 while(ip < ip_bound)
00271 if(*ref++ != x) break; else ip++;
00272 }
00273 else
00274 for(;;)
00275 {
00276
00277 if(*ref++ != *ip++) break;
00278 if(*ref++ != *ip++) break;
00279 if(*ref++ != *ip++) break;
00280 if(*ref++ != *ip++) break;
00281 if(*ref++ != *ip++) break;
00282 if(*ref++ != *ip++) break;
00283 if(*ref++ != *ip++) break;
00284 if(*ref++ != *ip++) break;
00285 while(ip < ip_bound)
00286 if(*ref++ != *ip++) break;
00287 break;
00288 }
00289
00290
00291 if(copy)
00292
00293 *(op-copy-1) = copy-1;
00294 else
00295
00296 op--;
00297
00298
00299 copy = 0;
00300
00301
00302 ip -= 3;
00303 len = ip - anchor;
00304
00305
00306 #if FASTLZ_LEVEL==2
00307 if(distance < MAX_DISTANCE)
00308 {
00309 if(len < 7)
00310 {
00311 *op++ = (len << 5) + (distance >> 8);
00312 *op++ = (distance & 255);
00313 }
00314 else
00315 {
00316 *op++ = (7 << 5) + (distance >> 8);
00317 for(len-=7; len >= 255; len-= 255)
00318 *op++ = 255;
00319 *op++ = len;
00320 *op++ = (distance & 255);
00321 }
00322 }
00323 else
00324 {
00325
00326 if(len < 7)
00327 {
00328 distance -= MAX_DISTANCE;
00329 *op++ = (len << 5) + 31;
00330 *op++ = 255;
00331 *op++ = distance >> 8;
00332 *op++ = distance & 255;
00333 }
00334 else
00335 {
00336 distance -= MAX_DISTANCE;
00337 *op++ = (7 << 5) + 31;
00338 for(len-=7; len >= 255; len-= 255)
00339 *op++ = 255;
00340 *op++ = len;
00341 *op++ = 255;
00342 *op++ = distance >> 8;
00343 *op++ = distance & 255;
00344 }
00345 }
00346 #else
00347
00348 if(FASTLZ_UNEXPECT_CONDITIONAL(len > MAX_LEN-2))
00349 while(len > MAX_LEN-2)
00350 {
00351 *op++ = (7 << 5) + (distance >> 8);
00352 *op++ = MAX_LEN - 2 - 7 -2;
00353 *op++ = (distance & 255);
00354 len -= MAX_LEN-2;
00355 }
00356
00357 if(len < 7)
00358 {
00359 *op++ = (len << 5) + (distance >> 8);
00360 *op++ = (distance & 255);
00361 }
00362 else
00363 {
00364 *op++ = (7 << 5) + (distance >> 8);
00365 *op++ = len - 7;
00366 *op++ = (distance & 255);
00367 }
00368 #endif
00369
00370
00371 HASH_FUNCTION(hval,ip);
00372 htab[hval] = ip++;
00373 HASH_FUNCTION(hval,ip);
00374 htab[hval] = ip++;
00375
00376
00377 *op++ = MAX_COPY-1;
00378
00379 continue;
00380
00381 literal:
00382 *op++ = *anchor++;
00383 ip = anchor;
00384 copy++;
00385 if(FASTLZ_UNEXPECT_CONDITIONAL(copy == MAX_COPY))
00386 {
00387 copy = 0;
00388 *op++ = MAX_COPY-1;
00389 }
00390 }
00391
00392
00393 ip_bound++;
00394 while(ip <= ip_bound)
00395 {
00396 *op++ = *ip++;
00397 copy++;
00398 if(copy == MAX_COPY)
00399 {
00400 copy = 0;
00401 *op++ = MAX_COPY-1;
00402 }
00403 }
00404
00405
00406 if(copy)
00407 *(op-copy-1) = copy-1;
00408 else
00409 op--;
00410
00411 #if FASTLZ_LEVEL==2
00412
00413 *(flzuint8*)output |= (1 << 5);
00414 #endif
00415
00416 return op - (flzuint8*)output;
00417 }
00418
00419 static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout)
00420 {
00421 const flzuint8* ip = (const flzuint8*) input;
00422 const flzuint8* ip_limit = ip + length;
00423 flzuint8* op = (flzuint8*) output;
00424 flzuint8* op_limit = op + maxout;
00425 flzuint32 ctrl = (*ip++) & 31;
00426 int loop = 1;
00427
00428 do
00429 {
00430 const flzuint8* ref = op;
00431 flzuint32 len = ctrl >> 5;
00432 flzuint32 ofs = (ctrl & 31) << 8;
00433
00434 if(ctrl >= 32)
00435 {
00436 #if FASTLZ_LEVEL==2
00437 flzuint8 code;
00438 #endif
00439 len--;
00440 ref -= ofs;
00441 if (len == 7-1)
00442 #if FASTLZ_LEVEL==1
00443 len += *ip++;
00444 ref -= *ip++;
00445 #else
00446 do
00447 {
00448 code = *ip++;
00449 len += code;
00450 } while (code==255);
00451 code = *ip++;
00452 ref -= code;
00453
00454
00455 if(FASTLZ_UNEXPECT_CONDITIONAL(code==255))
00456 if(FASTLZ_EXPECT_CONDITIONAL(ofs==(31 << 8)))
00457 {
00458 ofs = (*ip++) << 8;
00459 ofs += *ip++;
00460 ref = op - ofs - MAX_DISTANCE;
00461 }
00462 #endif
00463
00464 #ifdef FASTLZ_SAFE
00465 if (FASTLZ_UNEXPECT_CONDITIONAL(op + len + 3 > op_limit))
00466 return 0;
00467
00468 if (FASTLZ_UNEXPECT_CONDITIONAL(ref-1 < (flzuint8 *)output))
00469 return 0;
00470 #endif
00471
00472 if(FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit))
00473 ctrl = *ip++;
00474 else
00475 loop = 0;
00476
00477 if(ref == op)
00478 {
00479
00480 flzuint8 b = ref[-1];
00481 *op++ = b;
00482 *op++ = b;
00483 *op++ = b;
00484 for(; len; --len)
00485 *op++ = b;
00486 }
00487 else
00488 {
00489 #if !defined(FASTLZ_STRICT_ALIGN)
00490 const flzuint16* p;
00491 flzuint16* q;
00492 #endif
00493
00494 ref--;
00495 *op++ = *ref++;
00496 *op++ = *ref++;
00497 *op++ = *ref++;
00498
00499 #if !defined(FASTLZ_STRICT_ALIGN)
00500
00501 if(len & 1)
00502 {
00503 *op++ = *ref++;
00504 len--;
00505 }
00506
00507
00508 q = (flzuint16*) op;
00509 op += len;
00510 p = (const flzuint16*) ref;
00511 for(len>>=1; len > 4; len-=4)
00512 {
00513 *q++ = *p++;
00514 *q++ = *p++;
00515 *q++ = *p++;
00516 *q++ = *p++;
00517 }
00518 for(; len; --len)
00519 *q++ = *p++;
00520 #else
00521 for(; len; --len)
00522 *op++ = *ref++;
00523 #endif
00524 }
00525 }
00526 else
00527 {
00528 ctrl++;
00529 #ifdef FASTLZ_SAFE
00530 if (FASTLZ_UNEXPECT_CONDITIONAL(op + ctrl > op_limit))
00531 return 0;
00532 if (FASTLZ_UNEXPECT_CONDITIONAL(ip + ctrl > ip_limit))
00533 return 0;
00534 #endif
00535
00536 *op++ = *ip++;
00537 for(--ctrl; ctrl; ctrl--)
00538 *op++ = *ip++;
00539
00540 loop = FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit);
00541 if(loop)
00542 ctrl = *ip++;
00543 }
00544 }
00545 while(FASTLZ_EXPECT_CONDITIONAL(loop));
00546
00547 return op - (flzuint8*)output;
00548 }
00549
00550 #endif