1 a0d146ed 2005-07-12 devnull #include "stdinc.h"
2 a0d146ed 2005-07-12 devnull #include "whack.h"
6 a0d146ed 2005-07-12 devnull DMaxFastLen = 7,
7 a0d146ed 2005-07-12 devnull DBigLenCode = 0x3c, /* minimum code for large lenth encoding */
8 a0d146ed 2005-07-12 devnull DBigLenBits = 6,
9 a0d146ed 2005-07-12 devnull DBigLenBase = 1 /* starting items to encode for big lens */
12 a0d146ed 2005-07-12 devnull static uchar lenval[1 << (DBigLenBits - 1)] =
14 a0d146ed 2005-07-12 devnull 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
15 a0d146ed 2005-07-12 devnull 3, 3, 3, 3, 3, 3, 3, 3,
16 a0d146ed 2005-07-12 devnull 4, 4, 4, 4,
23 a0d146ed 2005-07-12 devnull static uchar lenbits[] =
26 a0d146ed 2005-07-12 devnull 2, 3, 5, 5,
29 a0d146ed 2005-07-12 devnull static uchar offbits[16] =
31 a0d146ed 2005-07-12 devnull 5, 5, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 12, 13
34 a0d146ed 2005-07-12 devnull static ushort offbase[16] =
37 a0d146ed 2005-07-12 devnull 0x40, 0x60,
38 a0d146ed 2005-07-12 devnull 0x80, 0xc0,
39 a0d146ed 2005-07-12 devnull 0x100, 0x180,
40 a0d146ed 2005-07-12 devnull 0x200, 0x300,
41 a0d146ed 2005-07-12 devnull 0x400, 0x600,
42 a0d146ed 2005-07-12 devnull 0x800, 0xc00,
48 a0d146ed 2005-07-12 devnull unwhackinit(Unwhack *uw)
50 a0d146ed 2005-07-12 devnull uw->err[0] = '\0';
54 a0d146ed 2005-07-12 devnull unwhack(Unwhack *uw, uchar *dst, int ndst, uchar *src, int nsrc)
56 a0d146ed 2005-07-12 devnull uchar *s, *d, *dmax, *smax, lit;
57 a0d146ed 2005-07-12 devnull ulong uwbits, lithist;
58 a0d146ed 2005-07-12 devnull int i, off, len, bits, use, code, uwnbits, overbits;
61 a0d146ed 2005-07-12 devnull dmax = d + ndst;
63 a0d146ed 2005-07-12 devnull smax = src + nsrc;
64 a0d146ed 2005-07-12 devnull uwnbits = 0;
65 a0d146ed 2005-07-12 devnull uwbits = 0;
66 a0d146ed 2005-07-12 devnull overbits = 0;
67 a0d146ed 2005-07-12 devnull lithist = ~0;
68 a0d146ed 2005-07-12 devnull while(src < smax || uwnbits - overbits >= MinDecode){
69 a0d146ed 2005-07-12 devnull while(uwnbits <= 24){
70 a0d146ed 2005-07-12 devnull uwbits <<= 8;
71 a0d146ed 2005-07-12 devnull if(src < smax)
72 a0d146ed 2005-07-12 devnull uwbits |= *src++;
74 a0d146ed 2005-07-12 devnull overbits += 8;
75 a0d146ed 2005-07-12 devnull uwnbits += 8;
79 a0d146ed 2005-07-12 devnull * literal
81 a0d146ed 2005-07-12 devnull len = lenval[(uwbits >> (uwnbits - 5)) & 0x1f];
82 a0d146ed 2005-07-12 devnull if(len == 0){
83 a0d146ed 2005-07-12 devnull if(lithist & 0xf){
84 a0d146ed 2005-07-12 devnull uwnbits -= 9;
85 a0d146ed 2005-07-12 devnull lit = (uwbits >> uwnbits) & 0xff;
86 a0d146ed 2005-07-12 devnull lit &= 255;
88 a0d146ed 2005-07-12 devnull uwnbits -= 8;
89 a0d146ed 2005-07-12 devnull lit = (uwbits >> uwnbits) & 0x7f;
90 a0d146ed 2005-07-12 devnull if(lit < 32){
91 a0d146ed 2005-07-12 devnull if(lit < 24){
92 a0d146ed 2005-07-12 devnull uwnbits -= 2;
93 a0d146ed 2005-07-12 devnull lit = (lit << 2) | ((uwbits >> uwnbits) & 3);
95 a0d146ed 2005-07-12 devnull uwnbits -= 3;
96 a0d146ed 2005-07-12 devnull lit = (lit << 3) | ((uwbits >> uwnbits) & 7);
98 a0d146ed 2005-07-12 devnull lit = (lit - 64) & 0xff;
101 a0d146ed 2005-07-12 devnull if(d >= dmax){
102 a0d146ed 2005-07-12 devnull snprint(uw->err, WhackErrLen, "too much output");
103 a0d146ed 2005-07-12 devnull return -1;
105 a0d146ed 2005-07-12 devnull *d++ = lit;
106 a0d146ed 2005-07-12 devnull lithist = (lithist << 1) | (lit < 32) | (lit > 127);
107 a0d146ed 2005-07-12 devnull continue;
111 a0d146ed 2005-07-12 devnull * length
113 a0d146ed 2005-07-12 devnull if(len < 255)
114 a0d146ed 2005-07-12 devnull uwnbits -= lenbits[len];
116 a0d146ed 2005-07-12 devnull uwnbits -= DBigLenBits;
117 a0d146ed 2005-07-12 devnull code = ((uwbits >> uwnbits) & ((1 << DBigLenBits) - 1)) - DBigLenCode;
118 a0d146ed 2005-07-12 devnull len = DMaxFastLen;
119 a0d146ed 2005-07-12 devnull use = DBigLenBase;
120 a0d146ed 2005-07-12 devnull bits = (DBigLenBits & 1) ^ 1;
121 a0d146ed 2005-07-12 devnull while(code >= use){
122 a0d146ed 2005-07-12 devnull len += use;
123 a0d146ed 2005-07-12 devnull code -= use;
124 a0d146ed 2005-07-12 devnull code <<= 1;
125 a0d146ed 2005-07-12 devnull uwnbits--;
126 a0d146ed 2005-07-12 devnull if(uwnbits < 0){
127 a0d146ed 2005-07-12 devnull snprint(uw->err, WhackErrLen, "len out of range");
128 a0d146ed 2005-07-12 devnull return -1;
130 a0d146ed 2005-07-12 devnull code |= (uwbits >> uwnbits) & 1;
131 a0d146ed 2005-07-12 devnull use <<= bits;
132 a0d146ed 2005-07-12 devnull bits ^= 1;
134 a0d146ed 2005-07-12 devnull len += code;
136 a0d146ed 2005-07-12 devnull while(uwnbits <= 24){
137 a0d146ed 2005-07-12 devnull uwbits <<= 8;
138 a0d146ed 2005-07-12 devnull if(src < smax)
139 a0d146ed 2005-07-12 devnull uwbits |= *src++;
141 a0d146ed 2005-07-12 devnull overbits += 8;
142 a0d146ed 2005-07-12 devnull uwnbits += 8;
147 a0d146ed 2005-07-12 devnull * offset
149 a0d146ed 2005-07-12 devnull uwnbits -= 4;
150 a0d146ed 2005-07-12 devnull bits = (uwbits >> uwnbits) & 0xf;
151 a0d146ed 2005-07-12 devnull off = offbase[bits];
152 a0d146ed 2005-07-12 devnull bits = offbits[bits];
154 a0d146ed 2005-07-12 devnull uwnbits -= bits;
155 a0d146ed 2005-07-12 devnull off |= (uwbits >> uwnbits) & ((1 << bits) - 1);
158 a0d146ed 2005-07-12 devnull if(off > d - dst){
159 a0d146ed 2005-07-12 devnull snprint(uw->err, WhackErrLen, "offset out of range: off=%d d=%ld len=%d nbits=%d", off, d - dst, len, uwnbits);
160 a0d146ed 2005-07-12 devnull return -1;
162 a0d146ed 2005-07-12 devnull if(d + len > dmax){
163 a0d146ed 2005-07-12 devnull snprint(uw->err, WhackErrLen, "len out of range");
164 a0d146ed 2005-07-12 devnull return -1;
166 a0d146ed 2005-07-12 devnull s = d - off;
167 a0d146ed 2005-07-12 devnull for(i = 0; i < len; i++)
168 a0d146ed 2005-07-12 devnull d[i] = s[i];
169 a0d146ed 2005-07-12 devnull d += len;
171 a0d146ed 2005-07-12 devnull if(uwnbits < overbits){
172 a0d146ed 2005-07-12 devnull snprint(uw->err, WhackErrLen, "compressed data overrun");
173 a0d146ed 2005-07-12 devnull return -1;
176 a0d146ed 2005-07-12 devnull len = d - dst;
178 a0d146ed 2005-07-12 devnull return len;