This commit is contained in:
freedakgmail
2025-11-22 23:49:24 +08:00
parent b83382b604
commit c033e46782
3580 changed files with 1745279 additions and 2428 deletions
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 Photopea
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+70
View File
@@ -0,0 +1,70 @@
# UZIP.js
Simple, tiny and fast ZIP library. It has our own DEFLATE compressor and decompressor (alternative to pako.js / ZLIB). It was made from scratch, without using existing implemetnations.
UZIP.js is faster than pako.js
- Inflate (decompression): 40% faster than Pako in Chrome, up to 50% faster in Firefox
- Deflate (compression) is almost always faster
- May produce smaller files than pako.js / ZLIB level 9 (especially for hard to compress data)
## Installation
**Web**: Add the `UZIP.js` script to your webpage:
```html
<script src="UZIP.js"></script>
```
**NodeJS**: Install the [`uzip` package](https://www.npmjs.com/package/uzip):
```
npm install uzip
```
## Interface
#### `UZIP.parse(buff)`
* `buff`: ArrayBuffer of the ZIP file
* returns an object with `key : property` pairs, where `key` is a file name (String), and `property` is a file (Uint8Array)
#### `UZIP.encode(obj)`
* `obj`: object with `key : property` pairs (see above)
* returns a ArrayBuffer of the ZIP file
Directories should be "included" inside file names.
```js
var obj = { "file.txt":new Uint8Array([72,69,76,76,79]), "dir/photo.jpg":..., "dir/pic.png":... };
var zip = UZIP.encode(obj);
```
## Deflate compression
The API is the same as the API of pako.js, just use `UZIP.xyz...` instead of `pako.xyz...`.
#### `UZIP.deflateRaw(buff)`
* `buff`: Uint8Array of the original file
* returns Uint8Array with DEFLATE stream
#### `UZIP.deflate(buff)`
* `buff`: Uint8Array of the original file
* returns Uint8Array with ZLIB stream (2 byte header + DEFLATE stream + 4 byte checksum)
These two functions have an optional third parameter: Options object,
which can be `{level:L}`, where L is the level of compression (0 to 9).
#### `UZIP.inflateRaw(buff)`
* `buff`: Uint8Array containing the deflate stream
* returns Uint8Array with decompressed bytes
#### `UZIP.inflate(buff)`
* `buff`: Uint8Array containing the ZLIB stream
* returns Uint8Array with decompressed bytes
These two functions have an optional third parameter: Output buffer (Uint8Array).
DEFLATE or ZLIB stream do not directly store the size of the output uncompressed data. Decompressors usually write the result into a small array, which is enlarged (copied into a bigger array) during the process.
Practical applications of DEFLATE (like ZIP or PNG files) usually store the size of uncompressed data. If you provide the output buffer, decompression is faster (no need for gradual enlarging of the output array).
+830
View File
@@ -0,0 +1,830 @@
var UZIP = {};
if(typeof module == "object") module.exports = UZIP;
UZIP["parse"] = function(buf, onlyNames) // ArrayBuffer
{
var rUs = UZIP.bin.readUshort, rUi = UZIP.bin.readUint, o = 0, out = {};
var data = new Uint8Array(buf);
var eocd = data.length-4;
while(rUi(data, eocd)!=0x06054b50) eocd--;
var o = eocd;
o+=4; // sign = 0x06054b50
o+=4; // disks = 0;
var cnu = rUs(data, o); o+=2;
var cnt = rUs(data, o); o+=2;
var csize = rUi(data, o); o+=4;
var coffs = rUi(data, o); o+=4;
o = coffs;
for(var i=0; i<cnu; i++)
{
var sign = rUi(data, o); o+=4;
o += 4; // versions;
o += 4; // flag + compr
o += 4; // time
var crc32 = rUi(data, o); o+=4;
var csize = rUi(data, o); o+=4;
var usize = rUi(data, o); o+=4;
var nl = rUs(data, o), el = rUs(data, o+2), cl = rUs(data, o+4); o += 6; // name, extra, comment
o += 8; // disk, attribs
var roff = rUi(data, o); o+=4;
o += nl + el + cl;
UZIP._readLocal(data, roff, out, csize, usize, onlyNames);
}
//console.log(out);
return out;
}
UZIP._readLocal = function(data, o, out, csize, usize, onlyNames)
{
var rUs = UZIP.bin.readUshort, rUi = UZIP.bin.readUint;
var sign = rUi(data, o); o+=4;
var ver = rUs(data, o); o+=2;
var gpflg = rUs(data, o); o+=2;
//if((gpflg&8)!=0) throw "unknown sizes";
var cmpr = rUs(data, o); o+=2;
var time = rUi(data, o); o+=4;
var crc32 = rUi(data, o); o+=4;
//var csize = rUi(data, o); o+=4;
//var usize = rUi(data, o); o+=4;
o+=8;
var nlen = rUs(data, o); o+=2;
var elen = rUs(data, o); o+=2;
var name = UZIP.bin.readUTF8(data, o, nlen); o+=nlen; //console.log(name);
o += elen;
//console.log(sign.toString(16), ver, gpflg, cmpr, crc32.toString(16), "csize, usize", csize, usize, nlen, elen, name, o);
if(onlyNames) { out[name]={size:usize, csize:csize}; return; }
var file = new Uint8Array(data.buffer, o);
if(false) {}
else if(cmpr==0) out[name] = new Uint8Array(file.buffer.slice(o, o+csize));
else if(cmpr==8) {
var buf = new Uint8Array(usize); UZIP.inflateRaw(file, buf);
/*var nbuf = pako["inflateRaw"](file);
if(usize>8514000) {
//console.log(PUtils.readASCII(buf , 8514500, 500));
//console.log(PUtils.readASCII(nbuf, 8514500, 500));
}
for(var i=0; i<buf.length; i++) if(buf[i]!=nbuf[i]) { console.log(buf.length, nbuf.length, usize, i); throw "e"; }
*/
out[name] = buf;
}
else throw "unknown compression method: "+cmpr;
}
UZIP.inflateRaw = function(file, buf) { return UZIP.F.inflate(file, buf); }
UZIP.inflate = function(file, buf) {
var CMF = file[0], FLG = file[1];
var CM = (CMF&15), CINFO = (CMF>>>4);
//console.log(CM, CINFO,CMF,FLG);
return UZIP.inflateRaw(new Uint8Array(file.buffer, file.byteOffset+2, file.length-6), buf);
}
UZIP.deflate = function(data, opts/*, buf, off*/) {
if(opts==null) opts={level:6};
var off=0, buf=new Uint8Array(50+Math.floor(data.length*1.1));
buf[off]=120; buf[off+1]=156; off+=2;
off = UZIP.F.deflateRaw(data, buf, off, opts.level);
var crc = UZIP.adler(data, 0, data.length);
buf[off+0]=((crc>>>24)&255);
buf[off+1]=((crc>>>16)&255);
buf[off+2]=((crc>>> 8)&255);
buf[off+3]=((crc>>> 0)&255);
return new Uint8Array(buf.buffer, 0, off+4);
}
UZIP.deflateRaw = function(data, opts) {
if(opts==null) opts={level:6};
var buf=new Uint8Array(50+Math.floor(data.length*1.1));
var off = UZIP.F.deflateRaw(data, buf, off, opts.level);
return new Uint8Array(buf.buffer, 0, off);
}
UZIP.encode = function(obj, noCmpr) {
if(noCmpr==null) noCmpr=false;
var tot = 0, wUi = UZIP.bin.writeUint, wUs = UZIP.bin.writeUshort;
var zpd = {};
for(var p in obj) { var cpr = !UZIP._noNeed(p) && !noCmpr, buf = obj[p], crc = UZIP.crc.crc(buf,0,buf.length);
zpd[p] = { cpr:cpr, usize:buf.length, crc:crc, file: (cpr ? UZIP.deflateRaw(buf) : buf) }; }
for(var p in zpd) tot += zpd[p].file.length + 30 + 46 + 2*UZIP.bin.sizeUTF8(p);
tot += 22;
var data = new Uint8Array(tot), o = 0;
var fof = []
for(var p in zpd) {
var file = zpd[p]; fof.push(o);
o = UZIP._writeHeader(data, o, p, file, 0);
}
var i=0, ioff = o;
for(var p in zpd) {
var file = zpd[p]; fof.push(o);
o = UZIP._writeHeader(data, o, p, file, 1, fof[i++]);
}
var csize = o-ioff;
wUi(data, o, 0x06054b50); o+=4;
o += 4; // disks
wUs(data, o, i); o += 2;
wUs(data, o, i); o += 2; // number of c d records
wUi(data, o, csize); o += 4;
wUi(data, o, ioff ); o += 4;
o += 2;
return data.buffer;
}
// no need to compress .PNG, .ZIP, .JPEG ....
UZIP._noNeed = function(fn) { var ext = fn.split(".").pop().toLowerCase(); return "png,jpg,jpeg,zip".indexOf(ext)!=-1; }
UZIP._writeHeader = function(data, o, p, obj, t, roff)
{
var wUi = UZIP.bin.writeUint, wUs = UZIP.bin.writeUshort;
var file = obj.file;
wUi(data, o, t==0 ? 0x04034b50 : 0x02014b50); o+=4; // sign
if(t==1) o+=2; // ver made by
wUs(data, o, 20); o+=2; // ver
wUs(data, o, 0); o+=2; // gflip
wUs(data, o, obj.cpr?8:0); o+=2; // cmpr
wUi(data, o, 0); o+=4; // time
wUi(data, o, obj.crc); o+=4; // crc32
wUi(data, o, file.length); o+=4; // csize
wUi(data, o, obj.usize); o+=4; // usize
wUs(data, o, UZIP.bin.sizeUTF8(p)); o+=2; // nlen
wUs(data, o, 0); o+=2; // elen
if(t==1) {
o += 2; // comment length
o += 2; // disk number
o += 6; // attributes
wUi(data, o, roff); o+=4; // usize
}
var nlen = UZIP.bin.writeUTF8(data, o, p); o+= nlen;
if(t==0) { data.set(file, o); o += file.length; }
return o;
}
UZIP.crc = {
table : ( function() {
var tab = new Uint32Array(256);
for (var n=0; n<256; n++) {
var c = n;
for (var k=0; k<8; k++) {
if (c & 1) c = 0xedb88320 ^ (c >>> 1);
else c = c >>> 1;
}
tab[n] = c; }
return tab; })(),
update : function(c, buf, off, len) {
for (var i=0; i<len; i++) c = UZIP.crc.table[(c ^ buf[off+i]) & 0xff] ^ (c >>> 8);
return c;
},
crc : function(b,o,l) { return UZIP.crc.update(0xffffffff,b,o,l) ^ 0xffffffff; }
}
UZIP.adler = function(data,o,len) {
var a = 1, b = 0;
var off = o, end=o+len;
while(off<end) {
var eend = Math.min(off+5552, end);
while(off<eend) {
a += data[off++];
b += a;
}
a=a%65521;
b=b%65521;
}
return (b << 16) | a;
}
UZIP.bin = {
readUshort : function(buff,p) { return (buff[p]) | (buff[p+1]<<8); },
writeUshort: function(buff,p,n){ buff[p] = (n)&255; buff[p+1] = (n>>8)&255; },
readUint : function(buff,p) { return (buff[p+3]*(256*256*256)) + ((buff[p+2]<<16) | (buff[p+1]<< 8) | buff[p]); },
writeUint : function(buff,p,n){ buff[p]=n&255; buff[p+1]=(n>>8)&255; buff[p+2]=(n>>16)&255; buff[p+3]=(n>>24)&255; },
readASCII : function(buff,p,l){ var s = ""; for(var i=0; i<l; i++) s += String.fromCharCode(buff[p+i]); return s; },
writeASCII : function(data,p,s){ for(var i=0; i<s.length; i++) data[p+i] = s.charCodeAt(i); },
pad : function(n) { return n.length < 2 ? "0" + n : n; },
readUTF8 : function(buff, p, l) {
var s = "", ns;
for(var i=0; i<l; i++) s += "%" + UZIP.bin.pad(buff[p+i].toString(16));
try { ns = decodeURIComponent(s); }
catch(e) { return UZIP.bin.readASCII(buff, p, l); }
return ns;
},
writeUTF8 : function(buff, p, str) {
var strl = str.length, i=0;
for(var ci=0; ci<strl; ci++)
{
var code = str.charCodeAt(ci);
if ((code&(0xffffffff-(1<< 7)+1))==0) { buff[p+i] = ( code ); i++; }
else if((code&(0xffffffff-(1<<11)+1))==0) { buff[p+i] = (192|(code>> 6)); buff[p+i+1] = (128|((code>> 0)&63)); i+=2; }
else if((code&(0xffffffff-(1<<16)+1))==0) { buff[p+i] = (224|(code>>12)); buff[p+i+1] = (128|((code>> 6)&63)); buff[p+i+2] = (128|((code>>0)&63)); i+=3; }
else if((code&(0xffffffff-(1<<21)+1))==0) { buff[p+i] = (240|(code>>18)); buff[p+i+1] = (128|((code>>12)&63)); buff[p+i+2] = (128|((code>>6)&63)); buff[p+i+3] = (128|((code>>0)&63)); i+=4; }
else throw "e";
}
return i;
},
sizeUTF8 : function(str) {
var strl = str.length, i=0;
for(var ci=0; ci<strl; ci++)
{
var code = str.charCodeAt(ci);
if ((code&(0xffffffff-(1<< 7)+1))==0) { i++ ; }
else if((code&(0xffffffff-(1<<11)+1))==0) { i+=2; }
else if((code&(0xffffffff-(1<<16)+1))==0) { i+=3; }
else if((code&(0xffffffff-(1<<21)+1))==0) { i+=4; }
else throw "e";
}
return i;
}
}
UZIP.F = {};
UZIP.F.deflateRaw = function(data, out, opos, lvl) {
var opts = [
/*
ush good_length; /* reduce lazy search above this match length
ush max_lazy; /* do not perform lazy search above this match length
ush nice_length; /* quit search above this match length
*/
/* good lazy nice chain */
/* 0 */ [ 0, 0, 0, 0,0], /* store only */
/* 1 */ [ 4, 4, 8, 4,0], /* max speed, no lazy matches */
/* 2 */ [ 4, 5, 16, 8,0],
/* 3 */ [ 4, 6, 16, 16,0],
/* 4 */ [ 4, 10, 16, 32,0], /* lazy matches */
/* 5 */ [ 8, 16, 32, 32,0],
/* 6 */ [ 8, 16, 128, 128,0],
/* 7 */ [ 8, 32, 128, 256,0],
/* 8 */ [32, 128, 258, 1024,1],
/* 9 */ [32, 258, 258, 4096,1]]; /* max compression */
var opt = opts[lvl];
var U = UZIP.F.U, goodIndex = UZIP.F._goodIndex, hash = UZIP.F._hash, putsE = UZIP.F._putsE;
var i = 0, pos = opos<<3, cvrd = 0, dlen = data.length;
if(lvl==0) {
while(i<dlen) { var len = Math.min(0xffff, dlen-i);
putsE(out, pos, (i+len==dlen ? 1 : 0)); pos = UZIP.F._copyExact(data, i, len, out, pos+8); i += len; }
return pos>>>3;
}
var lits = U.lits, strt=U.strt, prev=U.prev, li=0, lc=0, bs=0, ebits=0, c=0, nc=0; // last_item, literal_count, block_start
if(dlen>2) { nc=UZIP.F._hash(data,0); strt[nc]=0; }
var nmch=0,nmci=0;
for(i=0; i<dlen; i++) {
c = nc;
//*
if(i+1<dlen-2) {
nc = UZIP.F._hash(data, i+1);
var ii = ((i+1)&0x7fff);
prev[ii]=strt[nc];
strt[nc]=ii;
} //*/
if(cvrd<=i) {
if((li>14000 || lc>26697) && (dlen-i)>100) {
if(cvrd<i) { lits[li]=i-cvrd; li+=2; cvrd=i; }
pos = UZIP.F._writeBlock(((i==dlen-1) || (cvrd==dlen))?1:0, lits, li, ebits, data,bs,i-bs, out, pos); li=lc=ebits=0; bs=i;
}
var mch = 0;
//if(nmci==i) mch= nmch; else
if(i<dlen-2) mch = UZIP.F._bestMatch(data, i, prev, c, Math.min(opt[2],dlen-i), opt[3]);
/*
if(mch!=0 && opt[4]==1 && (mch>>>16)<opt[1] && i+1<dlen-2) {
nmch = UZIP.F._bestMatch(data, i+1, prev, nc, opt[2], opt[3]); nmci=i+1;
//var mch2 = UZIP.F._bestMatch(data, i+2, prev, nnc); //nmci=i+1;
if((nmch>>>16)>(mch>>>16)) mch=0;
}//*/
var len = mch>>>16, dst = mch&0xffff; //if(i-dst<0) throw "e";
if(mch!=0) {
var len = mch>>>16, dst = mch&0xffff; //if(i-dst<0) throw "e";
var lgi = goodIndex(len, U.of0); U.lhst[257+lgi]++;
var dgi = goodIndex(dst, U.df0); U.dhst[ dgi]++; ebits += U.exb[lgi] + U.dxb[dgi];
lits[li] = (len<<23)|(i-cvrd); lits[li+1] = (dst<<16)|(lgi<<8)|dgi; li+=2;
cvrd = i + len;
}
else { U.lhst[data[i]]++; }
lc++;
}
}
if(bs!=i || data.length==0) {
if(cvrd<i) { lits[li]=i-cvrd; li+=2; cvrd=i; }
pos = UZIP.F._writeBlock(1, lits, li, ebits, data,bs,i-bs, out, pos); li=0; lc=0; li=lc=ebits=0; bs=i;
}
while((pos&7)!=0) pos++;
return pos>>>3;
}
UZIP.F._bestMatch = function(data, i, prev, c, nice, chain) {
var ci = (i&0x7fff), pi=prev[ci];
//console.log("----", i);
var dif = ((ci-pi + (1<<15)) & 0x7fff); if(pi==ci || c!=UZIP.F._hash(data,i-dif)) return 0;
var tl=0, td=0; // top length, top distance
var dlim = Math.min(0x7fff, i);
while(dif<=dlim && --chain!=0 && pi!=ci /*&& c==UZIP.F._hash(data,i-dif)*/) {
if(tl==0 || (data[i+tl]==data[i+tl-dif])) {
var cl = UZIP.F._howLong(data, i, dif);
if(cl>tl) {
tl=cl; td=dif; if(tl>=nice) break; //*
if(dif+2<cl) cl = dif+2;
var maxd = 0; // pi does not point to the start of the word
for(var j=0; j<cl-2; j++) {
var ei = (i-dif+j+ (1<<15)) & 0x7fff;
var li = prev[ei];
var curd = (ei-li + (1<<15)) & 0x7fff;
if(curd>maxd) { maxd=curd; pi = ei; }
} //*/
}
}
ci=pi; pi = prev[ci];
dif += ((ci-pi + (1<<15)) & 0x7fff);
}
return (tl<<16)|td;
}
UZIP.F._howLong = function(data, i, dif) {
if(data[i]!=data[i-dif] || data[i+1]!=data[i+1-dif] || data[i+2]!=data[i+2-dif]) return 0;
var oi=i, l = Math.min(data.length, i+258); i+=3;
//while(i+4<l && data[i]==data[i-dif] && data[i+1]==data[i+1-dif] && data[i+2]==data[i+2-dif] && data[i+3]==data[i+3-dif]) i+=4;
while(i<l && data[i]==data[i-dif]) i++;
return i-oi;
}
UZIP.F._hash = function(data, i) {
return (((data[i]<<8) | data[i+1])+(data[i+2]<<4))&0xffff;
//var hash_shift = 0, hash_mask = 255;
//var h = data[i+1] % 251;
//h = (((h << 8) + data[i+2]) % 251);
//h = (((h << 8) + data[i+2]) % 251);
//h = ((h<<hash_shift) ^ (c) ) & hash_mask;
//return h | (data[i]<<8);
//return (data[i] | (data[i+1]<<8));
}
//UZIP.___toth = 0;
UZIP.saved = 0;
UZIP.F._writeBlock = function(BFINAL, lits, li, ebits, data,o0,l0, out, pos) {
var U = UZIP.F.U, putsF = UZIP.F._putsF, putsE = UZIP.F._putsE;
//*
var T, ML, MD, MH, numl, numd, numh, lset, dset; U.lhst[256]++;
T = UZIP.F.getTrees(); ML=T[0]; MD=T[1]; MH=T[2]; numl=T[3]; numd=T[4]; numh=T[5]; lset=T[6]; dset=T[7];
var cstSize = (((pos+3)&7)==0 ? 0 : 8-((pos+3)&7)) + 32 + (l0<<3);
var fxdSize = ebits + UZIP.F.contSize(U.fltree, U.lhst) + UZIP.F.contSize(U.fdtree, U.dhst);
var dynSize = ebits + UZIP.F.contSize(U.ltree , U.lhst) + UZIP.F.contSize(U.dtree , U.dhst);
dynSize += 14 + 3*numh + UZIP.F.contSize(U.itree, U.ihst) + (U.ihst[16]*2 + U.ihst[17]*3 + U.ihst[18]*7);
for(var j=0; j<286; j++) U.lhst[j]=0; for(var j=0; j<30; j++) U.dhst[j]=0; for(var j=0; j<19; j++) U.ihst[j]=0;
//*/
var BTYPE = (cstSize<fxdSize && cstSize<dynSize) ? 0 : ( fxdSize<dynSize ? 1 : 2 );
putsF(out, pos, BFINAL); putsF(out, pos+1, BTYPE); pos+=3;
var opos = pos;
if(BTYPE==0) {
while((pos&7)!=0) pos++;
pos = UZIP.F._copyExact(data, o0, l0, out, pos);
}
else {
var ltree, dtree;
if(BTYPE==1) { ltree=U.fltree; dtree=U.fdtree; }
if(BTYPE==2) {
UZIP.F.makeCodes(U.ltree, ML); UZIP.F.revCodes(U.ltree, ML);
UZIP.F.makeCodes(U.dtree, MD); UZIP.F.revCodes(U.dtree, MD);
UZIP.F.makeCodes(U.itree, MH); UZIP.F.revCodes(U.itree, MH);
ltree = U.ltree; dtree = U.dtree;
putsE(out, pos,numl-257); pos+=5; // 286
putsE(out, pos,numd- 1); pos+=5; // 30
putsE(out, pos,numh- 4); pos+=4; // 19
for(var i=0; i<numh; i++) putsE(out, pos+i*3, U.itree[(U.ordr[i]<<1)+1]); pos+=3* numh;
pos = UZIP.F._codeTiny(lset, U.itree, out, pos);
pos = UZIP.F._codeTiny(dset, U.itree, out, pos);
}
var off=o0;
for(var si=0; si<li; si+=2) {
var qb=lits[si], len=(qb>>>23), end = off+(qb&((1<<23)-1));
while(off<end) pos = UZIP.F._writeLit(data[off++], ltree, out, pos);
if(len!=0) {
var qc = lits[si+1], dst=(qc>>16), lgi=(qc>>8)&255, dgi=(qc&255);
pos = UZIP.F._writeLit(257+lgi, ltree, out, pos);
putsE(out, pos, len-U.of0[lgi]); pos+=U.exb[lgi];
pos = UZIP.F._writeLit(dgi, dtree, out, pos);
putsF(out, pos, dst-U.df0[dgi]); pos+=U.dxb[dgi]; off+=len;
}
}
pos = UZIP.F._writeLit(256, ltree, out, pos);
}
//console.log(pos-opos, fxdSize, dynSize, cstSize);
return pos;
}
UZIP.F._copyExact = function(data,off,len,out,pos) {
var p8 = (pos>>>3);
out[p8]=(len); out[p8+1]=(len>>>8); out[p8+2]=255-out[p8]; out[p8+3]=255-out[p8+1]; p8+=4;
out.set(new Uint8Array(data.buffer, off, len), p8);
//for(var i=0; i<len; i++) out[p8+i]=data[off+i];
return pos + ((len+4)<<3);
}
/*
Interesting facts:
- decompressed block can have bytes, which do not occur in a Huffman tree (copied from the previous block by reference)
*/
UZIP.F.getTrees = function() {
var U = UZIP.F.U;
var ML = UZIP.F._hufTree(U.lhst, U.ltree, 15);
var MD = UZIP.F._hufTree(U.dhst, U.dtree, 15);
var lset = [], numl = UZIP.F._lenCodes(U.ltree, lset);
var dset = [], numd = UZIP.F._lenCodes(U.dtree, dset);
for(var i=0; i<lset.length; i+=2) U.ihst[lset[i]]++;
for(var i=0; i<dset.length; i+=2) U.ihst[dset[i]]++;
var MH = UZIP.F._hufTree(U.ihst, U.itree, 7);
var numh = 19; while(numh>4 && U.itree[(U.ordr[numh-1]<<1)+1]==0) numh--;
return [ML, MD, MH, numl, numd, numh, lset, dset];
}
UZIP.F.getSecond= function(a) { var b=[]; for(var i=0; i<a.length; i+=2) b.push (a[i+1]); return b; }
UZIP.F.nonZero = function(a) { var b= ""; for(var i=0; i<a.length; i+=2) if(a[i+1]!=0)b+=(i>>1)+","; return b; }
UZIP.F.contSize = function(tree, hst) { var s=0; for(var i=0; i<hst.length; i++) s+= hst[i]*tree[(i<<1)+1]; return s; }
UZIP.F._codeTiny = function(set, tree, out, pos) {
for(var i=0; i<set.length; i+=2) {
var l = set[i], rst = set[i+1]; //console.log(l, pos, tree[(l<<1)+1]);
pos = UZIP.F._writeLit(l, tree, out, pos);
var rsl = l==16 ? 2 : (l==17 ? 3 : 7);
if(l>15) { UZIP.F._putsE(out, pos, rst, rsl); pos+=rsl; }
}
return pos;
}
UZIP.F._lenCodes = function(tree, set) {
var len=tree.length; while(len!=2 && tree[len-1]==0) len-=2; // when no distances, keep one code with length 0
for(var i=0; i<len; i+=2) {
var l = tree[i+1], nxt = (i+3<len ? tree[i+3]:-1), nnxt = (i+5<len ? tree[i+5]:-1), prv = (i==0 ? -1 : tree[i-1]);
if(l==0 && nxt==l && nnxt==l) {
var lz = i+5;
while(lz+2<len && tree[lz+2]==l) lz+=2;
var zc = Math.min((lz+1-i)>>>1, 138);
if(zc<11) set.push(17, zc-3);
else set.push(18, zc-11);
i += zc*2-2;
}
else if(l==prv && nxt==l && nnxt==l) {
var lz = i+5;
while(lz+2<len && tree[lz+2]==l) lz+=2;
var zc = Math.min((lz+1-i)>>>1, 6);
set.push(16, zc-3);
i += zc*2-2;
}
else set.push(l, 0);
}
return len>>>1;
}
UZIP.F._hufTree = function(hst, tree, MAXL) {
var list=[], hl = hst.length, tl=tree.length, i=0;
for(i=0; i<tl; i+=2) { tree[i]=0; tree[i+1]=0; }
for(i=0; i<hl; i++) if(hst[i]!=0) list.push({lit:i, f:hst[i]});
var end = list.length, l2=list.slice(0);
if(end==0) return 0; // empty histogram (usually for dist)
if(end==1) { var lit=list[0].lit, l2=lit==0?1:0; tree[(lit<<1)+1]=1; tree[(l2<<1)+1]=1; return 1; }
list.sort(function(a,b){return a.f-b.f;});
var a=list[0], b=list[1], i0=0, i1=1, i2=2; list[0]={lit:-1,f:a.f+b.f,l:a,r:b,d:0};
while(i1!=end-1) {
if(i0!=i1 && (i2==end || list[i0].f<list[i2].f)) { a=list[i0++]; } else { a=list[i2++]; }
if(i0!=i1 && (i2==end || list[i0].f<list[i2].f)) { b=list[i0++]; } else { b=list[i2++]; }
list[i1++]={lit:-1,f:a.f+b.f, l:a,r:b};
}
var maxl = UZIP.F.setDepth(list[i1-1], 0);
if(maxl>MAXL) { UZIP.F.restrictDepth(l2, MAXL, maxl); maxl = MAXL; }
for(i=0; i<end; i++) tree[(l2[i].lit<<1)+1]=l2[i].d;
return maxl;
}
UZIP.F.setDepth = function(t, d) {
if(t.lit!=-1) { t.d=d; return d; }
return Math.max( UZIP.F.setDepth(t.l, d+1), UZIP.F.setDepth(t.r, d+1) );
}
UZIP.F.restrictDepth = function(dps, MD, maxl) {
var i=0, bCost=1<<(maxl-MD), dbt=0;
dps.sort(function(a,b){return b.d==a.d ? a.f-b.f : b.d-a.d;});
for(i=0; i<dps.length; i++) if(dps[i].d>MD) { var od=dps[i].d; dps[i].d=MD; dbt+=bCost-(1<<(maxl-od)); } else break;
dbt = dbt>>>(maxl-MD);
while(dbt>0) { var od=dps[i].d; if(od<MD) { dps[i].d++; dbt-=(1<<(MD-od-1)); } else i++; }
for(; i>=0; i--) if(dps[i].d==MD && dbt<0) { dps[i].d--; dbt++; } if(dbt!=0) console.log("debt left");
}
UZIP.F._goodIndex = function(v, arr) {
var i=0; if(arr[i|16]<=v) i|=16; if(arr[i|8]<=v) i|=8; if(arr[i|4]<=v) i|=4; if(arr[i|2]<=v) i|=2; if(arr[i|1]<=v) i|=1; return i;
}
UZIP.F._writeLit = function(ch, ltree, out, pos) {
UZIP.F._putsF(out, pos, ltree[ch<<1]);
return pos+ltree[(ch<<1)+1];
}
UZIP.F.inflate = function(data, buf) {
var u8=Uint8Array;
if(data[0]==3 && data[1]==0) return (buf ? buf : new u8(0));
var F=UZIP.F, bitsF = F._bitsF, bitsE = F._bitsE, decodeTiny = F._decodeTiny, makeCodes = F.makeCodes, codes2map=F.codes2map, get17 = F._get17;
var U = F.U;
var noBuf = (buf==null);
if(noBuf) buf = new u8((data.length>>>2)<<3);
var BFINAL=0, BTYPE=0, HLIT=0, HDIST=0, HCLEN=0, ML=0, MD=0;
var off = 0, pos = 0;
var lmap, dmap;
while(BFINAL==0) {
BFINAL = bitsF(data, pos , 1);
BTYPE = bitsF(data, pos+1, 2); pos+=3;
//console.log(BFINAL, BTYPE);
if(BTYPE==0) {
if((pos&7)!=0) pos+=8-(pos&7);
var p8 = (pos>>>3)+4, len = data[p8-4]|(data[p8-3]<<8); //console.log(len);//bitsF(data, pos, 16),
if(noBuf) buf=UZIP.F._check(buf, off+len);
buf.set(new u8(data.buffer, data.byteOffset+p8, len), off);
//for(var i=0; i<len; i++) buf[off+i] = data[p8+i];
//for(var i=0; i<len; i++) if(buf[off+i] != data[p8+i]) throw "e";
pos = ((p8+len)<<3); off+=len; continue;
}
if(noBuf) buf=UZIP.F._check(buf, off+(1<<17)); // really not enough in many cases (but PNG and ZIP provide buffer in advance)
if(BTYPE==1) { lmap = U.flmap; dmap = U.fdmap; ML = (1<<9)-1; MD = (1<<5)-1; }
if(BTYPE==2) {
HLIT = bitsE(data, pos , 5)+257;
HDIST = bitsE(data, pos+ 5, 5)+ 1;
HCLEN = bitsE(data, pos+10, 4)+ 4; pos+=14;
var ppos = pos;
for(var i=0; i<38; i+=2) { U.itree[i]=0; U.itree[i+1]=0; }
var tl = 1;
for(var i=0; i<HCLEN; i++) { var l=bitsE(data, pos+i*3, 3); U.itree[(U.ordr[i]<<1)+1] = l; if(l>tl)tl=l; } pos+=3*HCLEN; //console.log(itree);
makeCodes(U.itree, tl);
codes2map(U.itree, tl, U.imap);
lmap = U.lmap; dmap = U.dmap;
pos = decodeTiny(U.imap, (1<<tl)-1, HLIT+HDIST, data, pos, U.ttree);
var mx0 = F._copyOut(U.ttree, 0, HLIT , U.ltree); ML = (1<<mx0)-1;
var mx1 = F._copyOut(U.ttree, HLIT, HDIST, U.dtree); MD = (1<<mx1)-1;
//var ml = decodeTiny(U.imap, (1<<tl)-1, HLIT , data, pos, U.ltree); ML = (1<<(ml>>>24))-1; pos+=(ml&0xffffff);
makeCodes(U.ltree, mx0);
codes2map(U.ltree, mx0, lmap);
//var md = decodeTiny(U.imap, (1<<tl)-1, HDIST, data, pos, U.dtree); MD = (1<<(md>>>24))-1; pos+=(md&0xffffff);
makeCodes(U.dtree, mx1);
codes2map(U.dtree, mx1, dmap);
}
//var ooff=off, opos=pos;
while(true) {
var code = lmap[get17(data, pos) & ML]; pos += code&15;
var lit = code>>>4; //U.lhst[lit]++;
if((lit>>>8)==0) { buf[off++] = lit; }
else if(lit==256) { break; }
else {
var end = off+lit-254;
if(lit>264) { var ebs = U.ldef[lit-257]; end = off + (ebs>>>3) + bitsE(data, pos, ebs&7); pos += ebs&7; }
//UZIP.F.dst[end-off]++;
var dcode = dmap[get17(data, pos) & MD]; pos += dcode&15;
var dlit = dcode>>>4;
var dbs = U.ddef[dlit], dst = (dbs>>>4) + bitsF(data, pos, dbs&15); pos += dbs&15;
//var o0 = off-dst, stp = Math.min(end-off, dst);
//if(stp>20) while(off<end) { buf.copyWithin(off, o0, o0+stp); off+=stp; } else
//if(end-dst<=off) buf.copyWithin(off, off-dst, end-dst); else
//if(dst==1) buf.fill(buf[off-1], off, end); else
if(noBuf) buf=UZIP.F._check(buf, off+(1<<17));
while(off<end) { buf[off]=buf[off++-dst]; buf[off]=buf[off++-dst]; buf[off]=buf[off++-dst]; buf[off]=buf[off++-dst]; }
off=end;
//while(off!=end) { buf[off]=buf[off++-dst]; }
}
}
//console.log(off-ooff, (pos-opos)>>>3);
}
//console.log(UZIP.F.dst);
//console.log(tlen, dlen, off-tlen+tcnt);
return buf.length==off ? buf : buf.slice(0,off);
}
UZIP.F._check=function(buf, len) {
var bl=buf.length; if(len<=bl) return buf;
var nbuf = new Uint8Array(Math.max(bl<<1,len)); nbuf.set(buf,0);
//for(var i=0; i<bl; i+=4) { nbuf[i]=buf[i]; nbuf[i+1]=buf[i+1]; nbuf[i+2]=buf[i+2]; nbuf[i+3]=buf[i+3]; }
return nbuf;
}
UZIP.F._decodeTiny = function(lmap, LL, len, data, pos, tree) {
var bitsE = UZIP.F._bitsE, get17 = UZIP.F._get17;
var i = 0;
while(i<len) {
var code = lmap[get17(data, pos)&LL]; pos+=code&15;
var lit = code>>>4;
if(lit<=15) { tree[i]=lit; i++; }
else {
var ll = 0, n = 0;
if(lit==16) {
n = (3 + bitsE(data, pos, 2)); pos += 2; ll = tree[i-1];
}
else if(lit==17) {
n = (3 + bitsE(data, pos, 3)); pos += 3;
}
else if(lit==18) {
n = (11 + bitsE(data, pos, 7)); pos += 7;
}
var ni = i+n;
while(i<ni) { tree[i]=ll; i++; }
}
}
return pos;
}
UZIP.F._copyOut = function(src, off, len, tree) {
var mx=0, i=0, tl=tree.length>>>1;
while(i<len) { var v=src[i+off]; tree[(i<<1)]=0; tree[(i<<1)+1]=v; if(v>mx)mx=v; i++; }
while(i<tl ) { tree[(i<<1)]=0; tree[(i<<1)+1]=0; i++; }
return mx;
}
UZIP.F.makeCodes = function(tree, MAX_BITS) { // code, length
var U = UZIP.F.U;
var max_code = tree.length;
var code, bits, n, i, len;
var bl_count = U.bl_count; for(var i=0; i<=MAX_BITS; i++) bl_count[i]=0;
for(i=1; i<max_code; i+=2) bl_count[tree[i]]++;
var next_code = U.next_code; // smallest code for each length
code = 0;
bl_count[0] = 0;
for (bits = 1; bits <= MAX_BITS; bits++) {
code = (code + bl_count[bits-1]) << 1;
next_code[bits] = code;
}
for (n = 0; n < max_code; n+=2) {
len = tree[n+1];
if (len != 0) {
tree[n] = next_code[len];
next_code[len]++;
}
}
}
UZIP.F.codes2map = function(tree, MAX_BITS, map) {
var max_code = tree.length;
var U=UZIP.F.U, r15 = U.rev15;
for(var i=0; i<max_code; i+=2) if(tree[i+1]!=0) {
var lit = i>>1;
var cl = tree[i+1], val = (lit<<4)|cl; // : (0x8000 | (U.of0[lit-257]<<7) | (U.exb[lit-257]<<4) | cl);
var rest = (MAX_BITS-cl), i0 = tree[i]<<rest, i1 = i0 + (1<<rest);
//tree[i]=r15[i0]>>>(15-MAX_BITS);
while(i0!=i1) {
var p0 = r15[i0]>>>(15-MAX_BITS);
map[p0]=val; i0++;
}
}
}
UZIP.F.revCodes = function(tree, MAX_BITS) {
var r15 = UZIP.F.U.rev15, imb = 15-MAX_BITS;
for(var i=0; i<tree.length; i+=2) { var i0 = (tree[i]<<(MAX_BITS-tree[i+1])); tree[i] = r15[i0]>>>imb; }
}
// used only in deflate
UZIP.F._putsE= function(dt, pos, val ) { val = val<<(pos&7); var o=(pos>>>3); dt[o]|=val; dt[o+1]|=(val>>>8); }
UZIP.F._putsF= function(dt, pos, val ) { val = val<<(pos&7); var o=(pos>>>3); dt[o]|=val; dt[o+1]|=(val>>>8); dt[o+2]|=(val>>>16); }
UZIP.F._bitsE= function(dt, pos, length) { return ((dt[pos>>>3] | (dt[(pos>>>3)+1]<<8) )>>>(pos&7))&((1<<length)-1); }
UZIP.F._bitsF= function(dt, pos, length) { return ((dt[pos>>>3] | (dt[(pos>>>3)+1]<<8) | (dt[(pos>>>3)+2]<<16))>>>(pos&7))&((1<<length)-1); }
/*
UZIP.F._get9 = function(dt, pos) {
return ((dt[pos>>>3] | (dt[(pos>>>3)+1]<<8))>>>(pos&7))&511;
} */
UZIP.F._get17= function(dt, pos) { // return at least 17 meaningful bytes
return (dt[pos>>>3] | (dt[(pos>>>3)+1]<<8) | (dt[(pos>>>3)+2]<<16) )>>>(pos&7);
}
UZIP.F._get25= function(dt, pos) { // return at least 17 meaningful bytes
return (dt[pos>>>3] | (dt[(pos>>>3)+1]<<8) | (dt[(pos>>>3)+2]<<16) | (dt[(pos>>>3)+3]<<24) )>>>(pos&7);
}
UZIP.F.U = function(){
var u16=Uint16Array, u32=Uint32Array;
return {
next_code : new u16(16),
bl_count : new u16(16),
ordr : [ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ],
of0 : [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,999,999,999],
exb : [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, 0, 0, 0],
ldef : new u16(32),
df0 : [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, 65535, 65535],
dxb : [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, 0, 0],
ddef : new u32(32),
flmap: new u16( 512), fltree: [],
fdmap: new u16( 32), fdtree: [],
lmap : new u16(32768), ltree : [], ttree:[],
dmap : new u16(32768), dtree : [],
imap : new u16( 512), itree : [],
//rev9 : new u16( 512)
rev15: new u16(1<<15),
lhst : new u32(286), dhst : new u32( 30), ihst : new u32(19),
lits : new u32(15000),
strt : new u16(1<<16),
prev : new u16(1<<15)
};
} ();
(function(){
var U = UZIP.F.U;
var len = 1<<15;
for(var i=0; i<len; i++) {
var x = i;
x = (((x & 0xaaaaaaaa) >>> 1) | ((x & 0x55555555) << 1));
x = (((x & 0xcccccccc) >>> 2) | ((x & 0x33333333) << 2));
x = (((x & 0xf0f0f0f0) >>> 4) | ((x & 0x0f0f0f0f) << 4));
x = (((x & 0xff00ff00) >>> 8) | ((x & 0x00ff00ff) << 8));
U.rev15[i] = (((x >>> 16) | (x << 16)))>>>17;
}
function pushV(tgt, n, sv) { while(n--!=0) tgt.push(0,sv); }
for(var i=0; i<32; i++) { U.ldef[i]=(U.of0[i]<<3)|U.exb[i]; U.ddef[i]=(U.df0[i]<<4)|U.dxb[i]; }
pushV(U.fltree, 144, 8); pushV(U.fltree, 255-143, 9); pushV(U.fltree, 279-255, 7); pushV(U.fltree,287-279,8);
/*
var i = 0;
for(; i<=143; i++) U.fltree.push(0,8);
for(; i<=255; i++) U.fltree.push(0,9);
for(; i<=279; i++) U.fltree.push(0,7);
for(; i<=287; i++) U.fltree.push(0,8);
*/
UZIP.F.makeCodes(U.fltree, 9);
UZIP.F.codes2map(U.fltree, 9, U.flmap);
UZIP.F.revCodes (U.fltree, 9)
pushV(U.fdtree,32,5);
//for(i=0;i<32; i++) U.fdtree.push(0,5);
UZIP.F.makeCodes(U.fdtree, 5);
UZIP.F.codes2map(U.fdtree, 5, U.fdmap);
UZIP.F.revCodes (U.fdtree, 5)
pushV(U.itree,19,0); pushV(U.ltree,286,0); pushV(U.dtree,30,0); pushV(U.ttree,320,0);
/*
for(var i=0; i< 19; i++) U.itree.push(0,0);
for(var i=0; i<286; i++) U.ltree.push(0,0);
for(var i=0; i< 30; i++) U.dtree.push(0,0);
for(var i=0; i<320; i++) U.ttree.push(0,0);
*/
})()
+7
View File
@@ -0,0 +1,7 @@
{
"name": "uzip",
"version": "0.20201231.0",
"files": [ "LICENSE", "README.md", "UZIP.js", "package.json" ],
"main": "./UZIP",
"license": "MIT"
}