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