blob: 61c8ceeb7f169a6a4a5477a7536c2f5efbfcb65e [file] [log] [blame]
Leo Repp58b9f112021-11-22 11:57:47 +01001/*
2 bzip2.js - a small bzip2 decompression implementation
3
4 Copyright 2011 by antimatter15 (antimatter15@gmail.com)
5
6 Based on micro-bunzip by Rob Landley (rob@landley.net).
7
8 Copyright (c) 2011 by antimatter15 (antimatter15@gmail.com).
9
10 Permission is hereby granted, free of charge, to any person obtaining a
11 copy of this software and associated documentation files (the "Software"),
12 to deal in the Software without restriction, including without limitation
13 the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 and/or sell copies of the Software, and to permit persons to whom the
15 Software is furnished to do so, subject to the following conditions:
16
17 The above copyright notice and this permission notice shall be included
18 in all copies or substantial portions of the Software.
19
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
24 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
26 THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27*/
28function Bzip2Error(message) {
29 this.name = 'Bzip2Error';
30 this.message = message;
31 this.stack = (new Error()).stack;
32}
33Bzip2Error.prototype = new Error;
34
35var message = {
36 Error: function(message) {throw new Bzip2Error(message);}
37};
38
39var bzip2 = {};
40bzip2.Bzip2Error = Bzip2Error;
41
42bzip2.crcTable =
43[
44 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
45 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
46 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
47 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
48 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
49 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
50 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
51 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
52 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
53 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
54 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
55 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
56 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
57 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
58 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
59 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
60 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
61 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
62 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
63 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
64 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
65 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
66 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
67 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
68 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
69 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
70 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
71 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
72 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
73 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
74 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
75 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
76 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
77 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
78 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
79 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
80 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
81 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
82 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
83 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
84 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
85 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
86 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
87 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
88 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
89 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
90 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
91 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
92 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
93 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
94 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
95 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
96 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
97 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
98 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
99 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
100 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
101 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
102 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
103 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
104 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
105 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
106 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
107 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
108];
109
110bzip2.array = function(bytes) {
111 var bit = 0, byte = 0;
112 var BITMASK = [0, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF ];
113 return function(n) {
114 var result = 0;
115 while(n > 0) {
116 var left = 8 - bit;
117 if (n >= left) {
118 result <<= left;
119 result |= (BITMASK[left] & bytes[byte++]);
120 bit = 0;
121 n -= left;
122 } else {
123 result <<= n;
124 result |= ((bytes[byte] & (BITMASK[n] << (8 - n - bit))) >> (8 - n - bit));
125 bit += n;
126 n = 0;
127 }
128 }
129 return result;
130 }
131}
132
133
134bzip2.simple = function(srcbuffer, stream) {
135 var bits = bzip2.array(srcbuffer);
136 var size = bzip2.header(bits);
137 var ret = false;
138 var bufsize = 100000 * size;
139 var buf = new Int32Array(bufsize);
140
141 do {
142 ret = bzip2.decompress(bits, stream, buf, bufsize);
143 } while(!ret);
144}
145
146bzip2.header = function(bits) {
147 this.byteCount = new Int32Array(256);
148 this.symToByte = new Uint8Array(256);
149 this.mtfSymbol = new Int32Array(256);
150 this.selectors = new Uint8Array(0x8000);
151
152 if (bits(8*3) != 4348520) message.Error("No magic number found");
153
154 var i = bits(8) - 48;
155 if (i < 1 || i > 9) message.Error("Not a BZIP archive");
156 return i;
157};
158
159
160//takes a function for reading the block data (starting with 0x314159265359)
161//a block size (0-9) (optional, defaults to 9)
162//a length at which to stop decompressing and return the output
163bzip2.decompress = function(bits, stream, buf, bufsize, streamCRC) {
164 var MAX_HUFCODE_BITS = 20;
165 var MAX_SYMBOLS = 258;
166 var SYMBOL_RUNA = 0;
167 var SYMBOL_RUNB = 1;
168 var GROUP_SIZE = 50;
169 var crc = 0 ^ (-1);
170
171 for(var h = '', i = 0; i < 6; i++) h += bits(8).toString(16);
172 if (h == "177245385090") {
173 var finalCRC = bits(32)|0;
174 if (finalCRC !== streamCRC) message.Error("Error in bzip2: crc32 do not match");
175 // align stream to byte
176 bits(null);
177 return null; // reset streamCRC for next call
178 }
179 if (h != "314159265359") message.Error("eek not valid bzip data");
180 var crcblock = bits(32)|0; // CRC code
181 if (bits(1)) message.Error("unsupported obsolete version");
182 var origPtr = bits(24);
183 if (origPtr > bufsize) message.Error("Initial position larger than buffer size");
184 var t = bits(16);
185 var symTotal = 0;
186 for (i = 0; i < 16; i++) {
187 if (t & (1 << (15 - i))) {
188 var k = bits(16);
189 for(j = 0; j < 16; j++) {
190 if (k & (1 << (15 - j))) {
191 this.symToByte[symTotal++] = (16 * i) + j;
192 }
193 }
194 }
195 }
196
197 var groupCount = bits(3);
198 if (groupCount < 2 || groupCount > 6) message.Error("another error");
199 var nSelectors = bits(15);
200 if (nSelectors == 0) message.Error("meh");
201 for(var i = 0; i < groupCount; i++) this.mtfSymbol[i] = i;
202
203 for(var i = 0; i < nSelectors; i++) {
204 for(var j = 0; bits(1); j++) if (j >= groupCount) message.Error("whoops another error");
205 var uc = this.mtfSymbol[j];
206 for(var k = j-1; k>=0; k--) {
207 this.mtfSymbol[k+1] = this.mtfSymbol[k];
208 }
209 this.mtfSymbol[0] = uc;
210 this.selectors[i] = uc;
211 }
212
213 var symCount = symTotal + 2;
214 var groups = [];
215 var length = new Uint8Array(MAX_SYMBOLS),
216 temp = new Uint16Array(MAX_HUFCODE_BITS+1);
217
218 var hufGroup;
219
220 for(var j = 0; j < groupCount; j++) {
221 t = bits(5); //lengths
222 for(var i = 0; i < symCount; i++) {
223 while(true){
224 if (t < 1 || t > MAX_HUFCODE_BITS) message.Error("I gave up a while ago on writing error messages");
225 if (!bits(1)) break;
226 if (!bits(1)) t++;
227 else t--;
228 }
229 length[i] = t;
230 }
231 var minLen, maxLen;
232 minLen = maxLen = length[0];
233 for(var i = 1; i < symCount; i++) {
234 if (length[i] > maxLen) maxLen = length[i];
235 else if (length[i] < minLen) minLen = length[i];
236 }
237 hufGroup = groups[j] = {};
238 hufGroup.permute = new Int32Array(MAX_SYMBOLS);
239 hufGroup.limit = new Int32Array(MAX_HUFCODE_BITS + 1);
240 hufGroup.base = new Int32Array(MAX_HUFCODE_BITS + 1);
241
242 hufGroup.minLen = minLen;
243 hufGroup.maxLen = maxLen;
244 var base = hufGroup.base;
245 var limit = hufGroup.limit;
246 var pp = 0;
247 for(var i = minLen; i <= maxLen; i++)
248 for(var t = 0; t < symCount; t++)
249 if (length[t] == i) hufGroup.permute[pp++] = t;
250 for(i = minLen; i <= maxLen; i++) temp[i] = limit[i] = 0;
251 for(i = 0; i < symCount; i++) temp[length[i]]++;
252 pp = t = 0;
253 for(i = minLen; i < maxLen; i++) {
254 pp += temp[i];
255 limit[i] = pp - 1;
256 pp <<= 1;
257 base[i+1] = pp - (t += temp[i]);
258 }
259 limit[maxLen] = pp + temp[maxLen] - 1;
260 base[minLen] = 0;
261 }
262
263 for(var i = 0; i < 256; i++) {
264 this.mtfSymbol[i] = i;
265 this.byteCount[i] = 0;
266 }
267 var runPos, count, symCount, selector;
268 runPos = count = symCount = selector = 0;
269 while(true) {
270 if (!(symCount--)) {
271 symCount = GROUP_SIZE - 1;
272 if (selector >= nSelectors) message.Error("meow i'm a kitty, that's an error");
273 hufGroup = groups[this.selectors[selector++]];
274 base = hufGroup.base;
275 limit = hufGroup.limit;
276 }
277 i = hufGroup.minLen;
278 j = bits(i);
279 while(true) {
280 if (i > hufGroup.maxLen) message.Error("rawr i'm a dinosaur");
281 if (j <= limit[i]) break;
282 i++;
283 j = (j << 1) | bits(1);
284 }
285 j -= base[i];
286 if (j < 0 || j >= MAX_SYMBOLS) message.Error("moo i'm a cow");
287 var nextSym = hufGroup.permute[j];
288 if (nextSym == SYMBOL_RUNA || nextSym == SYMBOL_RUNB) {
289 if (!runPos){
290 runPos = 1;
291 t = 0;
292 }
293 if (nextSym == SYMBOL_RUNA) t += runPos;
294 else t += 2 * runPos;
295 runPos <<= 1;
296 continue;
297 }
298 if (runPos) {
299 runPos = 0;
300 if (count + t > bufsize) message.Error("Boom.");
301 uc = this.symToByte[this.mtfSymbol[0]];
302 this.byteCount[uc] += t;
303 while(t--) buf[count++] = uc;
304 }
305 if (nextSym > symTotal) break;
306 if (count >= bufsize) message.Error("I can't think of anything. Error");
307 i = nextSym - 1;
308 uc = this.mtfSymbol[i];
309 for(var k = i-1; k>=0; k--) {
310 this.mtfSymbol[k+1] = this.mtfSymbol[k];
311 }
312 this.mtfSymbol[0] = uc
313 uc = this.symToByte[uc];
314 this.byteCount[uc]++;
315 buf[count++] = uc;
316 }
317 if (origPtr < 0 || origPtr >= count) message.Error("I'm a monkey and I'm throwing something at someone, namely you");
318 var j = 0;
319 for(var i = 0; i < 256; i++) {
320 k = j + this.byteCount[i];
321 this.byteCount[i] = j;
322 j = k;
323 }
324 for(var i = 0; i < count; i++) {
325 uc = buf[i] & 0xff;
326 buf[this.byteCount[uc]] |= (i << 8);
327 this.byteCount[uc]++;
328 }
329 var pos = 0, current = 0, run = 0;
330 if (count) {
331 pos = buf[origPtr];
332 current = (pos & 0xff);
333 pos >>= 8;
334 run = -1;
335 }
336 count = count;
337 var copies, previous, outbyte;
338 while(count) {
339 count--;
340 previous = current;
341 pos = buf[pos];
342 current = pos & 0xff;
343 pos >>= 8;
344 if (run++ == 3) {
345 copies = current;
346 outbyte = previous;
347 current = -1;
348 } else {
349 copies = 1;
350 outbyte = current;
351 }
352 while(copies--) {
353 crc = ((crc << 8) ^ this.crcTable[((crc>>24) ^ outbyte) & 0xFF])&0xFFFFFFFF; // crc32
354 stream(outbyte);
355 }
356 if (current != previous) run = 0;
357 }
358
359 crc = (crc ^ (-1)) >>> 0;
360 if ((crc|0) != (crcblock|0)) message.Error("Error in bzip2: crc32 do not match");
361 streamCRC = (crc ^ ((streamCRC << 1) | (streamCRC >>> 31))) & 0xFFFFFFFF;
362 return streamCRC;
363}
364
365module.exports = bzip2;