/zlib.js

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