/zlib.js
JavaScript | 464 lines | 383 code | 42 blank | 39 comment | 89 complexity | 6b0250df873f8ac882719af6e52d62e5 MD5 | raw file
1/* 2 * Extracted from pdf.js 3 * https://github.com/andreasgal/pdf.js 4 * 5 * Copyright (c) 2011 Mozilla Foundation 6 * 7 * Contributors: Andreas Gal <gal@mozilla.com> 8 * Chris G Jones <cjones@mozilla.com> 9 * Shaon Barman <shaon.barman@gmail.com> 10 * Vivien Nicolas <21@vingtetun.org> 11 * Justin D'Arcangelo <justindarc@gmail.com> 12 * Yury Delendik 13 * 14 * Permission is hereby granted, free of charge, to any person obtaining a 15 * copy of this software and associated documentation files (the "Software"), 16 * to deal in the Software without restriction, including without limitation 17 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 18 * and/or sell copies of the Software, and to permit persons to whom the 19 * Software is furnished to do so, subject to the following conditions: 20 * 21 * The above copyright notice and this permission notice shall be included in 22 * all copies or substantial portions of the Software. 23 * 24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 27 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 29 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 30 * DEALINGS IN THE SOFTWARE. 31 */ 32 33var DecodeStream = (function() { 34 function constructor() { 35 this.pos = 0; 36 this.bufferLength = 0; 37 this.eof = false; 38 this.buffer = null; 39 } 40 41 constructor.prototype = { 42 ensureBuffer: function decodestream_ensureBuffer(requested) { 43 var buffer = this.buffer; 44 var current = buffer ? buffer.byteLength : 0; 45 if (requested < current) 46 return buffer; 47 var size = 512; 48 while (size < requested) 49 size <<= 1; 50 var buffer2 = new Uint8Array(size); 51 for (var i = 0; i < current; ++i) 52 buffer2[i] = buffer[i]; 53 return this.buffer = buffer2; 54 }, 55 getByte: function decodestream_getByte() { 56 var pos = this.pos; 57 while (this.bufferLength <= pos) { 58 if (this.eof) 59 return null; 60 this.readBlock(); 61 } 62 return this.buffer[this.pos++]; 63 }, 64 getBytes: function decodestream_getBytes(length) { 65 var pos = this.pos; 66 67 if (length) { 68 this.ensureBuffer(pos + length); 69 var end = pos + length; 70 71 while (!this.eof && this.bufferLength < end) 72 this.readBlock(); 73 74 var bufEnd = this.bufferLength; 75 if (end > bufEnd) 76 end = bufEnd; 77 } else { 78 while (!this.eof) 79 this.readBlock(); 80 81 var end = this.bufferLength; 82 } 83 84 this.pos = end; 85 return this.buffer.subarray(pos, end); 86 }, 87 lookChar: function decodestream_lookChar() { 88 var pos = this.pos; 89 while (this.bufferLength <= pos) { 90 if (this.eof) 91 return null; 92 this.readBlock(); 93 } 94 return String.fromCharCode(this.buffer[this.pos]); 95 }, 96 getChar: function decodestream_getChar() { 97 var pos = this.pos; 98 while (this.bufferLength <= pos) { 99 if (this.eof) 100 return null; 101 this.readBlock(); 102 } 103 return String.fromCharCode(this.buffer[this.pos++]); 104 }, 105 makeSubStream: function decodestream_makeSubstream(start, length, dict) { 106 var end = start + length; 107 while (this.bufferLength <= end && !this.eof) 108 this.readBlock(); 109 return new Stream(this.buffer, start, length, dict); 110 }, 111 skip: function decodestream_skip(n) { 112 if (!n) 113 n = 1; 114 this.pos += n; 115 }, 116 reset: function decodestream_reset() { 117 this.pos = 0; 118 } 119 }; 120 121 return constructor; 122})(); 123 124var FlateStream = (function() { 125 var codeLenCodeMap = new Uint32Array([ 126 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 127 ]); 128 129 var lengthDecode = new Uint32Array([ 130 0x00003, 0x00004, 0x00005, 0x00006, 0x00007, 0x00008, 0x00009, 0x0000a, 131 0x1000b, 0x1000d, 0x1000f, 0x10011, 0x20013, 0x20017, 0x2001b, 0x2001f, 132 0x30023, 0x3002b, 0x30033, 0x3003b, 0x40043, 0x40053, 0x40063, 0x40073, 133 0x50083, 0x500a3, 0x500c3, 0x500e3, 0x00102, 0x00102, 0x00102 134 ]); 135 136 var distDecode = new Uint32Array([ 137 0x00001, 0x00002, 0x00003, 0x00004, 0x10005, 0x10007, 0x20009, 0x2000d, 138 0x30011, 0x30019, 0x40021, 0x40031, 0x50041, 0x50061, 0x60081, 0x600c1, 139 0x70101, 0x70181, 0x80201, 0x80301, 0x90401, 0x90601, 0xa0801, 0xa0c01, 140 0xb1001, 0xb1801, 0xc2001, 0xc3001, 0xd4001, 0xd6001 141 ]); 142 143 var fixedLitCodeTab = [new Uint32Array([ 144 0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c0, 145 0x70108, 0x80060, 0x80020, 0x900a0, 0x80000, 0x80080, 0x80040, 0x900e0, 146 0x70104, 0x80058, 0x80018, 0x90090, 0x70114, 0x80078, 0x80038, 0x900d0, 147 0x7010c, 0x80068, 0x80028, 0x900b0, 0x80008, 0x80088, 0x80048, 0x900f0, 148 0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c8, 149 0x7010a, 0x80064, 0x80024, 0x900a8, 0x80004, 0x80084, 0x80044, 0x900e8, 150 0x70106, 0x8005c, 0x8001c, 0x90098, 0x70116, 0x8007c, 0x8003c, 0x900d8, 151 0x7010e, 0x8006c, 0x8002c, 0x900b8, 0x8000c, 0x8008c, 0x8004c, 0x900f8, 152 0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c4, 153 0x70109, 0x80062, 0x80022, 0x900a4, 0x80002, 0x80082, 0x80042, 0x900e4, 154 0x70105, 0x8005a, 0x8001a, 0x90094, 0x70115, 0x8007a, 0x8003a, 0x900d4, 155 0x7010d, 0x8006a, 0x8002a, 0x900b4, 0x8000a, 0x8008a, 0x8004a, 0x900f4, 156 0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cc, 157 0x7010b, 0x80066, 0x80026, 0x900ac, 0x80006, 0x80086, 0x80046, 0x900ec, 158 0x70107, 0x8005e, 0x8001e, 0x9009c, 0x70117, 0x8007e, 0x8003e, 0x900dc, 159 0x7010f, 0x8006e, 0x8002e, 0x900bc, 0x8000e, 0x8008e, 0x8004e, 0x900fc, 160 0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c2, 161 0x70108, 0x80061, 0x80021, 0x900a2, 0x80001, 0x80081, 0x80041, 0x900e2, 162 0x70104, 0x80059, 0x80019, 0x90092, 0x70114, 0x80079, 0x80039, 0x900d2, 163 0x7010c, 0x80069, 0x80029, 0x900b2, 0x80009, 0x80089, 0x80049, 0x900f2, 164 0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900ca, 165 0x7010a, 0x80065, 0x80025, 0x900aa, 0x80005, 0x80085, 0x80045, 0x900ea, 166 0x70106, 0x8005d, 0x8001d, 0x9009a, 0x70116, 0x8007d, 0x8003d, 0x900da, 167 0x7010e, 0x8006d, 0x8002d, 0x900ba, 0x8000d, 0x8008d, 0x8004d, 0x900fa, 168 0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c6, 169 0x70109, 0x80063, 0x80023, 0x900a6, 0x80003, 0x80083, 0x80043, 0x900e6, 170 0x70105, 0x8005b, 0x8001b, 0x90096, 0x70115, 0x8007b, 0x8003b, 0x900d6, 171 0x7010d, 0x8006b, 0x8002b, 0x900b6, 0x8000b, 0x8008b, 0x8004b, 0x900f6, 172 0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900ce, 173 0x7010b, 0x80067, 0x80027, 0x900ae, 0x80007, 0x80087, 0x80047, 0x900ee, 174 0x70107, 0x8005f, 0x8001f, 0x9009e, 0x70117, 0x8007f, 0x8003f, 0x900de, 175 0x7010f, 0x8006f, 0x8002f, 0x900be, 0x8000f, 0x8008f, 0x8004f, 0x900fe, 176 0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c1, 177 0x70108, 0x80060, 0x80020, 0x900a1, 0x80000, 0x80080, 0x80040, 0x900e1, 178 0x70104, 0x80058, 0x80018, 0x90091, 0x70114, 0x80078, 0x80038, 0x900d1, 179 0x7010c, 0x80068, 0x80028, 0x900b1, 0x80008, 0x80088, 0x80048, 0x900f1, 180 0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c9, 181 0x7010a, 0x80064, 0x80024, 0x900a9, 0x80004, 0x80084, 0x80044, 0x900e9, 182 0x70106, 0x8005c, 0x8001c, 0x90099, 0x70116, 0x8007c, 0x8003c, 0x900d9, 183 0x7010e, 0x8006c, 0x8002c, 0x900b9, 0x8000c, 0x8008c, 0x8004c, 0x900f9, 184 0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c5, 185 0x70109, 0x80062, 0x80022, 0x900a5, 0x80002, 0x80082, 0x80042, 0x900e5, 186 0x70105, 0x8005a, 0x8001a, 0x90095, 0x70115, 0x8007a, 0x8003a, 0x900d5, 187 0x7010d, 0x8006a, 0x8002a, 0x900b5, 0x8000a, 0x8008a, 0x8004a, 0x900f5, 188 0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cd, 189 0x7010b, 0x80066, 0x80026, 0x900ad, 0x80006, 0x80086, 0x80046, 0x900ed, 190 0x70107, 0x8005e, 0x8001e, 0x9009d, 0x70117, 0x8007e, 0x8003e, 0x900dd, 191 0x7010f, 0x8006e, 0x8002e, 0x900bd, 0x8000e, 0x8008e, 0x8004e, 0x900fd, 192 0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c3, 193 0x70108, 0x80061, 0x80021, 0x900a3, 0x80001, 0x80081, 0x80041, 0x900e3, 194 0x70104, 0x80059, 0x80019, 0x90093, 0x70114, 0x80079, 0x80039, 0x900d3, 195 0x7010c, 0x80069, 0x80029, 0x900b3, 0x80009, 0x80089, 0x80049, 0x900f3, 196 0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900cb, 197 0x7010a, 0x80065, 0x80025, 0x900ab, 0x80005, 0x80085, 0x80045, 0x900eb, 198 0x70106, 0x8005d, 0x8001d, 0x9009b, 0x70116, 0x8007d, 0x8003d, 0x900db, 199 0x7010e, 0x8006d, 0x8002d, 0x900bb, 0x8000d, 0x8008d, 0x8004d, 0x900fb, 200 0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c7, 201 0x70109, 0x80063, 0x80023, 0x900a7, 0x80003, 0x80083, 0x80043, 0x900e7, 202 0x70105, 0x8005b, 0x8001b, 0x90097, 0x70115, 0x8007b, 0x8003b, 0x900d7, 203 0x7010d, 0x8006b, 0x8002b, 0x900b7, 0x8000b, 0x8008b, 0x8004b, 0x900f7, 204 0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900cf, 205 0x7010b, 0x80067, 0x80027, 0x900af, 0x80007, 0x80087, 0x80047, 0x900ef, 206 0x70107, 0x8005f, 0x8001f, 0x9009f, 0x70117, 0x8007f, 0x8003f, 0x900df, 207 0x7010f, 0x8006f, 0x8002f, 0x900bf, 0x8000f, 0x8008f, 0x8004f, 0x900ff 208 ]), 9]; 209 210 var fixedDistCodeTab = [new Uint32Array([ 211 0x50000, 0x50010, 0x50008, 0x50018, 0x50004, 0x50014, 0x5000c, 0x5001c, 212 0x50002, 0x50012, 0x5000a, 0x5001a, 0x50006, 0x50016, 0x5000e, 0x00000, 213 0x50001, 0x50011, 0x50009, 0x50019, 0x50005, 0x50015, 0x5000d, 0x5001d, 214 0x50003, 0x50013, 0x5000b, 0x5001b, 0x50007, 0x50017, 0x5000f, 0x00000 215 ]), 5]; 216 217 function error(e) { 218 throw new Error(e) 219 } 220 221 function constructor(bytes) { 222 //var bytes = stream.getBytes(); 223 var bytesPos = 0; 224 225 var cmf = bytes[bytesPos++]; 226 var flg = bytes[bytesPos++]; 227 if (cmf == -1 || flg == -1) 228 error('Invalid header in flate stream'); 229 if ((cmf & 0x0f) != 0x08) 230 error('Unknown compression method in flate stream'); 231 if ((((cmf << 8) + flg) % 31) != 0) 232 error('Bad FCHECK in flate stream'); 233 if (flg & 0x20) 234 error('FDICT bit set in flate stream'); 235 236 this.bytes = bytes; 237 this.bytesPos = bytesPos; 238 239 this.codeSize = 0; 240 this.codeBuf = 0; 241 242 DecodeStream.call(this); 243 } 244 245 constructor.prototype = Object.create(DecodeStream.prototype); 246 247 constructor.prototype.getBits = function(bits) { 248 var codeSize = this.codeSize; 249 var codeBuf = this.codeBuf; 250 var bytes = this.bytes; 251 var bytesPos = this.bytesPos; 252 253 var b; 254 while (codeSize < bits) { 255 if (typeof (b = bytes[bytesPos++]) == 'undefined') 256 error('Bad encoding in flate stream'); 257 codeBuf |= b << codeSize; 258 codeSize += 8; 259 } 260 b = codeBuf & ((1 << bits) - 1); 261 this.codeBuf = codeBuf >> bits; 262 this.codeSize = codeSize -= bits; 263 this.bytesPos = bytesPos; 264 return b; 265 }; 266 267 constructor.prototype.getCode = function(table) { 268 var codes = table[0]; 269 var maxLen = table[1]; 270 var codeSize = this.codeSize; 271 var codeBuf = this.codeBuf; 272 var bytes = this.bytes; 273 var bytesPos = this.bytesPos; 274 275 while (codeSize < maxLen) { 276 var b; 277 if (typeof (b = bytes[bytesPos++]) == 'undefined') 278 error('Bad encoding in flate stream'); 279 codeBuf |= (b << codeSize); 280 codeSize += 8; 281 } 282 var code = codes[codeBuf & ((1 << maxLen) - 1)]; 283 var codeLen = code >> 16; 284 var codeVal = code & 0xffff; 285 if (codeSize == 0 || codeSize < codeLen || codeLen == 0) 286 error('Bad encoding in flate stream'); 287 this.codeBuf = (codeBuf >> codeLen); 288 this.codeSize = (codeSize - codeLen); 289 this.bytesPos = bytesPos; 290 return codeVal; 291 }; 292 293 constructor.prototype.generateHuffmanTable = function(lengths) { 294 var n = lengths.length; 295 296 // find max code length 297 var maxLen = 0; 298 for (var i = 0; i < n; ++i) { 299 if (lengths[i] > maxLen) 300 maxLen = lengths[i]; 301 } 302 303 // build the table 304 var size = 1 << maxLen; 305 var codes = new Uint32Array(size); 306 for (var len = 1, code = 0, skip = 2; 307 len <= maxLen; 308 ++len, code <<= 1, skip <<= 1) { 309 for (var val = 0; val < n; ++val) { 310 if (lengths[val] == len) { 311 // bit-reverse the code 312 var code2 = 0; 313 var t = code; 314 for (var i = 0; i < len; ++i) { 315 code2 = (code2 << 1) | (t & 1); 316 t >>= 1; 317 } 318 319 // fill the table entries 320 for (var i = code2; i < size; i += skip) 321 codes[i] = (len << 16) | val; 322 323 ++code; 324 } 325 } 326 } 327 328 return [codes, maxLen]; 329 }; 330 331 constructor.prototype.readBlock = function() { 332 function repeat(stream, array, len, offset, what) { 333 var repeat = stream.getBits(len) + offset; 334 while (repeat-- > 0) 335 array[i++] = what; 336 } 337 338 // read block header 339 var hdr = this.getBits(3); 340 if (hdr & 1) 341 this.eof = true; 342 hdr >>= 1; 343 344 if (hdr == 0) { // uncompressed block 345 var bytes = this.bytes; 346 var bytesPos = this.bytesPos; 347 var b; 348 349 if (typeof (b = bytes[bytesPos++]) == 'undefined') 350 error('Bad block header in flate stream'); 351 var blockLen = b; 352 if (typeof (b = bytes[bytesPos++]) == 'undefined') 353 error('Bad block header in flate stream'); 354 blockLen |= (b << 8); 355 if (typeof (b = bytes[bytesPos++]) == 'undefined') 356 error('Bad block header in flate stream'); 357 var check = b; 358 if (typeof (b = bytes[bytesPos++]) == 'undefined') 359 error('Bad block header in flate stream'); 360 check |= (b << 8); 361 if (check != (~blockLen & 0xffff)) 362 error('Bad uncompressed block length in flate stream'); 363 364 this.codeBuf = 0; 365 this.codeSize = 0; 366 367 var bufferLength = this.bufferLength; 368 var buffer = this.ensureBuffer(bufferLength + blockLen); 369 var end = bufferLength + blockLen; 370 this.bufferLength = end; 371 for (var n = bufferLength; n < end; ++n) { 372 if (typeof (b = bytes[bytesPos++]) == 'undefined') { 373 this.eof = true; 374 break; 375 } 376 buffer[n] = b; 377 } 378 this.bytesPos = bytesPos; 379 return; 380 } 381 382 var litCodeTable; 383 var distCodeTable; 384 if (hdr == 1) { // compressed block, fixed codes 385 litCodeTable = fixedLitCodeTab; 386 distCodeTable = fixedDistCodeTab; 387 } else if (hdr == 2) { // compressed block, dynamic codes 388 var numLitCodes = this.getBits(5) + 257; 389 var numDistCodes = this.getBits(5) + 1; 390 var numCodeLenCodes = this.getBits(4) + 4; 391 392 // build the code lengths code table 393 var codeLenCodeLengths = Array(codeLenCodeMap.length); 394 var i = 0; 395 while (i < numCodeLenCodes) 396 codeLenCodeLengths[codeLenCodeMap[i++]] = this.getBits(3); 397 var codeLenCodeTab = this.generateHuffmanTable(codeLenCodeLengths); 398 399 // build the literal and distance code tables 400 var len = 0; 401 var i = 0; 402 var codes = numLitCodes + numDistCodes; 403 var codeLengths = new Array(codes); 404 while (i < codes) { 405 var code = this.getCode(codeLenCodeTab); 406 if (code == 16) { 407 repeat(this, codeLengths, 2, 3, len); 408 } else if (code == 17) { 409 repeat(this, codeLengths, 3, 3, len = 0); 410 } else if (code == 18) { 411 repeat(this, codeLengths, 7, 11, len = 0); 412 } else { 413 codeLengths[i++] = len = code; 414 } 415 } 416 417 litCodeTable = 418 this.generateHuffmanTable(codeLengths.slice(0, numLitCodes)); 419 distCodeTable = 420 this.generateHuffmanTable(codeLengths.slice(numLitCodes, codes)); 421 } else { 422 error('Unknown block type in flate stream'); 423 } 424 425 var buffer = this.buffer; 426 var limit = buffer ? buffer.length : 0; 427 var pos = this.bufferLength; 428 while (true) { 429 var code1 = this.getCode(litCodeTable); 430 if (code1 < 256) { 431 if (pos + 1 >= limit) { 432 buffer = this.ensureBuffer(pos + 1); 433 limit = buffer.length; 434 } 435 buffer[pos++] = code1; 436 continue; 437 } 438 if (code1 == 256) { 439 this.bufferLength = pos; 440 return; 441 } 442 code1 -= 257; 443 code1 = lengthDecode[code1]; 444 var code2 = code1 >> 16; 445 if (code2 > 0) 446 code2 = this.getBits(code2); 447 var len = (code1 & 0xffff) + code2; 448 code1 = this.getCode(distCodeTable); 449 code1 = distDecode[code1]; 450 code2 = code1 >> 16; 451 if (code2 > 0) 452 code2 = this.getBits(code2); 453 var dist = (code1 & 0xffff) + code2; 454 if (pos + len >= limit) { 455 buffer = this.ensureBuffer(pos + len); 456 limit = buffer.length; 457 } 458 for (var k = 0; k < len; ++k, ++pos) 459 buffer[pos] = buffer[pos - dist]; 460 } 461 }; 462 463 return constructor; 464})();