Mercurial > hg > toybox
annotate lib/bunzip.c @ 60:23aac9d42234
Turn a memmove into a while(), reducing running time by 3.5% in my tests.
author | Rob Landley <rob@landley.net> |
---|---|
date | Wed, 17 Jan 2007 18:18:50 -0500 |
parents | e82ae73acbd7 |
children | d6ece20e13ce |
rev | line source |
---|---|
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
1 /* vi: set sw=4 ts=4: */ |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
2 /* micro-bunzip, a small, simple bzip2 decompression implementation. |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
3 |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
4 Copyright 2003, 2006 by Rob Landley (rob@landley.net). |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
5 |
54
60a7fb8ddeb4
Add a quick and dirt bzcat (stdin to stdout only for the moment) to test
Rob Landley <rob@landley.net>
parents:
46
diff
changeset
|
6 Based on a close reading (but not the actual code) of the original bzip2 |
60a7fb8ddeb4
Add a quick and dirt bzcat (stdin to stdout only for the moment) to test
Rob Landley <rob@landley.net>
parents:
46
diff
changeset
|
7 decompression code by Julian R Seward (jseward@acm.org), which also |
60a7fb8ddeb4
Add a quick and dirt bzcat (stdin to stdout only for the moment) to test
Rob Landley <rob@landley.net>
parents:
46
diff
changeset
|
8 acknowledges contributions by Mike Burrows, David Wheeler, Peter Fenwick, |
60a7fb8ddeb4
Add a quick and dirt bzcat (stdin to stdout only for the moment) to test
Rob Landley <rob@landley.net>
parents:
46
diff
changeset
|
9 Alistair Moffat, Radford Neal, Ian H. Witten, Robert Sedgewick, and |
60a7fb8ddeb4
Add a quick and dirt bzcat (stdin to stdout only for the moment) to test
Rob Landley <rob@landley.net>
parents:
46
diff
changeset
|
10 Jon L. Bentley. |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
11 */ |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
12 |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
13 #include "toys.h" |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
14 |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
15 // Constants for huffman coding |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
16 #define MAX_GROUPS 6 |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
17 #define GROUP_SIZE 50 /* 64 would have been more efficient */ |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
18 #define MAX_HUFCODE_BITS 20 /* Longest huffman code allowed */ |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
19 #define MAX_SYMBOLS 258 /* 256 literals + RUNA + RUNB */ |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
20 #define SYMBOL_RUNA 0 |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
21 #define SYMBOL_RUNB 1 |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
22 |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
23 // Other housekeeping constants |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
24 #define IOBUF_SIZE 4096 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
25 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
26 // Status return values |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
27 #define RETVAL_OK 0 |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
28 #define RETVAL_LAST_BLOCK (-1) |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
29 #define RETVAL_NOT_BZIP_DATA (-2) |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
30 #define RETVAL_UNEXPECTED_INPUT_EOF (-3) |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
31 #define RETVAL_UNEXPECTED_OUTPUT_EOF (-4) |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
32 #define RETVAL_DATA_ERROR (-5) |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
33 #define RETVAL_OUT_OF_MEMORY (-6) |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
34 #define RETVAL_OBSOLETE_INPUT (-7) |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
35 |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
36 char *bunzip_errors[]={ |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
37 NULL, |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
38 "Bad file checksum", |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
39 "Not bzip data", |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
40 "Unexpected input EOF", |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
41 "Unexpected output EOF", |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
42 "Data error", |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
43 "Out of memory", |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
44 "Obsolete (pre 0.9.5) bzip format not supported." |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
45 }; |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
46 |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
47 // This is what we know about each huffman coding group |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
48 struct group_data { |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
49 int limit[MAX_HUFCODE_BITS], base[MAX_HUFCODE_BITS], permute[MAX_SYMBOLS]; |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
50 char minLen, maxLen; |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
51 }; |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
52 |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
53 // Structure holding all the housekeeping data, including IO buffers and |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
54 // memory that persists between calls to bunzip |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
55 typedef struct { |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
56 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
57 // For I/O error handling |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
58 jmp_buf jmpbuf; |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
59 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
60 // Input stream, input buffer, input bit buffer |
46 | 61 int in_fd, inbufCount, inbufPos; |
62 char *inbuf; | |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
63 unsigned int inbufBitCount, inbufBits; |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
64 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
65 // Output buffer |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
66 char outbuf[IOBUF_SIZE]; |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
67 int outbufPos; |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
68 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
69 // The CRC values stored in the block header and calculated from the data |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
70 unsigned int crc32Table[256], headerCRC, dataCRC, totalCRC; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
71 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
72 // Intermediate buffer and its size (in bytes) |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
73 unsigned int *dbuf, dbufSize; |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
74 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
75 // State for interrupting output loop |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
76 int writePos, writeRun, writeCount, writeCurrent; |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
77 |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
78 // These things are a bit too big to go on the stack |
46 | 79 char selectors[32768]; // nSelectors=15 bits |
80 struct group_data groups[MAX_GROUPS]; // huffman coding tables | |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
81 } bunzip_data; |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
82 |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
83 // Return the next nnn bits of input. All reads from the compressed input |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
84 // are done through this function. All reads are big endian. |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
85 static unsigned int get_bits(bunzip_data *bd, char bits_wanted) |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
86 { |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
87 unsigned int bits = 0; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
88 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
89 // If we need to get more data from the byte buffer, do so. (Loop getting |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
90 // one byte at a time to enforce endianness and avoid unaligned access.) |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
91 while (bd->inbufBitCount < bits_wanted) { |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
92 |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
93 // If we need to read more data from file into byte buffer, do so |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
94 if (bd->inbufPos == bd->inbufCount) { |
40
d046f8d1401e
Trawling through the archives: a broken test, an unnecessary memset, and a
Rob Landley <rob@landley.net>
parents:
39
diff
changeset
|
95 if (0 >= (bd->inbufCount = read(bd->in_fd, bd->inbuf, IOBUF_SIZE))) |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
96 longjmp(bd->jmpbuf, RETVAL_UNEXPECTED_INPUT_EOF); |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
97 bd->inbufPos = 0; |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
98 } |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
99 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
100 // Avoid 32-bit overflow (dump bit buffer to top of output) |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
101 if (bd->inbufBitCount>=24) { |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
102 bits = bd->inbufBits&((1<<bd->inbufBitCount)-1); |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
103 bits_wanted -= bd->inbufBitCount; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
104 bits <<= bits_wanted; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
105 bd->inbufBitCount = 0; |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
106 } |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
107 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
108 // Grab next 8 bits of input from buffer. |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
109 bd->inbufBits = (bd->inbufBits<<8) | bd->inbuf[bd->inbufPos++]; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
110 bd->inbufBitCount += 8; |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
111 } |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
112 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
113 // Calculate result |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
114 bd->inbufBitCount -= bits_wanted; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
115 bits |= (bd->inbufBits>>bd->inbufBitCount) & ((1<<bits_wanted)-1); |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
116 |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
117 return bits; |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
118 } |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
119 |
56
7794562e2e64
Comment and whitespace changes.
Rob Landley <rob@landley.net>
parents:
55
diff
changeset
|
120 // Decompress a block of text to intermediate buffer |
54
60a7fb8ddeb4
Add a quick and dirt bzcat (stdin to stdout only for the moment) to test
Rob Landley <rob@landley.net>
parents:
46
diff
changeset
|
121 int read_bunzip_data(bunzip_data *bd) |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
122 { |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
123 struct group_data *hufGroup; |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
124 int dbufCount, nextSym, dbufSize, origPtr, groupCount, *base, *limit, |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
125 selector, i, j, k, t, runPos, symCount, symTotal, nSelectors, |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
126 byteCount[256]; |
46 | 127 char uc, mtfSymbol[256], symToByte[256], *selectors; |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
128 unsigned int *dbuf; |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
129 |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
130 // Read in header signature (borrowing mtfSymbol for temp space). |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
131 for (i=0; i<6; i++) mtfSymbol[i] = get_bits(bd,8); |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
132 mtfSymbol[6] = 0; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
133 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
134 // Read CRC (which is stored big endian). |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
135 bd->headerCRC = get_bits(bd,32); |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
136 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
137 // Is this the last block (with CRC for file)? |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
138 if (!strcmp(mtfSymbol, "\x17\x72\x45\x38\x50\x90")) |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
139 return RETVAL_LAST_BLOCK; |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
140 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
141 // If it's not a valid data block, barf. |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
142 if (strcmp(mtfSymbol, "\x31\x41\x59\x26\x53\x59")) |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
143 return RETVAL_NOT_BZIP_DATA; |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
144 |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
145 dbuf = bd->dbuf; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
146 dbufSize = bd->dbufSize; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
147 selectors = bd->selectors; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
148 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
149 // We can add support for blockRandomised if anybody complains. |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
150 if (get_bits(bd,1)) return RETVAL_OBSOLETE_INPUT; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
151 if ((origPtr=get_bits(bd,24)) > dbufSize) return RETVAL_DATA_ERROR; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
152 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
153 // mapping table: if some byte values are never used (encoding things |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
154 // like ascii text), the compression code removes the gaps to have fewer |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
155 // symbols to deal with, and writes a sparse bitfield indicating which |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
156 // values were present. We make a translation table to convert the symbols |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
157 // back to the corresponding bytes. |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
158 t = get_bits(bd, 16); |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
159 symTotal = 0; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
160 for (i=0; i<16; i++) { |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
161 if (t&(1<<(15-i))) { |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
162 k = get_bits(bd,16); |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
163 for (j=0;j<16;j++) |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
164 if (k&(1<<(15-j))) symToByte[symTotal++] = (16*i)+j; |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
165 } |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
166 } |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
167 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
168 // How many different huffman coding groups does this block use? |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
169 groupCount = get_bits(bd,3); |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
170 if (groupCount<2 || groupCount>MAX_GROUPS) return RETVAL_DATA_ERROR; |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
171 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
172 // nSelectors: Every GROUP_SIZE many symbols we select a new huffman coding |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
173 // group. Read in the group selector list, which is stored as MTF encoded |
56
7794562e2e64
Comment and whitespace changes.
Rob Landley <rob@landley.net>
parents:
55
diff
changeset
|
174 // bit runs. (MTF = Move To Front. Every time a symbol occurs it's moved |
7794562e2e64
Comment and whitespace changes.
Rob Landley <rob@landley.net>
parents:
55
diff
changeset
|
175 // to the front of the table, so it has a shorter encoding next time.) |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
176 if (!(nSelectors = get_bits(bd, 15))) return RETVAL_DATA_ERROR; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
177 for (i=0; i<groupCount; i++) mtfSymbol[i] = i; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
178 for (i=0; i<nSelectors; i++) { |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
179 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
180 // Get next value |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
181 for(j=0;get_bits(bd,1);j++) |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
182 if (j>=groupCount) return RETVAL_DATA_ERROR; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
183 |
56
7794562e2e64
Comment and whitespace changes.
Rob Landley <rob@landley.net>
parents:
55
diff
changeset
|
184 // Decode MTF to get the next selector, and move it to the front. |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
185 uc = mtfSymbol[j]; |
55
0bb7c679499a
Memmove is 11 bytes shorter than the unrolled loop, and Manuel Nova pointed
Rob Landley <rob@landley.net>
parents:
54
diff
changeset
|
186 memmove(mtfSymbol+1, mtfSymbol, j); |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
187 mtfSymbol[0] = selectors[i] = uc; |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
188 } |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
189 // Read the huffman coding tables for each group, which code for symTotal |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
190 // literal symbols, plus two run symbols (RUNA, RUNB) |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
191 symCount = symTotal+2; |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
192 for (j=0; j<groupCount; j++) { |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
193 unsigned char length[MAX_SYMBOLS], temp[MAX_HUFCODE_BITS+1]; |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
194 int minLen, maxLen, pp; |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
195 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
196 // Read lengths |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
197 t = get_bits(bd, 5); |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
198 for (i = 0; i < symCount; i++) { |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
199 for(;;) { |
57
034de958ee65
Fix off by one error in a test.
Rob Landley <rob@landley.net>
parents:
56
diff
changeset
|
200 // !t || t > MAX_HUFCODE_BITS in one test. |
034de958ee65
Fix off by one error in a test.
Rob Landley <rob@landley.net>
parents:
56
diff
changeset
|
201 if (MAX_HUFCODE_BITS-1 < (unsigned)t-1) |
034de958ee65
Fix off by one error in a test.
Rob Landley <rob@landley.net>
parents:
56
diff
changeset
|
202 return RETVAL_DATA_ERROR; |
55
0bb7c679499a
Memmove is 11 bytes shorter than the unrolled loop, and Manuel Nova pointed
Rob Landley <rob@landley.net>
parents:
54
diff
changeset
|
203 if(!get_bits(bd, 1)) break; // Stop yet? |
0bb7c679499a
Memmove is 11 bytes shorter than the unrolled loop, and Manuel Nova pointed
Rob Landley <rob@landley.net>
parents:
54
diff
changeset
|
204 t += (1 - 2*get_bits(bd, 1)); // bit ? t-- : t++ |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
205 } |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
206 length[i] = t; |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
207 } |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
208 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
209 // Find largest and smallest lengths in this group |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
210 minLen = maxLen = length[0]; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
211 for (i = 1; i < symCount; i++) { |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
212 if(length[i] > maxLen) maxLen = length[i]; |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
213 else if(length[i] < minLen) minLen = length[i]; |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
214 } |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
215 |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
216 /* Calculate permute[], base[], and limit[] tables from length[]. |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
217 * |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
218 * permute[] is the lookup table for converting huffman coded symbols |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
219 * into decoded symbols. base[] is the amount to subtract from the |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
220 * value of a huffman symbol of a given length when using permute[]. |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
221 * |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
222 * limit[] indicates the largest numerical value a symbol with a given |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
223 * number of bits can have. It lets us know when to stop reading. |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
224 * |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
225 * To use these, keep reading bits until value <= limit[bitcount] or |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
226 * you've read over 20 bits (error). Then the decoded symbol |
56
7794562e2e64
Comment and whitespace changes.
Rob Landley <rob@landley.net>
parents:
55
diff
changeset
|
227 * equals permute[hufcode_value - base[hufcode_bitcount]]. |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
228 */ |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
229 hufGroup = bd->groups+j; |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
230 hufGroup->minLen = minLen; |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
231 hufGroup->maxLen = maxLen; |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
232 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
233 // Note that minLen can't be smaller than 1, so we adjust the base |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
234 // and limit array pointers so we're not always wasting the first |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
235 // entry. We do this again when using them (during symbol decoding). |
56
7794562e2e64
Comment and whitespace changes.
Rob Landley <rob@landley.net>
parents:
55
diff
changeset
|
236 base = hufGroup->base-1; |
7794562e2e64
Comment and whitespace changes.
Rob Landley <rob@landley.net>
parents:
55
diff
changeset
|
237 limit = hufGroup->limit-1; |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
238 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
239 // Calculate permute[] |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
240 pp = 0; |
56
7794562e2e64
Comment and whitespace changes.
Rob Landley <rob@landley.net>
parents:
55
diff
changeset
|
241 for (i = minLen; i <= maxLen; i++) |
7794562e2e64
Comment and whitespace changes.
Rob Landley <rob@landley.net>
parents:
55
diff
changeset
|
242 for (t = 0; t < symCount; t++) |
7794562e2e64
Comment and whitespace changes.
Rob Landley <rob@landley.net>
parents:
55
diff
changeset
|
243 if (length[t] == i) hufGroup->permute[pp++] = t; |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
244 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
245 // Count cumulative symbols coded for at each bit length |
56
7794562e2e64
Comment and whitespace changes.
Rob Landley <rob@landley.net>
parents:
55
diff
changeset
|
246 for (i = minLen; i <= maxLen; i++) temp[i] = limit[i] = 0; |
7794562e2e64
Comment and whitespace changes.
Rob Landley <rob@landley.net>
parents:
55
diff
changeset
|
247 for (i = 0; i < symCount; i++) temp[length[i]]++; |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
248 |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
249 /* Calculate limit[] (the largest symbol-coding value at each bit |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
250 * length, which is (previous limit<<1)+symbols at this level), and |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
251 * base[] (number of symbols to ignore at each bit length, which is |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
252 * limit-cumulative count of symbols coded for already). */ |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
253 pp = t = 0; |
56
7794562e2e64
Comment and whitespace changes.
Rob Landley <rob@landley.net>
parents:
55
diff
changeset
|
254 for (i = minLen; i < maxLen; i++) { |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
255 pp += temp[i]; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
256 limit[i] = pp-1; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
257 pp <<= 1; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
258 base[i+1] = pp-(t+=temp[i]); |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
259 } |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
260 limit[maxLen] = pp+temp[maxLen]-1; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
261 base[minLen] = 0; |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
262 } |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
263 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
264 // We've finished reading and digesting the block header. Now read this |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
265 // block's huffman coded symbols from the file and undo the huffman coding |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
266 // and run length encoding, saving the result into dbuf[dbufCount++] = uc |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
267 |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
268 // Initialize symbol occurrence counters and symbol mtf table |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
269 memset(byteCount, 0, 256*sizeof(int)); |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
270 for(i=0; i<256; i++) mtfSymbol[i] = (unsigned char)i; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
271 |
56
7794562e2e64
Comment and whitespace changes.
Rob Landley <rob@landley.net>
parents:
55
diff
changeset
|
272 // Loop through compressed symbols. This is the first "tight inner loop" |
7794562e2e64
Comment and whitespace changes.
Rob Landley <rob@landley.net>
parents:
55
diff
changeset
|
273 // that needs to be micro-optimized for speed. (This one fills out dbuf[] |
7794562e2e64
Comment and whitespace changes.
Rob Landley <rob@landley.net>
parents:
55
diff
changeset
|
274 // linearly, staying in cache more, so isn't as limited by DRAM access.) |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
275 runPos = dbufCount = symCount = selector = 0; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
276 for (;;) { |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
277 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
278 // Determine which huffman coding group to use. |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
279 if (!(symCount--)) { |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
280 symCount = GROUP_SIZE-1; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
281 if (selector >= nSelectors) return RETVAL_DATA_ERROR; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
282 hufGroup = bd->groups+selectors[selector++]; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
283 base = hufGroup->base-1; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
284 limit = hufGroup->limit-1; |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
285 } |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
286 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
287 // Read next huffman-coded symbol |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
288 i = hufGroup->minLen; |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
289 j = get_bits(bd, i); |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
290 for (;;) { |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
291 if (i > hufGroup->maxLen) return RETVAL_DATA_ERROR; |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
292 if (j <= limit[i]) break; |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
293 i++; |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
294 |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
295 j = (j << 1) | get_bits(bd,1); |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
296 } |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
297 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
298 // Huffman decode nextSym (with bounds checking) |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
299 j-=base[i]; |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
300 if (j < 0 || j >= MAX_SYMBOLS) return RETVAL_DATA_ERROR; |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
301 nextSym = hufGroup->permute[j]; |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
302 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
303 // If this is a repeated run, loop collecting data |
58
b060142aee01
Minor optimization the compiler already does for us (according to bloatcheck),
Rob Landley <rob@landley.net>
parents:
57
diff
changeset
|
304 if ((unsigned)nextSym <= SYMBOL_RUNB) { |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
305 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
306 // If this is the start of a new run, zero out counter |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
307 if(!runPos) { |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
308 runPos = 1; |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
309 t = 0; |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
310 } |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
311 |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
312 /* Neat trick that saves 1 symbol: instead of or-ing 0 or 1 at |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
313 each bit position, add 1 or 2 instead. For example, |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
314 1011 is 1<<0 + 1<<1 + 2<<2. 1010 is 2<<0 + 2<<1 + 1<<2. |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
315 You can make any bit pattern that way using 1 less symbol than |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
316 the basic or 0/1 method (except all bits 0, which would use no |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
317 symbols, but a run of length 0 doesn't mean anything in this |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
318 context). Thus space is saved. */ |
59
e82ae73acbd7
Another application of Manuel Nova's "math instead of ifs" trick. Saves 17b.
Rob Landley <rob@landley.net>
parents:
58
diff
changeset
|
319 t += (runPos << nextSym); // +runPos if RUNA; +2*runPos if RUNB |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
320 runPos <<= 1; |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
321 continue; |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
322 } |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
323 |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
324 /* When we hit the first non-run symbol after a run, we now know |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
325 how many times to repeat the last literal, so append that many |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
326 copies to our buffer of decoded symbols (dbuf) now. (The last |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
327 literal used is the one at the head of the mtfSymbol array.) */ |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
328 if (runPos) { |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
329 runPos = 0; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
330 if (dbufCount+t >= dbufSize) return RETVAL_DATA_ERROR; |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
331 |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
332 uc = symToByte[mtfSymbol[0]]; |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
333 byteCount[uc] += t; |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
334 while (t--) dbuf[dbufCount++] = uc; |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
335 } |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
336 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
337 // Is this the terminating symbol? |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
338 if (nextSym>symTotal) break; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
339 |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
340 /* At this point, the symbol we just decoded indicates a new literal |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
341 character. Subtract one to get the position in the MTF array |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
342 at which this literal is currently to be found. (Note that the |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
343 result can't be -1 or 0, because 0 and 1 are RUNA and RUNB. |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
344 Another instance of the first symbol in the mtf array, position 0, |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
345 would have been handled as part of a run.) */ |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
346 if (dbufCount>=dbufSize) return RETVAL_DATA_ERROR; |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
347 i = nextSym - 1; |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
348 uc = mtfSymbol[i]; |
60
23aac9d42234
Turn a memmove into a while(), reducing running time by 3.5% in my tests.
Rob Landley <rob@landley.net>
parents:
59
diff
changeset
|
349 // On my laptop, unrolling this memmove() into a loop costs 11 bytes |
23aac9d42234
Turn a memmove into a while(), reducing running time by 3.5% in my tests.
Rob Landley <rob@landley.net>
parents:
59
diff
changeset
|
350 // but shaves 3.5% off the total running time. |
23aac9d42234
Turn a memmove into a while(), reducing running time by 3.5% in my tests.
Rob Landley <rob@landley.net>
parents:
59
diff
changeset
|
351 while(i--) mtfSymbol[i+1] = mtfSymbol[i]; |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
352 mtfSymbol[0] = uc; |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
353 uc = symToByte[uc]; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
354 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
355 // We have our literal byte. Save it into dbuf. |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
356 byteCount[uc]++; |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
357 dbuf[dbufCount++] = (unsigned int)uc; |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
358 } |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
359 |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
360 /* At this point, we've finished reading huffman-coded symbols and |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
361 compressed runs from the input stream. There are dbufCount many of |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
362 them in dbuf[]. Now undo the Burrows-Wheeler transform on dbuf. |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
363 See http://marknelson.us/1996/09/01/bwt/ |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
364 */ |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
365 |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
366 // Now we know what dbufCount is, do a better sanity check on origPtr. |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
367 if (origPtr<0 || origPtr>=dbufCount) return RETVAL_DATA_ERROR; |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
368 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
369 // Turn byteCount into cumulative occurrence counts of 0 to n-1. |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
370 j = 0; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
371 for (i=0;i<256;i++) { |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
372 k = j+byteCount[i]; |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
373 byteCount[i] = j; |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
374 j = k; |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
375 } |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
376 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
377 // Figure out what order dbuf would be in if we sorted it. |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
378 for (i=0; i<dbufCount; i++) { |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
379 uc = (unsigned char)(dbuf[i] & 0xff); |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
380 dbuf[byteCount[uc]] |= (i << 8); |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
381 byteCount[uc]++; |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
382 } |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
383 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
384 // blockRandomised support would go here. |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
385 |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
386 // Using i as position, j as previous character, t as current character, |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
387 // and uc as run count. |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
388 bd->dataCRC = 0xffffffffL; |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
389 |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
390 /* Decode first byte by hand to initialize "previous" byte. Note that it |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
391 doesn't get output, and if the first three characters are identical |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
392 it doesn't qualify as a run (hence uc=255, which will either wrap |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
393 to 1 or get reset). */ |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
394 if (dbufCount) { |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
395 bd->writePos = dbuf[origPtr]; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
396 bd->writeCurrent = (unsigned char)(bd->writePos&0xff); |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
397 bd->writePos >>= 8; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
398 bd->writeRun = -1; |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
399 } |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
400 bd->writeCount = dbufCount; |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
401 |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
402 return RETVAL_OK; |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
403 } |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
404 |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
405 // Flush output buffer to disk |
54
60a7fb8ddeb4
Add a quick and dirt bzcat (stdin to stdout only for the moment) to test
Rob Landley <rob@landley.net>
parents:
46
diff
changeset
|
406 void flush_bunzip_outbuf(bunzip_data *bd, int out_fd) |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
407 { |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
408 if (bd->outbufPos) { |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
409 if (write(out_fd, bd->outbuf, bd->outbufPos) != bd->outbufPos) |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
410 longjmp(bd->jmpbuf,RETVAL_UNEXPECTED_OUTPUT_EOF); |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
411 bd->outbufPos = 0; |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
412 } |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
413 } |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
414 |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
415 // Undo burrows-wheeler transform on intermediate buffer to produce output. |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
416 // If !len, write up to len bytes of data to buf. Otherwise write to out_fd. |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
417 // Returns len ? bytes written : RETVAL_OK. Notice all errors negative #'s. |
54
60a7fb8ddeb4
Add a quick and dirt bzcat (stdin to stdout only for the moment) to test
Rob Landley <rob@landley.net>
parents:
46
diff
changeset
|
418 int write_bunzip_data(bunzip_data *bd, int out_fd, char *outbuf, int len) |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
419 { |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
420 unsigned int *dbuf = bd->dbuf; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
421 int count, pos, current, run, copies, outbyte, previous, gotcount = 0; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
422 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
423 for (;;) { |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
424 |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
425 // If last read was short due to end of file, return last block now |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
426 if (bd->writeCount < 0) return bd->writeCount; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
427 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
428 // If we need to refill dbuf, do it. |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
429 if (!bd->writeCount) { |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
430 int i = read_bunzip_data(bd); |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
431 if (i) { |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
432 if (i == RETVAL_LAST_BLOCK) { |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
433 bd->writeCount = i; |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
434 return gotcount; |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
435 } else return i; |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
436 } |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
437 } |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
438 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
439 // Loop generating output |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
440 count = bd->writeCount; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
441 pos = bd->writePos; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
442 current = bd->writeCurrent; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
443 run = bd->writeRun; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
444 while (count) { |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
445 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
446 // If somebody (like tar) wants a certain number of bytes of |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
447 // data from memory instead of written to a file, humor them. |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
448 if (len && bd->outbufPos>=len) goto dataus_interruptus; |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
449 count--; |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
450 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
451 // Follow sequence vector to undo Burrows-Wheeler transform. |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
452 previous = current; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
453 pos = dbuf[pos]; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
454 current = pos&0xff; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
455 pos >>= 8; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
456 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
457 // Whenever we see 3 consecutive copies of the same byte, |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
458 // the 4th is a repeat count |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
459 if (run++ == 3) { |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
460 copies = current; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
461 outbyte = previous; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
462 current = -1; |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
463 } else { |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
464 copies = 1; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
465 outbyte = current; |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
466 } |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
467 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
468 // Output bytes to buffer, flushing to file if necessary |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
469 while (copies--) { |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
470 if (bd->outbufPos == IOBUF_SIZE) flush_bunzip_outbuf(bd,out_fd); |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
471 bd->outbuf[bd->outbufPos++] = outbyte; |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
472 bd->dataCRC = (bd->dataCRC << 8) |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
473 ^ bd->crc32Table[(bd->dataCRC >> 24) ^ outbyte]; |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
474 } |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
475 if (current!=previous) run=0; |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
476 } |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
477 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
478 // Decompression of this block completed successfully |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
479 bd->dataCRC = ~(bd->dataCRC); |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
480 bd->totalCRC = ((bd->totalCRC << 1) | (bd->totalCRC >> 31)) |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
481 ^ bd->dataCRC; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
482 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
483 // If this block had a CRC error, force file level CRC error. |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
484 if (bd->dataCRC != bd->headerCRC) { |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
485 bd->totalCRC = bd->headerCRC+1; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
486 |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
487 return RETVAL_LAST_BLOCK; |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
488 } |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
489 dataus_interruptus: |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
490 bd->writeCount = count; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
491 if (len) { |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
492 gotcount += bd->outbufPos; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
493 memcpy(outbuf, bd->outbuf, len); |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
494 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
495 // If we got enough data, checkpoint loop state and return |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
496 if ((len-=bd->outbufPos)<1) { |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
497 bd->outbufPos -= len; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
498 if (bd->outbufPos) |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
499 memmove(bd->outbuf, bd->outbuf+len, bd->outbufPos); |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
500 bd->writePos = pos; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
501 bd->writeCurrent = current; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
502 bd->writeRun = run; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
503 |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
504 return gotcount; |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
505 } |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
506 } |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
507 } |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
508 } |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
509 |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
510 // Allocate the structure, read file header. If !len, src_fd contains |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
511 // filehandle to read from. Else inbuf contains data. |
54
60a7fb8ddeb4
Add a quick and dirt bzcat (stdin to stdout only for the moment) to test
Rob Landley <rob@landley.net>
parents:
46
diff
changeset
|
512 int start_bunzip(bunzip_data **bdp, int src_fd, char *inbuf, int len) |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
513 { |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
514 bunzip_data *bd; |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
515 unsigned int i, j, c; |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
516 |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
517 // Figure out how much data to allocate. |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
518 i = sizeof(bunzip_data); |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
519 if (!len) i += IOBUF_SIZE; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
520 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
521 // Allocate bunzip_data. Most fields initialize to zero. |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
522 if (!(bd = *bdp = malloc(i))) return RETVAL_OUT_OF_MEMORY; |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
523 memset(bd,0,sizeof(bunzip_data)); |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
524 if (len) { |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
525 bd->inbuf = inbuf; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
526 bd->inbufCount = len; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
527 bd->in_fd = -1; |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
528 } else { |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
529 bd->inbuf = (char *)(bd+1); |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
530 bd->in_fd = src_fd; |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
531 } |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
532 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
533 // Init the CRC32 table (big endian) |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
534 for (i=0; i<256; i++) { |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
535 c = i<<24; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
536 for (j=8; j; j--) |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
537 c=c&0x80000000 ? (c<<1)^0x04c11db7 : (c<<1); |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
538 bd->crc32Table[i] = c; |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
539 } |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
540 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
541 // Setup for I/O error handling via longjmp. |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
542 i = setjmp(bd->jmpbuf); |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
543 if (i) return i; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
544 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
545 // Ensure that file starts with "BZh". |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
546 for (i=0;i<3;i++) |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
547 if (get_bits(bd,8)!="BZh"[i]) return RETVAL_NOT_BZIP_DATA; |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
548 |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
549 // Next byte ascii '1'-'9', indicates block size in units of 100k of |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
550 // uncompressed data. Allocate intermediate buffer for block. |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
551 i = get_bits(bd, 8); |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
552 if (i<'1' || i>'9') return RETVAL_NOT_BZIP_DATA; |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
553 bd->dbufSize = 100000*(i-'0'); |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
554 if (!(bd->dbuf = malloc(bd->dbufSize * sizeof(int)))) |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
555 return RETVAL_OUT_OF_MEMORY; |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
556 |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
557 return RETVAL_OK; |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
558 } |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
559 |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
560 // Example usage: decompress src_fd to dst_fd. (Stops at end of bzip data, |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
561 // not end of file.) |
54
60a7fb8ddeb4
Add a quick and dirt bzcat (stdin to stdout only for the moment) to test
Rob Landley <rob@landley.net>
parents:
46
diff
changeset
|
562 char *bunzipStream(int src_fd, int dst_fd) |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
563 { |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
564 bunzip_data *bd; |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
565 int i; |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
566 |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
567 if (!(i = start_bunzip(&bd,src_fd,0,0))) { |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
568 i = write_bunzip_data(bd,dst_fd,0,0); |
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
569 if (i==RETVAL_LAST_BLOCK && bd->headerCRC==bd->totalCRC) i = RETVAL_OK; |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
570 } |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
571 flush_bunzip_outbuf(bd,dst_fd); |
39
00e73c4dea66
More whitespace/cowbell. (And change comment style to //.)
Rob Landley <rob@landley.net>
parents:
37
diff
changeset
|
572 free(bd->dbuf); |
37
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
573 free(bd); |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
574 return bunzip_errors[-i]; |
14d27eab3acf
Add my old micro-bunzip library. Needs some cleanup...
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
575 } |