9 typedef struct Huff Huff;
14 BigLenCode = 0x1f4, /* minimum code for large lenth encoding */
16 BigLenBase = 4 /* starting items to encode for big lens */
36 short bits; /* length of the code */
37 ulong encode; /* the code */
40 static Huff lentab[MaxFastLen] =
44 {5, 0x1c}, /* 11100 */
45 {5, 0x1d}, /* 11101 */
46 {6, 0x3c}, /* 111100 */
47 {7, 0x7a}, /* 1111010 */
48 {7, 0x7b}, /* 1111011 */
49 {8, 0xf8}, /* 11111000 */
50 {8, 0xf9}, /* 11111001 */
54 thwackinit(Thwack *tw)
58 memset(tw, 0, sizeof *tw);
59 for(i = 0; i < EWinBlocks; i++){
60 tw->blocks[i].data = tw->data[i];
61 tw->blocks[i].edata = tw->blocks[i].data;
62 tw->blocks[i].hash = tw->hash[i];
63 tw->blocks[i].acked = 0;
68 * acknowledgement for block seq & nearby preds
71 thwackack(Thwack *tw, ulong seq, ulong mask)
82 if(tw->blocks[slot].seq != seq)
85 tw->blocks[slot].acked = 1;
98 * find a string in the dictionary
101 thwmatch(ThwBlock *b, ThwBlock *eblocks, uchar **ss, uchar *esrc, ulong h)
103 int then, toff, w, ok;
107 if(esrc < s + MinMatch)
111 for(; b < eblocks; b++){
112 then = b->hash[(h ^ b->seq) & HashMask];
114 w = (ushort)(then - b->begin);
121 * don't need to check for the end because
122 * 1) s too close check above
123 * 2) entries too close not added to hash tables
126 if(s[0] != t[0] || s[1] != t[1] || s[2] != t[2])
133 for(s += 3; s < esrc; s++){
145 * knuth vol. 3 multiplicative hashing
146 * each byte x chosen according to rules
147 * 1/4 < x < 3/10, 1/3 x < < 3/7, 4/7 < x < 2/3, 7/10 < x < 3/4
148 * with reasonable spread between the bytes & their complements
150 * the 3 byte value appears to be as almost good as the 4 byte value,
151 * and might be faster on some machines
154 #define hashit(c) (((ulong)(c) * 0x6b43a9) >> (24 - HashLog))
156 #define hashit(c) ((((ulong)(c) & 0xffffff) * 0x6b43a9b5) >> (32 - HashLog))
159 * lz77 compression with single lookup in a hash table for each block
162 thwack(Thwack *tw, uchar *dst, uchar *src, int n, ulong seq, ulong stats[ThwStats])
164 ThwBlock *eblocks, *b, blocks[CompBlocks];
165 uchar *s, *ss, *sss, *esrc, *half, *twdst, *twdmax;
166 ulong cont, cseq, bseq, cmask, code, twbits;
167 int now, toff, lithist, h, len, slot, bits, use, twnbits, lits, matches, offbits, lenbits, nhist;
169 if(n > ThwMaxBlock || n < MinMatch)
176 * add source to the coding window
177 * there is always enough space
180 b = &tw->blocks[slot];
183 now = b->begin + b->maxoff;
191 * set up the history blocks
200 while(b < blocks + CompBlocks){
206 if(!tw->blocks[slot].acked)
208 bseq = tw->blocks[slot].seq;
210 if(seq - bseq >= MaxSeqStart)
213 }else if(cseq - bseq > MaxSeqMask)
216 cmask |= 1 << (cseq - bseq - 1);
217 *b = tw->blocks[slot];
222 *twdst++ = seq - cseq;
225 cont = (s[0] << 16) | (s[1] << 8) | s[2];
240 toff = thwmatch(blocks, eblocks, &sss, esrc, h);
244 for(; twnbits >= 8; twnbits -= 8){
247 *twdst++ = twbits >> (twnbits - 8);
251 lithist = (lithist << 1) | (toff < 32) | (toff > 127);
253 twbits = (twbits << 9) | toff;
255 }else if(lithist & 1){
256 toff = (toff + 64) & 0xff;
258 twbits = (twbits << 10) | toff;
261 twbits = (twbits << 11) | toff;
265 twbits = (twbits << 8) | toff;
273 * check for compression progress, bail if none achieved
276 if(4 * blocks->maxoff < 5 * lits)
281 if(s + MinMatch <= esrc){
282 blocks->hash[(h ^ blocks->seq) & HashMask] = now;
283 if(s + MinMatch < esrc)
284 cont = (cont << 8) | s[MinMatch];
291 blocks->maxoff += len;
298 if(len < MaxFastLen){
299 bits = lentab[len].bits;
300 twbits = (twbits << bits) | lentab[len].encode;
310 code = (code + use) << 1;
311 use <<= (bits & 1) ^ 1;
314 twbits = (twbits << bits) | (code + len);
318 for(; twnbits >= 8; twnbits -= 8){
321 *twdst++ = twbits >> (twnbits - 8);
329 for(bits = OffBase; toff >= (1 << bits); bits++)
331 if(bits < MaxOff+OffBase-1){
332 twbits = (twbits << 3) | (bits - OffBase);
338 twbits = (twbits << 4) | 0xe | (bits - (MaxOff+OffBase-1));
343 twbits = (twbits << bits) | toff & ((1 << bits) - 1);
346 if(s + MinMatch <= esrc){
348 blocks->hash[(h ^ blocks->seq) & HashMask] = now;
349 if(s + MinMatch < esrc)
350 cont = (cont << 8) | s[MinMatch];
358 twbits <<= 8 - (twnbits & 7);
359 twnbits += 8 - (twnbits & 7);
361 for(; twnbits >= 8; twnbits -= 8){
364 *twdst++ = twbits >> (twnbits - 8);
368 if(tw->slot >= EWinBlocks)
371 stats[StatBytes] += blocks->maxoff;
372 stats[StatLits] += lits;
373 stats[StatMatches] += matches;
374 stats[StatOffBits] += offbits;
375 stats[StatLenBits] += lenbits;
376 stats[StatDelay] = stats[StatDelay]*7/8 + dst[0];
377 stats[StatHist] = stats[StatHist]*7/8 + nhist;
378 stats[StatOutBytes] += twdst - dst;