]>
git.saurik.com Git - apple/xnu.git/blob - libkern/mkext.c
   2  * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved. 
   4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 
   6  * This file contains Original Code and/or Modifications of Original Code 
   7  * as defined in and that are subject to the Apple Public Source License 
   8  * Version 2.0 (the 'License'). You may not use this file except in 
   9  * compliance with the License. The rights granted to you under the License 
  10  * may not be used to create, or enable the creation or redistribution of, 
  11  * unlawful or unlicensed copies of an Apple operating system, or to 
  12  * circumvent, violate, or enable the circumvention or violation of, any 
  13  * terms of an Apple operating system software license agreement. 
  15  * Please obtain a copy of the License at 
  16  * http://www.opensource.apple.com/apsl/ and read it before using this file. 
  18  * The Original Code and all software distributed under the License are 
  19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  23  * Please see the License for the specific language governing rights and 
  24  * limitations under the License. 
  26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 
  28 #include <stdint.h> // For uintptr_t. 
  30 #include <libkern/mkext.h> 
  33 #define BASE 65521L /* largest prime smaller than 65536 */ 
  34 #define NMAX 5552  // the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 
  36 #define DO1(buf,i)  {s1 += buf[i]; s2 += s1;} 
  37 #define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1); 
  38 #define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2); 
  39 #define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4); 
  40 #define DO16(buf)   DO8(buf,0); DO8(buf,8); 
  43 mkext_adler32(uint8_t *buf
, int32_t len
) 
  45     unsigned long s1 
= 1; // adler & 0xffff; 
  46     unsigned long s2 
= 0; // (adler >> 16) & 0xffff; 
  51         k 
= len 
< NMAX 
? len 
: NMAX
; 
  65     return (s2 
<< 16) | s1
; 
  69 /************************************************************** 
  70  LZSS.C -- A Data Compression Program 
  71 *************************************************************** 
  72     4/6/1989 Haruhiko Okumura 
  73     Use, distribute, and modify this program freely. 
  74     Please send me your improved versions. 
  79 **************************************************************/ 
  81 #define N         4096  /* size of ring buffer - must be power of 2 */ 
  82 #define F         18    /* upper limit for match_length */ 
  83 #define THRESHOLD 2     /* encode string into position and length 
  84                            if match_length is greater than this */ 
  85 #define NIL       N     /* index for root of binary search trees */ 
  89      * left & right children & parent. These constitute binary search trees. 
  91     int lchild
[N 
+ 1], rchild
[N 
+ 257], parent
[N 
+ 1]; 
  93     /* ring buffer of size N, with extra F-1 bytes to aid string comparison */ 
  94     u_int8_t text_buf
[N 
+ F 
- 1]; 
  97      * match_length of longest match. 
  98      * These are set by the insert_node() procedure. 
 100     int match_position
, match_length
; 
 105 decompress_lzss(u_int8_t 
*dst
, u_int32_t dstlen
, u_int8_t 
*src
, u_int32_t srclen
) 
 107     /* ring buffer of size N, with extra F-1 bytes to aid string comparison */ 
 108     u_int8_t text_buf
[N 
+ F 
- 1]; 
 109     u_int8_t 
*dststart 
= dst
; 
 110         u_int8_t 
*dstend 
= dst 
+ dstlen
; 
 111     u_int8_t 
*srcend 
= src 
+ srclen
; 
 116     srcend 
= src 
+ srclen
; 
 117     for (i 
= 0; i 
< N 
- F
; i
++) 
 122         if (((flags 
>>= 1) & 0x100) == 0) { 
 123             if (src 
< srcend
) c 
= *src
++; else break; 
 124             flags 
= c 
| 0xFF00;  /* uses higher byte cleverly */ 
 125         }   /* to count eight */ 
 127             if (src 
< srcend
) c 
= *src
++; else break; 
 135             if (src 
< srcend
) i 
= *src
++; else break; 
 136             if (src 
< srcend
) j 
= *src
++; else break; 
 137             i 
|= ((j 
& 0xF0) << 4); 
 138             j  
