flate.ts 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609
  1. // DEFLATE is a complex format; to read this code, you should probably check the RFC first:
  2. // https://tools.ietf.org/html/rfc1951
  3. // Much of the following code is similar to that of UZIP.js:
  4. // https://github.com/photopea/UZIP.js
  5. // Many optimizations have been made, so the bundle size is ultimately smaller but performance is similar.
  6. // Sometimes 0 will appear where -1 would be more appropriate. This is because using a uint
  7. // is better for memory in most engines (I *think*).
  8. // aliases for shorter compressed code (most minifers don't do this)
  9. const u8 = Uint8Array, u16 = Uint16Array, u32 = Uint32Array;
  10. // fixed length extra bits
  11. 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]);
  12. // fixed distance extra bits
  13. // see fleb note
  14. 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 */ 0, 0]);
  15. // code length index map
  16. const clim = new u8([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]);
  17. // get base, reverse index map from extra bits
  18. const freb = (eb: Uint8Array, start: number) => {
  19. const b = new u16(31);
  20. for (let i = 0; i < 31; ++i) {
  21. b[i] = start += 1 << eb[i - 1];
  22. }
  23. // numbers here are at max 18 bits
  24. const r = new u32(b[30]);
  25. for (let i = 1; i < 30; ++i) {
  26. for (let j = b[i]; j < b[i + 1]; ++j) {
  27. r[j] = ((j - b[i]) << 5) | i;
  28. }
  29. }
  30. return [b, r] as const;
  31. }
  32. const [fl, revfl] = freb(fleb, 2);
  33. // we can ignore the fact that the other numbers are wrong; they never happen anyway
  34. fl[28] = 258;
  35. revfl[258] = 28;
  36. const [fd, revfd] = freb(fdeb, 0);
  37. // map of value to reverse (assuming 16 bits)
  38. const rev = new u16(32768);
  39. for (let i = 0; i < 32768; ++i) {
  40. // reverse table algorithm from UZIP.js
  41. let x = i;
  42. x = ((x & 0xaaaaaaaa) >>> 1) | ((x & 0x55555555) << 1);
  43. x = ((x & 0xcccccccc) >>> 2) | ((x & 0x33333333) << 2);
  44. x = ((x & 0xf0f0f0f0) >>> 4) | ((x & 0x0f0f0f0f) << 4);
  45. x = ((x & 0xff00ff00) >>> 8) | ((x & 0x00ff00ff) << 8);
  46. rev[i] = ((x >>> 16) | (x << 16)) >>> 17;
  47. }
  48. // create huffman tree from u8 "map": index -> code length for code index
  49. // mb (max bits) must be at most 15
  50. // TODO: optimize/split up?
  51. const hMap = ((cd: Uint8Array, mb: number, r: 0 | 1) => {
  52. const s = cd.length;
  53. // index
  54. let i = 0;
  55. // u8 "map": index -> # of codes with bit length = index
  56. const l = new u8(mb);
  57. // length of cd must be 288 (total # of codes)
  58. for (; i < s; ++i) ++l[cd[i] - 1];
  59. // u16 "map": index -> minimum code for bit length = index
  60. const le = new u16(mb);
  61. for (i = 0; i < mb; ++i) {
  62. le[i] = (le[i - 1] + l[i - 1]) << 1;
  63. }
  64. let co: Uint16Array;
  65. if (r) {
  66. co = new u16(s);
  67. for (i = 0; i < s; ++i) co[i] = rev[le[cd[i] - 1]++] >>> (15 - cd[i]);
  68. } else {
  69. // u16 "map": index -> number of actual bits, symbol for code
  70. co = new u16(1 << mb);
  71. // bits to remove for reverser
  72. const rvb = 15 - mb;
  73. for (i = 0; i < s; ++i) {
  74. // ignore 0 lengths
  75. if (cd[i]) {
  76. // num encoding both symbol and bits read
  77. const sv = (i << 4) | cd[i];
  78. // free bits
  79. const r = mb - cd[i];
  80. // start value
  81. let v = le[cd[i] - 1]++ << r;
  82. // m is end value
  83. for (const m = v | ((1 << r) - 1); v <= m; ++v) {
  84. // every 16 bit value starting with the code yields the same result
  85. co[rev[v] >>> rvb] = sv;
  86. }
  87. }
  88. }
  89. }
  90. return co;
  91. });
  92. // fixed length tree
  93. const flt = new u8(286);
  94. for (let i = 0; i < 144; ++i) flt[i] = 8;
  95. for (let i = 144; i < 256; ++i) flt[i] = 9;
  96. for (let i = 256; i < 280; ++i) flt[i] = 7;
  97. for (let i = 280; i < 286; ++i) flt[i] = 8;
  98. // fixed distance tree
  99. const fdt = new u8(30);
  100. for (let i = 0; i < 30; ++i) fdt[i] = 5;
  101. // fixed length map
  102. const flm = hMap(flt, 9, 0), flnm = hMap(flt, 9, 1);
  103. // fixed distance map
  104. const fdm = hMap(fdt, 5, 0), fdnm = hMap(fdt, 5, 1);
  105. // find max of array
  106. const max = (a: Uint8Array | number[]) => {
  107. let m = a[0];
  108. for (let i = 0; i < a.length; ++i) {
  109. if (a[i] > m) m = a[i];
  110. }
  111. return m;
  112. };
  113. // read d, starting at bit p continuing for l bits
  114. const bits = (d: Uint8Array, p: number, l: number) => {
  115. const o = p >>> 3;
  116. return ((d[o] | (d[o + 1] << 8)) >>> (p & 7)) & ((1 << l) - 1);
  117. }
  118. // read d, starting at bit p continuing for at least 16 bits
  119. const bits16 = (d: Uint8Array, p: number) => {
  120. const o = p >>> 3;
  121. return ((d[o] | (d[o + 1] << 8) | (d[o + 2] << 16) | (d[o + 3] << 24)) >>> (p & 7));
  122. }
  123. // expands raw DEFLATE data
  124. const inflate = (dat: Uint8Array, outSize?: number) => {
  125. let buf = outSize && new u8(outSize);
  126. // have to estimate size
  127. const noBuf = !buf;
  128. // Slightly less than 2x - assumes ~60% compression ratio
  129. if (noBuf) buf = new u8((dat.length >>> 2) << 3);
  130. // ensure buffer can fit at least l elements
  131. const cbuf = (l: number) => {
  132. let bl = buf.length;
  133. // need to increase size to fit
  134. if (l > bl) {
  135. // Double or set to necessary, whichever is greater
  136. const nbuf = new u8(Math.max(bl << 1, l));
  137. nbuf.set(buf);
  138. buf = nbuf;
  139. }
  140. }
  141. // last chunk chunktype literal dist lengths lmask dmask
  142. let final = 0, type = 0, hLit = 0, hDist = 0, hcLen = 0, ml = 0, md = 0;
  143. // bitpos bytes
  144. let pos = 0, bt = 0;
  145. // len dist
  146. let lm: Uint16Array, dm: Uint16Array;
  147. while (!final) {
  148. // BFINAL - this is only 1 when last chunk is next
  149. final = bits(dat, pos, 1);
  150. // type: 0 = no compression, 1 = fixed huffman, 2 = dynamic huffman
  151. type = bits(dat, pos + 1, 2);
  152. pos += 3;
  153. if (!type) {
  154. // go to end of byte boundary
  155. if (pos & 7) pos += 8 - (pos & 7);
  156. const s = (pos >>> 3) + 4, l = dat[s - 4] | (dat[s - 3] << 8);
  157. // ensure size
  158. if (noBuf) cbuf(bt + l);
  159. // Copy over uncompressed data
  160. buf.set(dat.subarray(s, s + l), bt);
  161. // Get new bitpos, update byte count
  162. pos = (s + l) << 3, bt += l;
  163. continue;
  164. }
  165. // Make sure the buffer can hold this + the largest possible addition
  166. // maximum chunk size (practically, theoretically infinite) is 2^17;
  167. if (noBuf) cbuf(bt + 131072);
  168. if (type == 1) {
  169. lm = flm;
  170. dm = fdm;
  171. ml = 511;
  172. md = 31;
  173. }
  174. else if (type == 2) {
  175. hLit = bits(dat, pos, 5) + 257;
  176. hDist = bits(dat, pos + 5, 5) + 1;
  177. hcLen = bits(dat, pos + 10, 4) + 4;
  178. pos += 14;
  179. // length+distance tree
  180. const ldt = new u8(hLit + hDist);
  181. // code length tree
  182. const clt = new u8(19);
  183. for (let i = 0; i < hcLen; ++i) {
  184. // use index map to get real code
  185. clt[clim[i]] = bits(dat, pos + i * 3, 3);
  186. }
  187. pos += hcLen * 3;
  188. // code lengths bits
  189. const clb = max(clt);
  190. // code lengths map
  191. const clm = hMap(clt, clb, 0);
  192. for (let i = 0; i < ldt.length;) {
  193. const r = clm[bits(dat, pos, clb)];
  194. // bits read
  195. pos += r & 15;
  196. // symbol
  197. const s = r >>> 4;
  198. // code length to copy
  199. if (s < 16) {
  200. ldt[i++] = s;
  201. } else {
  202. // copy count
  203. let c = 0, n = 0;
  204. if (s == 16) n = 3 + bits(dat, pos, 2), pos += 2, c = ldt[i - 1];
  205. else if (s == 17) n = 3 + bits(dat, pos, 3), pos += 3;
  206. else if (s == 18) n = 11 + bits(dat, pos, 7), pos += 7;
  207. while (n--) ldt[i++] = c;
  208. }
  209. }
  210. // length tree distance tree
  211. const lt = ldt.subarray(0, hLit), dt = ldt.subarray(hLit);
  212. // max length bits
  213. const mlb = max(lt)
  214. // max dist bits
  215. const mdb = max(dt);
  216. ml = (1 << mlb) - 1;
  217. lm = hMap(lt, mlb, 0);
  218. md = (1 << mdb) - 1;
  219. dm = hMap(dt, mdb, 0);
  220. }
  221. for (;;) {
  222. // bits read, code
  223. const c = lm[bits16(dat, pos) & ml];
  224. pos += c & 15;
  225. // code
  226. const sym = c >>> 4;
  227. if (sym < 256) buf[bt++] = sym;
  228. else if (sym == 256) break;
  229. else {
  230. let end = bt + sym - 254;
  231. // no extra bits needed if less
  232. if (sym > 264) {
  233. // index
  234. const i = sym - 257;
  235. end = bt + bits(dat, pos, fleb[i]) + fl[i];
  236. pos += fleb[i];
  237. }
  238. // dist
  239. const d = dm[bits16(dat, pos) & md];
  240. pos += d & 15;
  241. const dsym = d >>> 4;
  242. let dt = fd[dsym];
  243. if (dsym > 3) {
  244. dt += bits16(dat, pos) & ((1 << fdeb[dsym]) - 1);
  245. pos += fdeb[dsym];
  246. }
  247. if (noBuf) cbuf(bt + 131072);
  248. while (bt < end) {
  249. buf[bt] = buf[bt++ - dt];
  250. buf[bt] = buf[bt++ - dt];
  251. buf[bt] = buf[bt++ - dt];
  252. buf[bt] = buf[bt++ - dt];
  253. }
  254. bt = end;
  255. }
  256. }
  257. }
  258. return buf.slice(0, bt);
  259. }
  260. // starting at p, write the minimum number of bits that can hold v to ds
  261. const wbits = (d: Uint8Array, p: number, v: number) => {
  262. v <<= p & 7;
  263. const o = p >>> 3;
  264. d[o] |= v;
  265. d[o + 1] |= v >>> 8;
  266. }
  267. // starting at p, write the minimum number of bits (>8) that can hold v to ds
  268. const wbits16 = (d: Uint8Array, p: number, v: number) => {
  269. v <<= p & 7;
  270. const o = p >>> 3;
  271. d[o] |= v;
  272. d[o + 1] |= v >>> 8;
  273. d[o + 2] |= v >>> 16;
  274. }
  275. type HuffNode = {
  276. // symbol
  277. s: number;
  278. // frequency
  279. f: number;
  280. // left child
  281. l?: HuffNode;
  282. // right child
  283. r?: HuffNode;
  284. };
  285. // creates code lengths from a frequency table
  286. const hTree = (d: Uint16Array, mb: number) => {
  287. // Need extra info to make a tree
  288. const t: HuffNode[] = [];
  289. for (let i = 0; i < d.length; ++i) {
  290. if (d[i]) {
  291. t.push({ s: i, f: d[i] });
  292. }
  293. }
  294. const s = t.length;
  295. const t2 = t.slice();
  296. // after i2 reaches last ind, will be stopped
  297. t.push({ s: -1, f: 32768 });
  298. if (s == 0) return [new u8(0), 0] as const;
  299. if (s == 1) return [new u8([!t[0].s as unknown as number]), 1] as const;
  300. t.sort((a, b) => a.f - b.f);
  301. let l = t[0], r = t[1], i0 = 0, i1 = 1, i2 = 2;
  302. t[0] = { s: -1, f: l.f + r.f, l, r };
  303. // complex algorithm from UZIP.js
  304. // i0 is lookbehind, i2 is lookahead - after processing two low-freq
  305. // symbols that combined have high freq, will start processing i2 (high-freq,
  306. // non-composite) symbols instead
  307. // see https://reddit.com/r/photopea/comments/ikekht/uzipjs_questions/
  308. while (i1 != s - 1) {
  309. if (t[i0].f < t[i2].f) l = t[i0++];
  310. else l = t[i2++];
  311. if (i0 != i1 && t[i0].f < t[i2].f) r = t[i0++];
  312. else r = t[i2++];
  313. t[i1++] = { s: -1, f: l.f + r.f, l, r };
  314. }
  315. let maxSym = t2[0].s;
  316. for (let i = 0; i < s; ++i) {
  317. if (t2[i].s > maxSym) maxSym = t2[i].s;
  318. }
  319. // code lengths
  320. const tr = new u16(maxSym + 1);
  321. // max bits in tree
  322. let mbt = ln(t[i1 - 1], tr, 0);
  323. if (mbt > mb) {
  324. // more algorithms from UZIP.js
  325. // TODO: find out how this code works (debt)
  326. // ind debt
  327. let i = 0, dt = 0;
  328. // cost
  329. const cst = 1 << (mbt - mb);
  330. t2.sort((a, b) => tr[b.s] - tr[a.s] || a.f - b.f);
  331. for (; i < s; ++i) {
  332. const i2 = t2[i].s;
  333. if (tr[i2] > mb) {
  334. dt += cst - (1 << (mbt - tr[i2]));
  335. tr[i2] = mb;
  336. } else break;
  337. }
  338. dt >>>= (mbt - mb);
  339. while (dt > 0) {
  340. const i2 = t2[i].s;
  341. if (tr[i2] < mb) dt -= 1 << (mb - tr[i2]++ - 1);
  342. else ++i;
  343. }
  344. for (; i >= 0 && !dt; --i) {
  345. const i2 = t2[i].s;
  346. if (tr[i2] == mb) {
  347. --tr[i2];
  348. ++dt;
  349. }
  350. }
  351. mbt = mb;
  352. }
  353. return [new u8(tr), mbt] as const;
  354. }
  355. // get the max length and assign length codes
  356. const ln = (n: HuffNode, l: Uint16Array, d: number): number => {
  357. return n.s == -1
  358. ? Math.max(ln(n.l, l, d + 1), ln(n.r, l, d + 1))
  359. : (l[n.s] = d);
  360. }
  361. // length codes generation
  362. const lc = (c: Uint8Array) => {
  363. let s = c.length;
  364. // Note that the semicolon was intentional
  365. while (s && !c[--s]);
  366. ++s;
  367. const cl = new u16(s);
  368. // ind num streak
  369. let cli = 0, cln = c[0], cls = 1;
  370. const w = (v: number) => { cl[cli++] = v; }
  371. for (let i = 1; i < s; ++i) {
  372. if (c[i] == cln && i != s - 1)
  373. ++cls;
  374. else {
  375. if (!cln && cls > 3) {
  376. for (; cls > 138; cls -= 138) w(4082);
  377. if (cls > 3) {
  378. w(cls > 10 ? ((cls - 11) << 5) | 18 : ((cls - 3) << 5) | 17);
  379. cls = 0;
  380. }
  381. } else if (cls > 4) {
  382. w(cln), --cls;
  383. for (; cls > 6; cls -= 6) w(112);
  384. if (cls > 3) w(((cls - 3) << 5) | 16), cls = 0;
  385. }
  386. cl.fill(cln, cli, cli += cls);
  387. cls = 1;
  388. cln = c[i];
  389. }
  390. }
  391. w(cln);
  392. return [cl.slice(0, cli), s] as const;
  393. }
  394. // calculate the length of output from tree, code lengths
  395. const clen = (cf: Uint16Array, cl: Uint8Array) => {
  396. let l = 0;
  397. for (let i = 0; i < cl.length; ++i) l += cf[i] * cl[i];
  398. return l;
  399. }
  400. // writes a fixed block
  401. // returns the new bit pos
  402. const wfblk = (out: Uint8Array, pos: number, dat: Uint8Array) => {
  403. // no need to write 00 as type: TypedArray defaults to 0
  404. const s = dat.length;
  405. const o = (pos + 2) >>> 3;
  406. out[o + 1] = s & 255;
  407. out[o + 2] = s >>> 8;
  408. out[o + 3] = out[o + 1] ^ 255;
  409. out[o + 4] = out[o + 2] ^ 255;
  410. out.set(dat, o + 5);
  411. return (o + 4 + s) << 3;
  412. }
  413. // writes a block
  414. const wblk = (dat: Uint8Array, out: Uint8Array, final: number, syms: Uint32Array, lf: Uint16Array, df: Uint16Array, eb: number, li: number, bs: number, bl: number, p: number) => {
  415. wbits(out, p++, final);
  416. ++lf[256];
  417. const [dlt, mlb] = hTree(lf, 15);
  418. const [ddt, mdb] = hTree(df, 15);
  419. const [lclt, nlc] = lc(dlt);
  420. const [lcdt, ndc] = lc(ddt);
  421. const lcfreq = new u16(19);
  422. for (let i = 0; i < lclt.length; ++i) lcfreq[lclt[i] & 31]++;
  423. for (let i = 0; i < lcdt.length; ++i) lcfreq[lcdt[i] & 31]++;
  424. const [lct, mlcb] = hTree(lcfreq, 7);
  425. let nlcc = 19;
  426. for (; nlcc > 4 && !lct[clim[nlcc - 1]]; --nlcc);
  427. const flen = (bl + 5) << 3;
  428. const ftlen = clen(lf, flt) + clen(df, fdt) + eb;
  429. const dtlen = clen(lf, dlt) + clen(df, ddt) + eb + 14 + 3 * nlcc + clen(lcfreq, lct) + (2 * lcfreq[16] + 3 * lcfreq[17] + 7 * lcfreq[18]);
  430. if (flen < ftlen && flen < dtlen) return wfblk(out, p, dat.subarray(bs, bs + bl));
  431. let lm: Uint16Array, ll: Uint8Array, dm: Uint16Array, dl: Uint8Array;
  432. wbits(out, p, 1 + (dtlen < ftlen as unknown as number)), p += 2;
  433. if (dtlen < ftlen) {
  434. lm = hMap(dlt, mlb, 1), ll = dlt, dm = hMap(ddt, mdb, 1), dl = ddt;
  435. const llm = hMap(lct, mlcb, 1);
  436. wbits(out, p, nlc - 257);
  437. wbits(out, p + 5, ndc - 1);
  438. wbits(out, p + 10, nlcc - 4);
  439. p += 14;
  440. for (let i = 0; i < nlcc; ++i) wbits(out, p + 3 * i, lct[clim[i]]);
  441. p += 3 * nlcc;
  442. const lcts = [lclt, lcdt];
  443. for (let it = 0; it < 2; ++it) {
  444. const clct = lcts[it];
  445. for (let i = 0; i < clct.length; ++i) {
  446. const len = clct[i] & 31;
  447. wbits(out, p, llm[len]), p += lct[len];
  448. if (len > 15) {
  449. wbits(out, p, clct[i] >>> 5), p += len == 16 ? 2 : len == 17 ? 3 : 7;
  450. }
  451. }
  452. }
  453. } else {
  454. lm = flnm, ll = flt, dm = fdnm, dl = fdt;
  455. }
  456. for (let i = 0; i < li; ++i) {
  457. if (syms[i] > 255) {
  458. const len = syms[i] & 31;
  459. wbits16(out, p, lm[len + 257]), p += ll[len + 257];
  460. if (len > 7) wbits(out, p, (syms[i] >>> 5) & 31), p += fleb[len];
  461. const dst = (syms[i] >>> 10) & 31;
  462. wbits16(out, p, dm[dst]), p += dl[dst];
  463. if (dst > 3) wbits16(out, p, (syms[i] >>> 15) & 8191), p += fdeb[dst];
  464. } else {
  465. wbits16(out, p, lm[syms[i]]), p += ll[syms[i]];
  466. }
  467. }
  468. wbits16(out, p, lm[256]);
  469. return p + ll[256];
  470. }
  471. // deflate options (nice << 13) | chain
  472. const deo = new u32([65540, 131080, 131088, 131104, 262176, 1048704, 1048832, 2114560, 2117632]);
  473. // compresses data into a raw DEFLATE buffer
  474. const deflate = (dat: Uint8Array, lvl: number, pre = 0, post = 0) => {
  475. const s = dat.length;
  476. const o = new u8(pre + s + 5 * Math.ceil(s / 16384) + post);
  477. // writing to this writes to the output buffer
  478. const w = o.subarray(pre, o.length - post);
  479. if (!lvl || dat.length < 4) {
  480. for (let i = 0, pos = 0; i < s; i += 65535) {
  481. // end
  482. const e = i + 65535;
  483. if (e < s) {
  484. // write full block
  485. pos = wfblk(w, pos, dat.subarray(i, e));
  486. } else {
  487. // write final block
  488. w[i] = 1;
  489. wfblk(w, pos, dat.subarray(i, s));
  490. }
  491. }
  492. return o;
  493. }
  494. const opt = deo[lvl - 1];
  495. const n = opt >>> 13, c = opt & 8191;
  496. // prev 2-byte val map curr 2-byte val map
  497. const prev = new u16(32768), head = new u16(32768);
  498. // 12288 is an arbitrary choice for max num of symbols per block
  499. // 112 extra to never need to create a tiny huffman block near the end
  500. const syms = new u32(12400);
  501. // length/literal freq distance freq
  502. const lf = new u16(286), df = new u16(30);
  503. // punishment for missing a value
  504. const pnsh = Math.floor(lvl / 2)
  505. // l/lcnt exbits index l/lind waitdx bitpos
  506. let lc = 0, eb = 0, i = 0, li = 0, wi = 0, bs = 0, pos = 0;
  507. for (; i < s; ++i) {
  508. // first 2 bytes
  509. const b2 = dat[i] | (dat[i + 1] << 8);
  510. // index mod 32768
  511. let imod = i & 32767;
  512. // previous index with this value
  513. let pimod = head[b2];
  514. prev[imod] = pimod;
  515. head[b2] = imod;
  516. // We always should modify head and prev, but only add symbols if
  517. // this data is not yet processed ("wait" for wait index)
  518. if (wi <= i) {
  519. // 24573 arbitrary: 24576 - 3
  520. if ((li > 12288 || lc > 24573) && s - i > 111) {
  521. pos = wblk(dat, w, 0, syms, lf, df, eb, li, bs, i - bs, pos);
  522. li = lc = eb = 0, bs = i;
  523. for (let j = 0; j < 286; ++j) lf[j] = 0;
  524. for (let j = 0; j < 30; ++j) df[j] = 0;
  525. }
  526. // bytes remaining
  527. const rem = s - i;
  528. // len dist chain
  529. let l = 2, d = 0, ch = c, dif = (imod - pimod + 32768) & 32767;
  530. const maxn = Math.min(n, rem);
  531. const maxd = Math.min(32767, i);
  532. // max possible max length
  533. const ml = Math.min(258, rem);
  534. while (dif <= maxd && --ch && imod != pimod) {
  535. if (dat[i + l] == dat[i + l - dif]) {
  536. let nl = 0;
  537. // const ml = Math.min(mml, dif);
  538. for (; nl < ml && dat[i + nl] == dat[i + nl - dif]; ++nl);
  539. if (nl > l) {
  540. l = nl;
  541. d = dif;
  542. // break out early when we reach "nice" (we are satisfied enough)
  543. if (nl >= maxn) break;
  544. // now, find the rarest 2-byte sequence within this
  545. // length of literals and search for that instead.
  546. // Much faster than just using the start
  547. const mmd = nl - 2;
  548. let md = 0;
  549. for (let j = 0; j < mmd; ++j) {
  550. const ti = (i - dif + j + 32768) & 32767;
  551. const pti = prev[ti];
  552. const cd = (ti - pti + 32768) & 32767;
  553. if (cd > md) md = cd, pimod = ti;
  554. }
  555. } else if (nl < 2) ch >>>= pnsh; // this is cheating, but we need performance :/
  556. }
  557. // check the previous match
  558. imod = pimod, pimod = prev[pimod];
  559. dif += (imod - pimod + 32768) & 32767;
  560. }
  561. // d will be nonzero only when a match was found
  562. if (d) {
  563. // store both dist and len data in one Uint32
  564. // Make sure this is recognized as a len/dist with 28th bit (2^28)
  565. syms[li++] = 268435456 | (revfd[d] << 10) | revfl[l];
  566. const lin = revfl[l] & 31, din = revfd[d] & 31;
  567. eb += fleb[lin] + fdeb[din];
  568. ++lf[257 + lin];
  569. ++df[din];
  570. wi = i + l;
  571. } else {
  572. syms[li++] = dat[i];
  573. ++lf[dat[i]];
  574. }
  575. ++lc;
  576. }
  577. }
  578. if (bs != i) pos = wblk(dat, w, 1, syms, lf, df, eb, li, bs, i - bs, pos);
  579. return o.subarray(0, (pos >>> 3) + 1 + post);
  580. }
  581. export { inflate, deflate };