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/libsa/mkext.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  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
    3  *
    4  * @APPLE_LICENSE_HEADER_START@
    5  * 
    6  * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
    7  * 
    8  * This file contains Original Code and/or Modifications of Original Code
    9  * as defined in and that are subject to the Apple Public Source License
   10  * Version 2.0 (the 'License'). You may not use this file except in
   11  * compliance with the License. Please obtain a copy of the License at
   12  * http://www.opensource.apple.com/apsl/ and read it before using this
   13  * file.
   14  * 
   15  * The Original Code and all software distributed under the License are
   16  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   17  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   18  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   19  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   20  * Please see the License for the specific language governing rights and
   21  * limitations under the License.
   22  * 
   23  * @APPLE_LICENSE_HEADER_END@
   24  */
   25 #include <string.h>
   26 #if KERNEL
   27 #include <libsa/mkext.h>
   28 #include <libsa/stdlib.h>
   29 #else
   30 #include <Kernel/libsa/mkext.h>
   31 #include <stdlib.h>
   32 #endif /* KERNEL */
   33 
   34 
   35 __private_extern__ u_int32_t
   36 adler32(u_int8_t *buffer, int32_t length)
   37 {
   38     int32_t cnt;
   39     u_int32_t  result, lowHalf, highHalf;
   40     
   41     lowHalf = 1;
   42     highHalf = 0;
   43     
   44     for (cnt = 0; cnt < length; cnt++) {
   45         if ((cnt % 5000) == 0) {
   46             lowHalf  %= 65521L;
   47             highHalf %= 65521L;
   48         }
   49         
   50         lowHalf += buffer[cnt];
   51         highHalf += lowHalf;
   52     }
   53     
   54     lowHalf  %= 65521L;
   55     highHalf %= 65521L;
   56     
   57     result = (highHalf << 16) | lowHalf;
   58     
   59     return result;
   60 }
   61 
   62 /**************************************************************
   63  LZSS.C -- A Data Compression Program
   64 ***************************************************************
   65     4/6/1989 Haruhiko Okumura
   66     Use, distribute, and modify this program freely.
   67     Please send me your improved versions.
   68         PC-VAN      SCIENCE
   69         NIFTY-Serve PAF01022
   70         CompuServe  74050,1022
   71 
   72 **************************************************************/
   73 
   74 #define N         4096  /* size of ring buffer - must be power of 2 */
   75 #define F         18    /* upper limit for match_length */
   76 #define THRESHOLD 2     /* encode string into position and length
   77                            if match_length is greater than this */
   78 #define NIL       N     /* index for root of binary search trees */
   79 
   80 struct encode_state {
   81     /*
   82      * left & right children & parent. These constitute binary search trees.
   83      */
   84     int lchild[N + 1], rchild[N + 257], parent[N + 1];
   85 
   86     /* ring buffer of size N, with extra F-1 bytes to aid string comparison */
   87     u_int8_t text_buf[N + F - 1];
   88 
   89     /*
   90      * match_length of longest match.
   91      * These are set by the insert_node() procedure.
   92      */
   93     int match_position, match_length;
   94 };
   95 
   96 
   97 __private_extern__ int
   98 decompress_lzss(u_int8_t *dst, u_int8_t *src, u_int32_t srclen)
   99 {
  100     /* ring buffer of size N, with extra F-1 bytes to aid string comparison */
  101     u_int8_t text_buf[N + F - 1];
  102     u_int8_t *dststart = dst;
  103     u_int8_t *srcend = src + srclen;
  104     int  i, j, k, r, c;
  105     unsigned int flags;
  106     
  107     dst = dststart;
  108     srcend = src + srclen;
  109     for (i = 0; i < N - F; i++)
  110         text_buf[i] = ' ';
  111     r = N - F;
  112     flags = 0;
  113     for ( ; ; ) {
  114         if (((flags >>= 1) & 0x100) == 0) {
  115             if (src < srcend) c = *src++; else break;
  116             flags = c | 0xFF00;  /* uses higher byte cleverly */
  117         }   /* to count eight */
  118         if (flags & 1) {
  119             if (src < srcend) c = *src++; else break;
  120             *dst++ = c;
  121             text_buf[r++] = c;
  122             r &= (N - 1);
  123         } else {
  124             if (src < srcend) i = *src++; else break;
  125             if (src < srcend) j = *src++; else break;
  126             i |= ((j & 0xF0) << 4);
  127             j  =  (j & 0x0F) + THRESHOLD;
  128             for (k = 0; k <= j; k++) {
  129                 c = text_buf[(i + k) & (N - 1)];
  130                 *dst++ = c;
  131                 text_buf[r++] = c;
  132                 r &= (N - 1);
  133             }
  134         }
  135     }
  136     
  137     return dst - dststart;
  138 }
  139 
  140 #if !KERNEL
  141 
  142 /*
  143  * initialize state, mostly the trees
  144  *
  145  * For i = 0 to N - 1, rchild[i] and lchild[i] will be the right and left 
  146  * children of node i.  These nodes need not be initialized.  Also, parent[i] 
  147  * is the parent of node i.  These are initialized to NIL (= N), which stands 
  148  * for 'not used.'  For i = 0 to 255, rchild[N + i + 1] is the root of the 
  149  * tree for strings that begin with character i.  These are initialized to NIL. 
  150  * Note there are 256 trees. */
  151 static void init_state(struct encode_state *sp)
  152 {
  153     int  i;
  154 
  155     bzero(sp, sizeof(*sp));
  156 
  157     for (i = 0; i < N - F; i++)
  158         sp->text_buf[i] = ' ';
  159     for (i = N + 1; i <= N + 256; i++)
  160         sp->rchild[i] = NIL;
  161     for (i = 0; i < N; i++)
  162         sp->parent[i] = NIL;
  163 }
  164 
  165 /*
  166  * Inserts string of length F, text_buf[r..r+F-1], into one of the trees
  167  * (text_buf[r]'th tree) and returns the longest-match position and length
  168  * via the global variables match_position and match_length.
  169  * If match_length = F, then removes the old node in favor of the new one,
  170  * because the old one will be deleted sooner. Note r plays double role,
  171  * as tree node and position in buffer.
  172  */
  173 static void insert_node(struct encode_state *sp, int r)
  174 {
  175     int  i, p, cmp;
  176     u_int8_t  *key;
  177 
  178     cmp = 1;
  179     key = &sp->text_buf[r];
  180     p = N + 1 + key[0];
  181     sp->rchild[r] = sp->lchild[r] = NIL;
  182     sp->match_length = 0;
  183     for ( ; ; ) {
  184         if (cmp >= 0) {
  185             if (sp->rchild[p] != NIL)
  186                 p = sp->rchild[p];
  187             else {
  188                 sp->rchild[p] = r; 
  189                 sp->parent[r] = p;
  190                 return;
  191             }
  192         } else {
  193             if (sp->lchild[p] != NIL)
  194                 p = sp->lchild[p];
  195             else {
  196                 sp->lchild[p] = r;
  197                 sp->parent[r] = p;
  198                 return;
  199             }
  200         }
  201         for (i = 1; i < F; i++) {
  202             if ((cmp = key[i] - sp->text_buf[p + i]) != 0)
  203                 break;
  204         }
  205         if (i > sp->match_length) {
  206             sp->match_position = p;
  207             if ((sp->match_length = i) >= F)
  208                 break;
  209         }
  210     }
  211     sp->parent[r] = sp->parent[p];
  212     sp->lchild[r] = sp->lchild[p];
  213     sp->rchild[r] = sp->rchild[p];
  214     sp->parent[sp->lchild[p]] = r;
  215     sp->parent[sp->rchild[p]] = r;
  216     if (sp->rchild[sp->parent[p]] == p)
  217         sp->rchild[sp->parent[p]] = r;
  218     else
  219         sp->lchild[sp->parent[p]] = r;
  220     sp->parent[p] = NIL;  /* remove p */
  221 }
  222 
  223 /* deletes node p from tree */
  224 static void delete_node(struct encode_state *sp, int p)
  225 {
  226     int  q;
  227     
  228     if (sp->parent[p] == NIL)
  229         return;  /* not in tree */
  230     if (sp->rchild[p] == NIL)
  231         q = sp->lchild[p];
  232     else if (sp->lchild[p] == NIL)
  233         q = sp->rchild[p];
  234     else {
  235         q = sp->lchild[p];
  236         if (sp->rchild[q] != NIL) {
  237             do {
  238                 q = sp->rchild[q];
  239             } while (sp->rchild[q] != NIL);
  240             sp->rchild[sp->parent[q]] = sp->lchild[q];
  241             sp->parent[sp->lchild[q]] = sp->parent[q];
  242             sp->lchild[q] = sp->lchild[p];
  243             sp->parent[sp->lchild[p]] = q;
  244         }
  245         sp->rchild[q] = sp->rchild[p];
  246         sp->parent[sp->rchild[p]] = q;
  247     }
  248     sp->parent[q] = sp->parent[p];
  249     if (sp->rchild[sp->parent[p]] == p)
  250         sp->rchild[sp->parent[p]] = q;
  251     else
  252         sp->lchild[sp->parent[p]] = q;
  253     sp->parent[p] = NIL;
  254 }
  255 
  256 __private_extern__ u_int8_t *
  257 compress_lzss(u_int8_t *dst, u_int32_t dstlen, u_int8_t *src, u_int32_t srcLen)
  258 {
  259     /* Encoding state, mostly tree but some current match stuff */
  260     struct encode_state *sp;
  261 
  262     int  i, c, len, r, s, last_match_length, code_buf_ptr;
  263     u_int8_t code_buf[17], mask;
  264     u_int8_t *srcend = src + srcLen;
  265     u_int8_t *dstend = dst + dstlen;
  266 
  267     /* initialize trees */
  268     sp = (struct encode_state *) malloc(sizeof(*sp));
  269     init_state(sp);
  270 
  271     /*
  272      * code_buf[1..16] saves eight units of code, and code_buf[0] works
  273      * as eight flags, "1" representing that the unit is an unencoded
  274      * letter (1 byte), "" a position-and-length pair (2 bytes).
  275      * Thus, eight units require at most 16 bytes of code.
  276      */
  277     code_buf[0] = 0;
  278     code_buf_ptr = mask = 1;
  279 
  280     /* Clear the buffer with any character that will appear often. */
  281     s = 0;  r = N - F;
  282 
  283     /* Read F bytes into the last F bytes of the buffer */
  284     for (len = 0; len < F && src < srcend; len++)
  285         sp->text_buf[r + len] = *src++;  
  286     if (!len)
  287         return (void *) 0;  /* text of size zero */
  288 
  289     /*
  290      * Insert the F strings, each of which begins with one or more
  291      * 'space' characters.  Note the order in which these strings are
  292      * inserted.  This way, degenerate trees will be less likely to occur.
  293      */
  294     for (i = 1; i <= F; i++)
  295         insert_node(sp, r - i); 
  296 
  297     /*
  298      * Finally, insert the whole string just read.
  299      * The global variables match_length and match_position are set.
  300      */
  301     insert_node(sp, r);
  302     do {
  303         /* match_length may be spuriously long near the end of text. */
  304         if (sp->match_length > len)
  305             sp->match_length = len;
  306         if (sp->match_length <= THRESHOLD) {
  307             sp->match_length = 1;  /* Not long enough match.  Send one byte. */
  308             code_buf[0] |= mask;  /* 'send one byte' flag */
  309             code_buf[code_buf_ptr++] = sp->text_buf[r];  /* Send uncoded. */
  310         } else {
  311             /* Send position and length pair. Note match_length > THRESHOLD. */
  312             code_buf[code_buf_ptr++] = (u_int8_t) sp->match_position;
  313             code_buf[code_buf_ptr++] = (u_int8_t)
  314                 ( ((sp->match_position >> 4) & 0xF0)
  315                 |  (sp->match_length - (THRESHOLD + 1)) );
  316         }
  317         if ((mask <<= 1) == 0) {  /* Shift mask left one bit. */
  318                 /* Send at most 8 units of code together */
  319             for (i = 0; i < code_buf_ptr; i++)
  320                 if (dst < dstend)
  321                     *dst++ = code_buf[i]; 
  322                 else
  323                     return (void *) 0;
  324             code_buf[0] = 0;
  325             code_buf_ptr = mask = 1;
  326         }
  327         last_match_length = sp->match_length;
  328         for (i = 0; i < last_match_length && src < srcend; i++) {
  329             delete_node(sp, s);    /* Delete old strings and */
  330             c = *src++;
  331             sp->text_buf[s] = c;    /* read new bytes */
  332 
  333             /*
  334              * If the position is near the end of buffer, extend the buffer
  335              * to make string comparison easier.
  336              */
  337             if (s < F - 1)
  338                 sp->text_buf[s + N] = c;
  339 
  340             /* Since this is a ring buffer, increment the position modulo N. */
  341             s = (s + 1) & (N - 1);
  342             r = (r + 1) & (N - 1);
  343 
  344             /* Register the string in text_buf[r..r+F-1] */
  345             insert_node(sp, r); 
  346         }
  347         while (i++ < last_match_length) {
  348         delete_node(sp, s);
  349 
  350             /* After the end of text, no need to read, */
  351             s = (s + 1) & (N - 1); 
  352             r = (r + 1) & (N - 1);
  353             /* but buffer may not be empty. */
  354             if (--len)
  355                 insert_node(sp, r);
  356         }
  357     } while (len > 0);   /* until length of string to be processed is zero */
  358 
  359     if (code_buf_ptr > 1) {    /* Send remaining code. */
  360         for (i = 0; i < code_buf_ptr; i++)
  361             if (dst < dstend)
  362                 *dst++ = code_buf[i]; 
  363             else
  364                 return (void *) 0;
  365     }
  366 
  367     return dst;
  368 }
  369 
  370 #endif /* !KERNEL */
  371 

Cache object: a4cc46e97b81d8cc81ba5aa50e1e0c39


[ 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.