index.ts 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. const u8 = Uint8Array, u16 = Uint16Array;
  2. // fixed lengths
  3. const fl = new u16([3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, /* unused */ 258, 258, /* impossible */ 258]);
  4. // fixed length extra bits
  5. // yes, this can be calculated, but hardcoding is more efficient
  6. const fleb = new u8([0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, /* unused */ 0, 0, /* impossible */ 0]);
  7. // fixed distances
  8. const fd = new u16([1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, /* unused */ 32768, 32768]);
  9. // fixed distance extra bits
  10. // see fleb note
  11. const fdeb = new u8([0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, /* unused */ 13, 13]);
  12. // code length index map
  13. const clim = new u8([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]);
  14. // map of value to reverse (assuming 16 bits)
  15. const rev = new u16(32768);
  16. for (let i = 0; i < 32768; ++i) {
  17. // reverse table algorithm from UZIP.js
  18. let x = i;
  19. x = ((x & 0xaaaaaaaa) >>> 1) | ((x & 0x55555555) << 1);
  20. x = ((x & 0xcccccccc) >>> 2) | ((x & 0x33333333) << 2);
  21. x = ((x & 0xf0f0f0f0) >>> 4) | ((x & 0x0f0f0f0f) << 4);
  22. rev[i] = ((x & 0xff00ff00) >>> 8) | ((x & 0x00ff00ff) << 8);
  23. }
  24. // create huffman tree from u8 "map": index -> code length for code index
  25. // mb (max bits) must be at most 15
  26. const hTree = (cd: Uint8Array, mb: number) => {
  27. // index
  28. let i = 0;
  29. // u8 "map": index -> # of codes with bit length = index
  30. const l = new u8(mb);
  31. // length of cd must be 288 (total # of codes)
  32. for (; i < cd.length; ++i) ++l[cd[i] - 1];
  33. // u16 "map": index -> minimum code for bit length = index
  34. const le = new u16(mb);
  35. for (i = 0; i < mb; ++i) {
  36. le[i] = (le[i - 1] + l[i - 1]) << 1;
  37. }
  38. // u16 "map": index -> number of actual bits, symbol for code
  39. const co = new u16(1 << mb);
  40. for (i = 0; i < cd.length; ++i) {
  41. // ignore 0 lengths
  42. if (cd[i]) {
  43. // num encoding both symbol and bits read
  44. const sv = (i << 4) | cd[i];
  45. // free bits
  46. const r = mb - cd[i];
  47. // bits to remove for reverser
  48. const rvb = 16 - mb;
  49. // start value
  50. let v = le[cd[i] - 1]++ << r;
  51. // m is end value
  52. for (const m = v | ((1 << r) - 1); v <= m; ++v) {
  53. // every 16 bit value starting with the code yields the same result
  54. co[rev[v] >>> rvb] = sv;
  55. }
  56. }
  57. }
  58. return co;
  59. }
  60. // fixed length tree
  61. const flt = new u8(288);
  62. for (let i = 0; i < 144; ++i) flt[i] = 8;
  63. for (let i = 144; i < 256; ++i) flt[i] = 9;
  64. for (let i = 256; i < 280; ++i) flt[i] = 7;
  65. for (let i = 280; i < 288; ++i) flt[i] = 8;
  66. // fixed distance tree
  67. const fdt = new u8(32);
  68. for (let i = 0; i < 32; ++i) fdt[i] = 5;
  69. // fixed length map
  70. const flm = hTree(flt, 9);
  71. // fixed distance map
  72. const fdm = hTree(fdt, 5);
  73. // fixed length mask
  74. const fml = (1 << 9) - 1;
  75. // fixed dist mask
  76. const fmd = (1 << 5) - 1;
  77. // find max of array
  78. const max = (a: Uint8Array) => {
  79. let m = a[0];
  80. for (let i = 0; i < a.length; ++i) {
  81. if (a[i] > m) m = a[i];
  82. }
  83. return m;
  84. };
  85. // read d, starting at bit p continuing for l bits
  86. const bits = (d: Uint8Array, p: number, l: number) => {
  87. const o = p >>> 3;
  88. return ((d[o] | (d[o + 1] << 8)) >>> (p & 7)) & ((1 << l) - 1);
  89. }
  90. // read d, starting at bit p continuing for at least 16 bits
  91. const bits16 = (d: Uint8Array, p: number) => {
  92. const o = p >>> 3;
  93. return ((d[o] | (d[o + 1] << 8) | (d[o + 2] << 16) | (d[o + 3] << 24)) >>> (p & 7));
  94. }
  95. // maximum chunk size (practically, theoretically infinite)
  96. const MC = 1 << 17;
  97. const inflate = (dat: Uint8Array, buf?: Uint8Array) => {
  98. // have to estimate size
  99. const noBuf = buf == null;
  100. // Slightly less than 2x - assumes ~60% compression ratio
  101. if (noBuf) buf = new u8((dat.length >>> 2) << 3);
  102. // ensure buffer can fit at least l elements
  103. const cbuf = (l: number) => {
  104. let bl = buf.length;
  105. // need to increase size to fit
  106. if (l > bl) {
  107. // Double or set to necessary, whichever is greater
  108. const nbuf = new u8(Math.max(bl << 1, l));
  109. nbuf.set(buf);
  110. buf = nbuf;
  111. }
  112. }
  113. // last chunk chunktype literal dist lengths lmask dmask
  114. let final = false, type = 0, hLit = 0, hDist = 0, hcLen = 0, ml = 0, md = 0;
  115. // bitpos bytes
  116. let pos = 0, bt = 0;
  117. // len dist
  118. let lm: Uint16Array, dm: Uint16Array;
  119. while (!final) {
  120. // BFINAL - this is only 1 when last chunk is next
  121. final = bits(dat, pos, 1) as unknown as boolean;
  122. // type: 0 = no compression, 1 = fixed huffman, 2 = dynamic huffman
  123. type = bits(dat, pos + 1, 2);
  124. pos += 3;
  125. if (!type) {
  126. // go to end of byte boundary
  127. if (pos & 7) pos += 8 - (pos & 7);
  128. const s = (pos >>> 3) + 4, l = dat[s - 4] | (dat[s - 3] << 8);
  129. // ensure size
  130. if (noBuf) cbuf(bt + l);
  131. // Copy over uncompressed data
  132. buf.set(dat.subarray(s, s + l), bt);
  133. // Get new bitpos, update byte count
  134. pos = (s + l) << 3, bt += l;
  135. continue;
  136. }
  137. // Make sure the buffer can hold this + the largest possible addition
  138. if (noBuf) cbuf(bt + MC);
  139. if (type == 1) {
  140. lm = flm;
  141. dm = fdm;
  142. ml = fml;
  143. md = fmd;
  144. }
  145. else if (type == 2) {
  146. hLit = bits(dat, pos, 5) + 257;
  147. hDist = bits(dat, pos + 5, 5) + 1;
  148. hcLen = bits(dat, pos + 10, 4) + 4;
  149. pos += 14;
  150. // length+distance tree
  151. const ldt = new u8(hLit + hDist);
  152. // code length tree
  153. const clt = new u8(19);
  154. for (let i = 0; i < hcLen; ++i) {
  155. // use index map to get real code
  156. clt[clim[i]] = bits(dat, pos + i * 3, 3);
  157. }
  158. pos += hcLen * 3;
  159. // code lengths bits
  160. const clb = max(clt);
  161. // code lengths map
  162. const clm = hTree(clt, clb);
  163. for (let i = 0; i < ldt.length;) {
  164. const r = clm[bits(dat, pos, clb)];
  165. // bits read
  166. pos += r & 15;
  167. // symbol
  168. const s = r >>> 4;
  169. // code length to copy
  170. if (s < 16) {
  171. ldt[i++] = s;
  172. } else {
  173. // copy count
  174. let c = 0, n = 0;
  175. if (s == 16) n = 3 + bits(dat, pos, 2), pos += 2, c = ldt[i - 1];
  176. else if (s == 17) n = 3 + bits(dat, pos, 3), pos += 3;
  177. else if (s == 18) n = 11 + bits(dat, pos, 7), pos += 7;
  178. while (n--) ldt[i++] = c;
  179. }
  180. }
  181. // length tree distance tree
  182. const lt = ldt.subarray(0, hLit), dt = ldt.subarray(hLit);
  183. // max length bits
  184. const mlb = max(lt)
  185. // max dist bits
  186. const mdb = max(dt);
  187. ml = (1 << mlb) - 1;
  188. lm = hTree(lt, mlb);
  189. md = (1 << mdb) - 1;
  190. dm = hTree(dt, mdb);
  191. }
  192. while (1) {
  193. // bits read, code
  194. const c = lm[bits16(dat, pos) & ml];
  195. pos += c & 15;
  196. // code
  197. const sym = c >>> 4;
  198. if (sym < 256) buf[bt++] = sym;
  199. else if (sym == 256) break;
  200. else {
  201. let end = bt + sym - 254;
  202. // no extra bits needed if less
  203. if (sym > 264) {
  204. // index
  205. const i = sym - 257;
  206. end = bt + bits(dat, pos, fleb[i]) + fl[i];
  207. pos += fleb[i];
  208. }
  209. // dist
  210. const d = dm[bits16(dat, pos) & md];
  211. pos += d & 15;
  212. const dsym = d >>> 4;
  213. let dt = fd[dsym];
  214. if (dsym > 3) {
  215. dt += bits16(dat, pos) & ((1 << fdeb[dsym]) - 1);
  216. pos += fdeb[dsym];
  217. }
  218. if (noBuf) cbuf(bt + MC);
  219. while (bt < end) {
  220. buf[bt] = buf[bt++-dt];
  221. buf[bt] = buf[bt++-dt];
  222. buf[bt] = buf[bt++-dt];
  223. buf[bt] = buf[bt++-dt];
  224. }
  225. bt = end;
  226. }
  227. }
  228. }
  229. return buf.slice(0, bt);
  230. }
  231. export { inflate };