Mercurial > hg > toybox
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 |