FreeBSD/Linux Kernel Cross Reference
sys/port/unthwack.c
1 #include "u.h"
2 #include "lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6
7 #include "thwack.h"
8
9 enum
10 {
11 DMaxFastLen = 7,
12 DBigLenCode = 0x3c, /* minimum code for large lenth encoding */
13 DBigLenBits = 6,
14 DBigLenBase = 1 /* starting items to encode for big lens */
15 };
16
17 static uchar lenval[1 << (DBigLenBits - 1)] =
18 {
19 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
20 3, 3, 3, 3, 3, 3, 3, 3,
21 4, 4, 4, 4,
22 5,
23 6,
24 255,
25 255
26 };
27
28 static uchar lenbits[] =
29 {
30 0, 0, 0,
31 2, 3, 5, 5,
32 };
33
34 static uchar offbits[16] =
35 {
36 5, 5, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 12, 13
37 };
38
39 static ushort offbase[16] =
40 {
41 0, 0x20,
42 0x40, 0x60,
43 0x80, 0xc0,
44 0x100, 0x180,
45 0x200, 0x300,
46 0x400, 0x600,
47 0x800, 0xc00,
48 0x1000,
49 0x2000
50 };
51
52 void
53 unthwackinit(Unthwack *ut)
54 {
55 int i;
56
57 memset(ut, 0, sizeof *ut);
58 for(i = 0; i < DWinBlocks; i++)
59 ut->blocks[i].data = ut->data[i];
60 }
61
62 ulong
63 unthwackstate(Unthwack *ut, uchar *mask)
64 {
65 ulong bseq, seq;
66 int slot, m;
67
68 seq = ~0UL;
69 m = 0;
70 slot = ut->slot;
71 for(;;){
72 slot--;
73 if(slot < 0)
74 slot += DWinBlocks;
75 if(slot == ut->slot)
76 break;
77 if(ut->blocks[slot].maxoff == 0)
78 continue;
79 bseq = ut->blocks[slot].seq;
80 if(seq == ~0UL)
81 seq = bseq;
82 else if(seq - bseq > MaxSeqMask)
83 break;
84 else
85 m |= 1 << (seq - bseq - 1);
86 }
87 *mask = m;
88 return seq;
89 }
90
91 /*
92 * insert this block in it's correct sequence number order.
93 * replace the oldest block, which is always pointed to by ut->slot.
94 * the encoder doesn't use a history at wraparound,
95 * so don't worry about that case.
96 */
97 static int
98 unthwackinsert(Unthwack *ut, int len, ulong seq)
99 {
100 uchar *d;
101 int slot, tslot;
102
103 tslot = ut->slot;
104 for(;;){
105 slot = tslot - 1;
106 if(slot < 0)
107 slot += DWinBlocks;
108 if(ut->blocks[slot].seq <= seq || ut->blocks[slot].maxoff == 0)
109 break;
110 d = ut->blocks[tslot].data;
111 ut->blocks[tslot] = ut->blocks[slot];
112 ut->blocks[slot].data = d;
113 tslot = slot;
114 }
115 ut->blocks[tslot].seq = seq;
116 ut->blocks[tslot].maxoff = len;
117
118 ut->slot++;
119 if(ut->slot >= DWinBlocks)
120 ut->slot = 0;
121
122 ut->blocks[ut->slot].seq = ~0UL;
123 ut->blocks[ut->slot].maxoff = 0;
124
125 return tslot;
126 }
127
128 int
129 unthwack(Unthwack *ut, uchar *dst, int ndst, uchar *src, int nsrc, ulong seq)
130 {
131 UnthwBlock blocks[CompBlocks], *b, *eblocks;
132 uchar *s, *d, *dmax, *smax, lit;
133 ulong cmask, cseq, bseq, utbits;
134 int i, off, len, bits, slot, use, code, utnbits, overbits, lithist;
135
136 if(nsrc < 4 || nsrc > ThwMaxBlock)
137 return -1;
138
139 slot = ut->slot;
140 b = blocks;
141 *b = ut->blocks[slot];
142 d = b->data;
143 dmax = d + ndst;
144
145 /*
146 * set up the history blocks
147 */
148 cseq = seq - src[0];
149 cmask = src[1];
150 b++;
151 while(cseq != seq && b < blocks + CompBlocks){
152 slot--;
153 if(slot < 0)
154 slot += DWinBlocks;
155 if(slot == ut->slot)
156 break;
157 bseq = ut->blocks[slot].seq;
158 if(bseq == cseq){
159 *b = ut->blocks[slot];
160 b++;
161 if(cmask == 0){
162 cseq = seq;
163 break;
164 }
165 do{
166 bits = cmask & 1;
167 cseq--;
168 cmask >>= 1;
169 }while(!bits);
170 }
171 }
172 eblocks = b;
173 if(cseq != seq){
174 print("blocks dropped: seq=%ld cseq=%ld %d cmask=%#lx %#x\n", seq, cseq, src[0], cmask, src[1]);
175 return -2;
176 }
177
178 smax = src + nsrc;
179 src += 2;
180 utnbits = 0;
181 utbits = 0;
182 overbits = 0;
183 lithist = ~0;
184 while(src < smax || utnbits - overbits >= MinDecode){
185 while(utnbits <= 24){
186 utbits <<= 8;
187 if(src < smax)
188 utbits |= *src++;
189 else
190 overbits += 8;
191 utnbits += 8;
192 }
193
194 /*
195 * literal
196 */
197 len = lenval[(utbits >> (utnbits - 5)) & 0x1f];
198 if(len == 0){
199 if(lithist & 0xf){
200 utnbits -= 9;
201 lit = (utbits >> utnbits) & 0xff;
202 lit &= 255;
203 }else{
204 utnbits -= 8;
205 lit = (utbits >> utnbits) & 0x7f;
206 if(lit < 32){
207 if(lit < 24){
208 utnbits -= 2;
209 lit = (lit << 2) | ((utbits >> utnbits) & 3);
210 }else{
211 utnbits -= 3;
212 lit = (lit << 3) | ((utbits >> utnbits) & 7);
213 }
214 lit = (lit - 64) & 0xff;
215 }
216 }
217 if(d >= dmax)
218 return -1;
219 *d++ = lit;
220 lithist = (lithist << 1) | (lit < 32) | (lit > 127);
221 blocks->maxoff++;
222 continue;
223 }
224
225 /*
226 * length
227 */
228 if(len < 255)
229 utnbits -= lenbits[len];
230 else{
231 utnbits -= DBigLenBits;
232 code = ((utbits >> utnbits) & ((1 << DBigLenBits) - 1)) - DBigLenCode;
233 len = DMaxFastLen;
234 use = DBigLenBase;
235 bits = (DBigLenBits & 1) ^ 1;
236 while(code >= use){
237 len += use;
238 code -= use;
239 code <<= 1;
240 utnbits--;
241 if(utnbits < 0)
242 return -1;
243 code |= (utbits >> utnbits) & 1;
244 use <<= bits;
245 bits ^= 1;
246 }
247 len += code;
248
249 while(utnbits <= 24){
250 utbits <<= 8;
251 if(src < smax)
252 utbits |= *src++;
253 else
254 overbits += 8;
255 utnbits += 8;
256 }
257 }
258
259 /*
260 * offset
261 */
262 utnbits -= 4;
263 bits = (utbits >> utnbits) & 0xf;
264 off = offbase[bits];
265 bits = offbits[bits];
266
267 utnbits -= bits;
268 off |= (utbits >> utnbits) & ((1 << bits) - 1);
269 off++;
270
271 b = blocks;
272 while(off > b->maxoff){
273 off -= b->maxoff;
274 b++;
275 if(b >= eblocks)
276 return -1;
277 }
278 if(d + len > dmax
279 || b != blocks && len > off)
280 return -1;
281 s = b->data + b->maxoff - off;
282 blocks->maxoff += len;
283
284 for(i = 0; i < len; i++)
285 d[i] = s[i];
286 d += len;
287 }
288 if(utnbits < overbits)
289 return -1;
290
291 len = d - blocks->data;
292 memmove(dst, blocks->data, len);
293
294 unthwackinsert(ut, len, seq);
295
296 return len;
297 }
Cache object: cbfa7b94de3476216ef3b209a3201d08
|