The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/cxgbe/cudbg/fastlz.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 0aaa1f58e9e8148e8e2a7b69ef471e06


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.