=  (j 
& 0x0F) + THRESHOLD
; 
 139             for (k 
= 0; k 
<= j
; k
++) { 
 140                 c 
= text_buf
[(i 
+ k
) & (N 
- 1)]; 
 151     return dst 
- dststart
; 
 157  * initialize state, mostly the trees 
 159  * For i = 0 to N - 1, rchild[i] and lchild[i] will be the right and left  
 160  * children of node i.  These nodes need not be initialized.  Also, parent[i]  
 161  * is the parent of node i.  These are initialized to NIL (= N), which stands  
 162  * for 'not used.'  For i = 0 to 255, rchild[N + i + 1] is the root of the  
 163  * tree for strings that begin with character i.  These are initialized to NIL.  
 164  * Note there are 256 trees. */ 
 165 static void init_state(struct encode_state 
*sp
) 
 169     bzero(sp
, sizeof(*sp
)); 
 171     for (i 
= 0; i 
< N 
- F
; i
++) 
 172         sp
->text_buf
[i
] = ' '; 
 173     for (i 
= N 
+ 1; i 
<= N 
+ 256; i
++) 
 175     for (i 
= 0; i 
< N
; i
++) 
 180  * Inserts string of length F, text_buf[r..r+F-1], into one of the trees 
 181  * (text_buf[r]'th tree) and returns the longest-match position and length 
 182  * via the global variables match_position and match_length. 
 183  * If match_length = F, then removes the old node in favor of the new one, 
 184  * because the old one will be deleted sooner. Note r plays double role, 
 185  * as tree node and position in buffer. 
 187 static void insert_node(struct encode_state 
*sp
, int r
) 
 193     key 
= &sp
->text_buf
[r
]; 
 195     sp
->rchild
[r
] = sp
->lchild
[r
] = NIL
; 
 196     sp
->match_length 
= 0; 
 199             if (sp
->rchild
[p
] != NIL
) 
 207             if (sp
->lchild
[p
] != NIL
) 
 215         for (i 
= 1; i 
< F
; i
++) { 
 216             if ((cmp 
= key
[i
] - sp
->text_buf
[p 
+ i
]) != 0) 
 219         if (i 
> sp
->match_length
) { 
 220             sp
->match_position 
= p
; 
 221             if ((sp
->match_length 
= i
) >= F
) 
 225     sp
->parent
[r
] = sp
->parent
[p
]; 
 226     sp
->lchild
[r
] = sp
->lchild
[p
]; 
 227     sp
->rchild
[r
] = sp
->rchild
[p
]; 
 228     sp
->parent
[sp
->lchild
[p
]] = r
; 
 229     sp
->parent
[sp
->rchild
[p
]] = r
; 
 230     if (sp
->rchild
[sp
->parent
[p
]] == p
) 
 231         sp
->rchild
[sp
->parent
[p
]] = r
; 
 233         sp
->lchild
[sp
->parent
[p
]] = r
; 
 234     sp
->parent
[p
] = NIL
;  /* remove p */ 
 237 /* deletes node p from tree */ 
 238 static void delete_node(struct encode_state 
*sp
, int p
) 
 242     if (sp
->parent
[p
] == NIL
) 
 243         return;  /* not in tree */ 
 244     if (sp
->rchild
[p
] == NIL
) 
 246     else if (sp
->lchild
[p
] == NIL
) 
 250         if (sp
->rchild
[q
] != NIL
) { 
 253             } while (sp
->rchild
[q
] != NIL
); 
 254             sp
->rchild
[sp
->parent
[q
]] = sp
->lchild
[q
]; 
 255             sp
->parent
[sp
->lchild
[q
]] = sp
->parent
[q
]; 
 256             sp
->lchild
[q
] = sp
->lchild
[p
]; 
 257             sp
->parent
[sp
->lchild
[p
]] = q
; 
 259         sp
->rchild
[q
] = sp
->rchild
[p
]; 
 260         sp
->parent
[sp
->rchild
[p
]] = q
; 
 262     sp
->parent
[q
] = sp
->parent
[p
]; 
 263     if (sp
->rchild
[sp
->parent
[p
]] == p
) 
 264         sp
->rchild
[sp
->parent
[p
]] = q
; 
 266         sp
->lchild
[sp
->parent
[p
]] = q
;