comparison toys/pending/compress.c @ 1206:1b36fd8dd5cf draft

Add crc code: zcat now works.
author Rob Landley <rob@landley.net>
date Sat, 22 Feb 2014 08:01:11 -0600
parents a0f08d393def
children 6ca31490f581
comparison
equal deleted inserted replaced
1205:bd745ae2b115 1206:1b36fd8dd5cf
47 // base offset and extra bits tables (length and distance) 47 // base offset and extra bits tables (length and distance)
48 char lenbits[29], distbits[30]; 48 char lenbits[29], distbits[30];
49 unsigned short lenbase[29], distbase[30]; 49 unsigned short lenbase[29], distbase[30];
50 void *fixdisthuff, *fixlithuff; 50 void *fixdisthuff, *fixlithuff;
51 51
52 unsigned (*crcfunc)(char *data, int len); 52 void (*crcfunc)(char *data, int len);
53 unsigned crc; 53 unsigned crc, len;
54 54
55 char *outbuf; 55 char *outbuf;
56 unsigned outlen; 56 unsigned outlen;
57 int outfd; 57 int outfd;
58 ) 58 )
100 100
101 return (bb->buf[bufpos]>>(bb->bitpos++&7))&1; 101 return (bb->buf[bufpos]>>(bb->bitpos++&7))&1;
102 } 102 }
103 103
104 // Fetch the next X bits from the bitbuf, little endian 104 // Fetch the next X bits from the bitbuf, little endian
105 int bitbuf_get(struct bitbuf *bb, int bits) 105 unsigned bitbuf_get(struct bitbuf *bb, int bits)
106 { 106 {
107 int result = 0, offset = 0; 107 int result = 0, offset = 0;
108 108
109 while (bits) { 109 while (bits) {
110 int click = bb->bitpos >> 3, blow, blen; 110 int click = bb->bitpos >> 3, blow, blen;
129 { 129 {
130 TT.outbuf[TT.outlen++ & 32767] = sym; 130 TT.outbuf[TT.outlen++ & 32767] = sym;
131 131
132 if (!(TT.outlen & 32767)) { 132 if (!(TT.outlen & 32767)) {
133 xwrite(TT.outfd, TT.outbuf, 32768); 133 xwrite(TT.outfd, TT.outbuf, 32768);
134 TT.crcfunc(0, 32768); 134 if (TT.crcfunc) TT.crcfunc(0, 32768);
135 } 135 }
136 } 136 }
137 137
138 // Huffman coding uses bits to traverse a binary tree to a leaf node, 138 // Huffman coding uses bits to traverse a binary tree to a leaf node,
139 // By placing frequently occurring symbols at shorter paths, frequently 139 // By placing frequently occurring symbols at shorter paths, frequently
260 i += len; 260 i += len;
261 } 261 }
262 } 262 }
263 if (i > litlen+distlen) error_exit("bad tree"); 263 if (i > litlen+distlen) error_exit("bad tree");
264 264
265 len2huff(lithuff = ((struct huff *)toybuf)+2, bits, litlen); 265 len2huff(lithuff = h2, bits, litlen);
266 len2huff(disthuff = ((struct huff *)toybuf)+3, bits+litlen, distlen); 266 len2huff(disthuff = ((struct huff *)toybuf)+2, bits+litlen, distlen);
267 267
268 // Static huffman codes 268 // Static huffman codes
269 } else { 269 } else {
270 lithuff = TT.fixlithuff; 270 lithuff = TT.fixlithuff;
271 disthuff = TT.fixdisthuff; 271 disthuff = TT.fixdisthuff;
296 } 296 }
297 297
298 // Was that the last block? 298 // Was that the last block?
299 if (final) break; 299 if (final) break;
300 } 300 }
301 if (TT.outlen & 32767) xwrite(TT.outfd, TT.outbuf, TT.outlen & 32767); 301
302 if (TT.outlen & 32767) {
303 xwrite(TT.outfd, TT.outbuf, TT.outlen & 32767);
304 if (TT.crcfunc) TT.crcfunc(0, TT.outlen & 32767);
305 }
302 } 306 }
303 307
304 static void init_deflate(void) 308 static void init_deflate(void)
305 { 309 {
306 int i, n = 1; 310 int i, n = 1;
329 TT.distbits[i] = n; 333 TT.distbits[i] = n;
330 } 334 }
331 335
332 // Init fixed huffman tables 336 // Init fixed huffman tables
333 for (i=0; i<288; i++) toybuf[i] = 8 + (i>143) - ((i>255)<<1) + (i>279); 337 for (i=0; i<288; i++) toybuf[i] = 8 + (i>143) - ((i>255)<<1) + (i>279);
334 len2huff(TT.fixlithuff = ((struct huff *)toybuf)+4, toybuf, 288); 338 len2huff(TT.fixlithuff = ((struct huff *)toybuf)+3, toybuf, 288);
335 memset(toybuf, 5, 30); 339 memset(toybuf, 5, 30);
336 len2huff(TT.fixdisthuff = ((struct huff *)toybuf)+5, toybuf, 30); 340 len2huff(TT.fixdisthuff = ((struct huff *)toybuf)+4, toybuf, 30);
337 } 341 }
338 342
339 // Return true/false whether we consumed a gzip header. 343 // Return true/false whether we consumed a gzip header.
340 static int is_gzip(struct bitbuf *bb) 344 static int is_gzip(struct bitbuf *bb)
341 { 345 {
353 if (flags & 2) bitbuf_skip(bb, 16); 357 if (flags & 2) bitbuf_skip(bb, 16);
354 358
355 return 1; 359 return 1;
356 } 360 }
357 361
362 void gzip_crc(char *data, int len)
363 {
364 int i;
365 unsigned crc, *crc_table = (unsigned *)(toybuf+sizeof(toybuf)-1024);
366
367 crc = TT.crc;
368 for (i=0; i<len; i++) crc = crc_table[(crc^TT.outbuf[i])&0xff] ^ (crc>>8);
369 TT.crc = crc;
370 TT.len += len;
371 }
372
358 static void do_zcat(int fd, char *name) 373 static void do_zcat(int fd, char *name)
359 { 374 {
360 struct bitbuf *bb = bitbuf_init(fd, sizeof(toybuf)); 375 struct bitbuf *bb = bitbuf_init(fd, sizeof(toybuf));
361 376
362 if (!is_gzip(bb)) error_exit("not gzip"); 377 if (!is_gzip(bb)) error_exit("not gzip");
363 TT.outfd = 1; 378 TT.outfd = 1;
379
380 // Use last 1k of toybuf for little endian crc table
381 crc_init((unsigned *)(toybuf+sizeof(toybuf)-1024), 1);
382 TT.crcfunc = gzip_crc;
383
364 inflate(bb); 384 inflate(bb);
365 385
366 // tail: crc32, len32 386 // tail: crc32, len32
367 387
388 bitbuf_skip(bb, (8-bb->bitpos)&7);
389 if (~TT.crc != bitbuf_get(bb, 32) || TT.len != bitbuf_get(bb, 32))
390 error_exit("bad crc");
368 free(bb); 391 free(bb);
369 } 392 }
370 393
371 // Parse many different kinds of command line argument: 394 // Parse many different kinds of command line argument:
372 395