@syncfusion/ej2-compression
Advanced tools
| /*! | ||
| * filename: ej2-compression.min.js | ||
| * version : 31.2.2 | ||
| * version : 31.2.12 | ||
| * Copyright Syncfusion Inc. 2001 - 2025. All rights reserved. | ||
@@ -10,2 +10,2 @@ * Use of this code is subject to the terms of our license. | ||
| */ | ||
| !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("SyncfusionFileUtils")):"function"==typeof define&&define.amd?define(["SyncfusionFileUtils"],e):"object"==typeof exports?exports.SyncfusionCompression=e(require("SyncfusionFileUtils")):t.SyncfusionCompression=e(t.SyncfusionFileUtils)}(self,(t=>(()=>{"use strict";var e={115:e=>{e.exports=t}},i={};function r(t){var n=i[t];if(void 0!==n)return n.exports;var s=i[t]={exports:{}};return e[t](s,s.exports,r),s.exports}r.d=(t,e)=>{for(var i in e)r.o(e,i)&&!r.o(t,i)&&Object.defineProperty(t,i,{enumerable:!0,get:e[i]})},r.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var n={};return(()=>{r.r(n),r.d(n,{ChecksumCalculator:()=>m,CompressedStreamReader:()=>B,CompressedStreamWriter:()=>p,CompressorHuffmanTree:()=>l,DecompressorHuffmanTree:()=>g,Stream:()=>v,Utils:()=>e,ZipArchive:()=>o,ZipArchiveItem:()=>a,ZipArchiveItemHelper:()=>h});var t=r(115),e=function(){function t(){}return t.bitReverse=function(e){return t.reverseBits[15&e]<<12|t.reverseBits[e>>4&15]<<8|t.reverseBits[e>>8&15]<<4|t.reverseBits[e>>12]},t.bitConverterToInt32=function(t,e){return t[e]|t[e+1]<<8|t[e+2]<<16|t[e+3]<<24},t.bitConverterToInt16=function(t,e){return t[e]|t[e+1]<<8},t.bitConverterToUInt32=function(t){var e=new Uint32Array(1);return e[0]=t,e[0]},t.bitConverterToUInt16=function(t,e){var i=new Uint16Array(1);return i[0]=t[e]|t[e+1]<<8,i[0]},t.bitConverterUintToInt32=function(t){var e=new Int32Array(1);return e[0]=t,e[0]},t.bitConverterInt32ToUint=function(t){var e=new Uint32Array(1);return e[0]=t,e[0]},t.bitConverterInt32ToInt16=function(t){var e=new Int16Array(1);return e[0]=t,e[0]},t.byteToString=function(t){for(var e="",i=0;i<t.length;i++)e+=String.fromCharCode(t[i]);return e},t.byteIntToString=function(t){for(var e="",i=0;i<t.length;i++)e+=String.fromCharCode(t[i]);return e},t.arrayCopy=function(t,e,i,r,n){var s=new Uint8Array(t.buffer,e).subarray(0,n);i.set(s,r)},t.mergeArray=function(t,e){var i=new Uint8Array(t.length+e.length);return i.set(t),i.set(e,t.length),i},t.encodedString=function(t){var e,i,r,n,s,o,h="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",a=0,f=0,u=3*(t=t.replace(/[^A-Za-z0-9\+\/\=]/g,"")).length/4;if(t.charAt(t.length-1)===h.charAt(64)&&u--,t.charAt(t.length-2)===h.charAt(64)&&u--,u%1!=0)throw new Error("Invalid base64 input, bad content length.");for(var c=new Uint8Array(0|u);a<t.length;)e=h.indexOf(t.charAt(a++))<<2|(n=h.indexOf(t.charAt(a++)))>>4,i=(15&n)<<4|(s=h.indexOf(t.charAt(a++)))>>2,r=(3&s)<<6|(o=h.indexOf(t.charAt(a++))),c[f++]=e,64!==s&&(c[f++]=i),64!==o&&(c[f++]=r);return c},t.reverseBits=[0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15],t.huffCodeLengthOrders=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],t}(),i=[],s=4096,o=function(){function r(){0===i.length&&r.initCrc32Table(),this.files=[],this.level="Normal",t.Save.isMicrosoftBrowser=!!navigator.msSaveBlob}return Object.defineProperty(r.prototype,"items",{get:function(){return this.files},enumerable:!0,configurable:!0}),Object.defineProperty(r.prototype,"compressionLevel",{get:function(){return this.level},set:function(t){this.level=t},enumerable:!0,configurable:!0}),Object.defineProperty(r.prototype,"length",{get:function(){return void 0===this.files?0:this.files.length},enumerable:!0,configurable:!0}),r.prototype.addItem=function(t){if(null==t)throw new Error("ArgumentException: item cannot be null or undefined");for(var e=0;e<this.files.length;e++){var i=this.files[e];if(i instanceof a&&i.name===t.name)throw new Error("item with same name already exist")}this.files.push(t)},r.prototype.addDirectory=function(t){if(null==t)throw new Error("ArgumentException: string cannot be null or undefined");if(0===t.length)throw new Error("ArgumentException: string cannot be empty");if("/"!==t.slice(-1)&&(t+="/"),-1!==this.files.indexOf(t))throw new Error("item with same name already exist");this.files.push(t)},r.prototype.getItem=function(t){if(t>=0&&t<this.files.length)return this.files[t]},r.prototype.contains=function(t){return-1!==this.files.indexOf(t)},r.prototype.open=function(t){var i=e.encodedString(t);if(0==i.length)throw new DOMException("stream");var n=new v(i),s=r.findValueFromEnd(n,101010256,65557);if(s<0)throw new DOMException("Can't locate end of central directory record. Possible wrong file format or archive is corrupt.");n.position=s+12;var o=s-r.ReadInt32(n);n.position=o,this.readCentralDirectoryDataAndExtractItems(n)},r.prototype.readCentralDirectoryDataAndExtractItems=function(t){if(null==t)throw new DOMException("stream");for(var e;33639248==r.ReadInt32(t);)(e=new h).readCentralDirectoryData(t);e.readData(t,e.checkCrc),e.decompressData(),this.files.push(new a(e.unCompressedStream.buffer,e.name))},r.prototype.save=function(t){if(null==t||0===t.length)throw new Error("ArgumentException: fileName cannot be null or undefined");if(0===this.files.length)throw new Error("InvalidOperation");var e=this;return new Promise((function(i,r){e.saveInternal(t,!1).then((function(){i(e)}))}))},r.prototype.saveAsBlob=function(){var t=this;return new Promise((function(e,i){t.saveInternal("",!0).then((function(t){e(t)}))}))},r.prototype.saveInternal=function(t,e){var i=this,r=this;return new Promise((function(n,s){for(var o=[],h=0,a=0;a<r.files.length;a++){i.getCompressedData(i.files[a]).then((function(i){if(h=r.constructZippedObject(o,i,h,i.isDirectory),o.length===r.files.length){var s=r.writeZippedContent(t,o,h,e);n(s)}}))}}))},r.prototype.destroy=function(){if(void 0!==this.files&&this.files.length>0){for(var t=0;t<this.files.length;t++){var e=this.files[t];e instanceof a&&e.destroy(),e=void 0}this.files=[]}this.files=void 0,this.level=void 0},r.prototype.getCompressedData=function(t){var e=this;return new Promise((function(r,n){if(t instanceof a){var s=new FileReader;s.onload=function(){var n=new Uint8Array(s.result),o={fileName:t.name,crc32Value:0,compressedData:[],compressedSize:void 0,uncompressedDataSize:n.length,compressionType:void 0,isDirectory:!1};if("Normal"===e.level){e.compressData(n,o,i);for(var h=0,a=0;a<o.compressedData.length;a++)h+=o.compressedData[a].length;o.compressedSize=h,o.compressionType="\b\0"}else o.compressedSize=n.length,o.crc32Value=e.calculateCrc32Value(0,n,i),o.compressionType="\0\0",o.compressedData.push(n);r(o)},s.readAsArrayBuffer(t.data)}else{r({fileName:t,crc32Value:0,compressedData:"",compressedSize:0,uncompressedDataSize:0,compressionType:"\0\0",isDirectory:!0})}}))},r.prototype.compressData=function(t,e,i){var r=new p(!0),n=0,s=0;do{if(n>=t.length){r.close();break}s=Math.min(t.length,n+16384);var o=t.subarray(n,s);e.crc32Value=this.calculateCrc32Value(e.crc32Value,o,i),r.write(o,0,s-n),n=s}while(n<=t.length);e.compressedData=r.compressedData,r.destroy()},r.prototype.constructZippedObject=function(t,e,i,r){var n=0,s=new Date;r&&(n|=16),n|=0;var o=this.writeHeader(e,s),h="PK"+o+e.fileName,a=this.writeCentralDirectory(e,o,i,n);return t.push({localHeader:h,centralDir:a,compressedData:e}),i+h.length+e.compressedSize},r.prototype.writeHeader=function(t,e){var i="";return i+="\n\0\0\0",i+=t.compressionType,i+=this.getBytes(this.getModifiedTime(e),2),i+=this.getBytes(this.getModifiedDate(e),2),i+=this.getBytes(t.crc32Value,4),i+=this.getBytes(t.compressedSize,4),i+=this.getBytes(t.uncompressedDataSize,4),i+=this.getBytes(t.fileName.length,2),i+=this.getBytes(0,2)},r.prototype.writeZippedContent=function(e,i,r,n){for(var s=0,o=[],h=0;h<i.length;h++){var a=i[h];for(s+=a.centralDir.length,o.push(this.getArrayBuffer(a.localHeader));a.compressedData.compressedData.length;)o.push(a.compressedData.compressedData.shift().buffer)}for(h=0;h<i.length;h++)o.push(this.getArrayBuffer(i[h].centralDir));o.push(this.getArrayBuffer(this.writeFooter(i,s,r)));var f=new Blob(o,{type:"application/zip"});return n||t.Save.save(e,f),f},r.prototype.writeCentralDirectory=function(t,e,i,r){return"PK"+this.getBytes(20,2)+e+this.getBytes(0,2)+"\0\0\0\0"+this.getBytes(r,4)+this.getBytes(i,4)+t.fileName},r.prototype.writeFooter=function(t,e,i){return"PK\0\0\0\0"+this.getBytes(t.length,2)+this.getBytes(t.length,2)+this.getBytes(e,4)+this.getBytes(i,4)+this.getBytes(0,2)},r.prototype.getArrayBuffer=function(t){for(var e=new Uint8Array(t.length),i=0;i<t.length;++i)e[i]=255&t.charCodeAt(i);return e.buffer},r.prototype.getBytes=function(t,e){for(var i="",r=0;r<e;r++)i+=String.fromCharCode(255&t),t>>>=8;return i},r.prototype.getModifiedTime=function(t){var e=t.getHours();return e<<=6,e|=t.getMinutes(),(e<<=5)|t.getSeconds()/2},r.prototype.getModifiedDate=function(t){var e=t.getFullYear()-1980;return e<<=4,e|=t.getMonth()+1,(e<<=5)|t.getDate()},r.prototype.calculateCrc32Value=function(t,e,i){t^=-1;for(var r=0;r<e.length;r++)t=t>>>8^i[255&(t^e[r])];return~t},r.initCrc32Table=function(){for(var t,e=0;e<256;e++){t=e;for(var r=0;r<8;r++)t=1&t?3988292384^t>>>1:t>>>1;i[e]=t}},r.findValueFromEnd=function(t,e,i){if(null==t)throw new DOMException("stream");var r=t.inputStream.buffer.byteLength;if(r<4)return-1;var n=new Uint8Array(4),s=Math.max(0,r-i),o=r-1-4;t.position=o,t.read(n,0,4);var h=n[0],a=h==e;if(!a)for(;o>s;)if(h<<=8,o--,t.position=o,(h+=t.readByte())==e){a=!0;break}return a?o:-1},r.ReadInt32=function(t){var i=new Uint8Array(4);if(4!=t.read(i,0,4))throw new DOMException("Unable to read value at the specified position - end of stream was reached.");return e.bitConverterToInt32(i,0)},r.ReadInt16=function(t){var i=new Uint8Array(2);if(2!=t.read(i,0,2))throw new DOMException("Unable to read value at the specified position - end of stream was reached.");return e.bitConverterToInt16(i,0)},r.ReadUInt16=function(t){var i=new Uint8Array(2);if(2!=t.read(i,0,2))throw new DOMException("Unable to read value at the specified position - end of stream was reached.");return e.bitConverterToInt16(i,0)},r}(),h=function(){function t(){this.headerSignature=67324752,this.checkCrc=!0,this.crc32=0}return t.prototype.readCentralDirectoryData=function(t){t.position+=4,this.options=o.ReadInt16(t),this.compressionMethod=o.ReadInt16(t),this.checkCrc=99!=this.compressionMethod;o.ReadInt32(t);this.crc32=e.bitConverterToUInt32(o.ReadInt32(t)),this.compressedSize=o.ReadInt32(t),this.originalSize=o.ReadInt32(t);var i=o.ReadInt16(t),r=o.ReadInt16(t),n=o.ReadInt16(t);t.position+=4,this.externalAttributes=o.ReadInt32(t),this.localHeaderOffset=o.ReadInt32(t);var s=new Uint8Array(i);t.read(s,0,i);var h=e.byteToString(s);h=h.replace("\\","/"),this.name=h,t.position+=r+n,0!=this.options&&(this.options=0)},t.prototype.readData=function(t,e){if(0==t.length)throw new DOMException("stream");t.position=this.localHeaderOffset,this.checkCrc=e,this.readLocalHeader(t),this.readCompressedData(t)},t.prototype.decompressData=function(){8==this.compressionMethod&&this.originalSize>0&&this.decompressDataOld()},t.prototype.decompressDataOld=function(){var t,e=new B(this.compressedStream,!0);this.originalSize>0&&(t=new v(new Uint8Array(this.originalSize)));var i,r=new Uint8Array(s);for(new Uint8Array(0);(i=e.read(r,0,s))>0;)t.write(r.subarray(0,i),0,i);this.unCompressedStream=t.toByteArray(),this.checkCrc},t.prototype.readLocalHeader=function(t){if(0==t.length)throw new DOMException("stream");if(o.ReadInt32(t)!=this.headerSignature)throw new DOMException("Can't find local header signature - wrong file format or file is corrupt.");t.position+=22;var e=o.ReadInt16(t),i=o.ReadUInt16(t);if(99==this.compressionMethod);else if(i>2){if(t.position+=e,23==o.ReadInt16(t))throw new DOMException("UnSupported");t.position+=i-2}else t.position+=e+i},t.prototype.readCompressedData=function(t){var e;if(this.compressedSize>0){var i=this.compressedSize;e=new v(new Uint8Array(i));for(var r=new Uint8Array(s);i>0;){var n=Math.min(i,s);if(t.read(r,0,n)!=n)throw new DOMException("End of file reached - wrong file format or file is corrupt.");e.write(r.subarray(0,n),0,n),i-=n}this.compressedStream=new Uint8Array(e.inputStream)}else this.compressedSize<0||this.compressedSize},t}(),a=function(){function t(t,e){if(null==t)throw new Error("ArgumentException: data cannot be null or undefined");if(null==e)throw new Error("ArgumentException: string cannot be null or undefined");if(0===e.length)throw new Error("string cannot be empty");this.data=t,this.name=e}return Object.defineProperty(t.prototype,"dataStream",{get:function(){return this.decompressedStream},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"name",{get:function(){return this.fileName},set:function(t){this.fileName=t},enumerable:!0,configurable:!0}),t.prototype.destroy=function(){this.fileName=void 0,this.data=void 0},t}(),f=new Int16Array(286),u=new Uint8Array(286),c=new Int16Array(30),d=new Uint8Array(30),p=function(){function e(t){this.pendingBuffer=new Uint8Array(65536),this.pendingBufLength=0,this.pendingBufCache=0,this.pendingBufBitsInCache=0,this.bufferPosition=0,this.extraBits=0,this.currentHash=0,this.matchStart=0,this.matchLength=0,this.matchPrevAvail=!1,this.blockStart=0,this.stringStart=0,this.lookAhead=0,this.totalBytesIn=0,this.inputOffset=0,this.inputEnd=0,this.windowSize=32768,this.windowMask=this.windowSize-1,this.hashSize=32768,this.hashMask=this.hashSize-1,this.hashShift=Math.floor(17/3),this.maxDist=this.windowSize-262,this.checkSum=1,this.noWrap=!1,e.isHuffmanTreeInitiated||(e.initHuffmanTree(),e.isHuffmanTreeInitiated=!0),this.treeLiteral=new l(this,286,257,15),this.treeDistances=new l(this,30,1,15),this.treeCodeLengths=new l(this,19,4,7),this.arrDistances=new Uint16Array(16384),this.arrLiterals=new Uint8Array(16384),this.stream=[],this.dataWindow=new Uint8Array(2*this.windowSize),this.hashHead=new Int16Array(this.hashSize),this.hashPrevious=new Int16Array(this.windowSize),this.blockStart=this.stringStart=1,this.noWrap=t,t||this.writeZLibHeader()}return Object.defineProperty(e.prototype,"compressedData",{get:function(){return this.stream},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"getCompressedString",{get:function(){var t="";if(void 0!==this.stream)for(var e=0;e<this.stream.length;e++)t+=String.fromCharCode.apply(null,this.stream[e]);return t},enumerable:!0,configurable:!0}),e.prototype.write=function(e,i,r){if(null==e)throw new Error("ArgumentException: data cannot null or undefined");var n=i+r;if(0>i||i>n||n>e.length)throw new Error("ArgumentOutOfRangeException: Offset or length is incorrect");if("string"==typeof e){var s=new t.Encoding(!1);s.type="Utf8",n=i+(e=new Uint8Array(s.getBytes(e,0,e.length))).length}for(this.inputBuffer=e,this.inputOffset=i,this.inputEnd=n,this.noWrap||(this.checkSum=m.checksumUpdate(this.checkSum,this.inputBuffer,this.inputOffset,n));this.inputEnd!==this.inputOffset||0!==this.pendingBufLength;)this.pendingBufferFlush(),this.compressData(!1)},e.prototype.writeZLibHeader=function(){var t=30720;t|=64,t+=31-t%31,this.pendingBufferWriteShortBytes(t)},e.prototype.pendingBufferWriteShortBytes=function(t){this.pendingBuffer[this.pendingBufLength++]=t>>8,this.pendingBuffer[this.pendingBufLength++]=t},e.prototype.compressData=function(t){var e;do{this.fillWindow();var i=t&&this.inputEnd===this.inputOffset;e=this.compressSlow(i,t)}while(0===this.pendingBufLength&&e);return e},e.prototype.compressSlow=function(t,e){if(this.lookAhead<262&&!t)return!1;for(;this.lookAhead>=262||t;){if(0===this.lookAhead)return this.lookAheadCompleted(e);this.stringStart>=2*this.windowSize-262&&this.slideWindow();var i=this.matchStart,r=this.matchLength;if(this.lookAhead>=3&&this.discardMatch(),r>=3&&this.matchLength<=r?r=this.matchPreviousBest(i,r):this.matchPreviousAvailable(),this.bufferPosition>=16384)return this.huffmanIsFull(e)}return!0},e.prototype.discardMatch=function(){var t=this.insertString();0!==t&&this.stringStart-t<=this.maxDist&&this.findLongestMatch(t)&&this.matchLength<=5&&3===this.matchLength&&this.stringStart-this.matchStart>4096&&(this.matchLength=2)},e.prototype.matchPreviousAvailable=function(){this.matchPrevAvail&&this.huffmanTallyLit(255&this.dataWindow[this.stringStart-1]),this.matchPrevAvail=!0,this.stringStart++,this.lookAhead--},e.prototype.matchPreviousBest=function(t,e){this.huffmanTallyDist(this.stringStart-1-t,e),e-=2;do{this.stringStart++,this.lookAhead--,this.lookAhead>=3&&this.insertString()}while(--e>0);return this.stringStart++,this.lookAhead--,this.matchPrevAvail=!1,this.matchLength=2,e},e.prototype.lookAheadCompleted=function(t){return this.matchPrevAvail&&this.huffmanTallyLit(255&this.dataWindow[this.stringStart-1]),this.matchPrevAvail=!1,this.huffmanFlushBlock(this.dataWindow,this.blockStart,this.stringStart-this.blockStart,t),this.blockStart=this.stringStart,!1},e.prototype.huffmanIsFull=function(t){var e=this.stringStart-this.blockStart;this.matchPrevAvail&&e--;var i=t&&0===this.lookAhead&&!this.matchPrevAvail;return this.huffmanFlushBlock(this.dataWindow,this.blockStart,e,i),this.blockStart+=e,!i},e.prototype.fillWindow=function(){for(this.stringStart>=this.windowSize+this.maxDist&&this.slideWindow();this.lookAhead<262&&this.inputOffset<this.inputEnd;){var t=2*this.windowSize-this.lookAhead-this.stringStart;t>this.inputEnd-this.inputOffset&&(t=this.inputEnd-this.inputOffset),this.dataWindow.set(this.inputBuffer.subarray(this.inputOffset,this.inputOffset+t),this.stringStart+this.lookAhead),this.inputOffset+=t,this.totalBytesIn+=t,this.lookAhead+=t}this.lookAhead>=3&&this.updateHash()},e.prototype.slideWindow=function(){this.dataWindow.set(this.dataWindow.subarray(this.windowSize,this.windowSize+this.windowSize),0),this.matchStart-=this.windowSize,this.stringStart-=this.windowSize,this.blockStart-=this.windowSize;for(var t=0;t<this.hashSize;++t){var e=65535&this.hashHead[t];this.hashHead[t]=e>=this.windowSize?e-this.windowSize:0}for(t=0;t<this.windowSize;t++){e=65535&this.hashPrevious[t];this.hashPrevious[t]=e>=this.windowSize?e-this.windowSize:0}},e.prototype.insertString=function(){var t,e=(this.currentHash<<this.hashShift^this.dataWindow[this.stringStart+2])&this.hashMask;return this.hashPrevious[this.stringStart&this.windowMask]=t=this.hashHead[e],this.hashHead[e]=this.stringStart,this.currentHash=e,65535&t},e.prototype.findLongestMatch=function(t){var e,i=4096,r=258,n=this.stringStart,s=this.stringStart+this.matchLength,o=Math.max(this.matchLength,2),h=Math.max(this.stringStart-this.maxDist,0),a=this.stringStart+258-1,f=this.dataWindow[s-1],u=this.dataWindow[s],c=this.dataWindow;o>=32&&(i>>=2),r>this.lookAhead&&(r=this.lookAhead);do{if(c[t+o]===u&&c[t+o-1]===f&&c[t]===c[n]&&c[t+1]===c[n+1]){for(e=t+2,n+=2;c[++n]===c[++e]&&c[++n]===c[++e]&&c[++n]===c[++e]&&c[++n]===c[++e]&&c[++n]===c[++e]&&c[++n]===c[++e]&&c[++n]===c[++e]&&c[++n]===c[++e]&&n<a;);if(n>s){if(this.matchStart=t,s=n,(o=n-this.stringStart)>=r)break;f=c[s-1],u=c[s]}n=this.stringStart}}while((t=65535&this.hashPrevious[t&this.windowMask])>h&&0!=--i);return this.matchLength=Math.min(o,this.lookAhead),this.matchLength>=3},e.prototype.updateHash=function(){this.currentHash=this.dataWindow[this.stringStart]<<this.hashShift^this.dataWindow[this.stringStart+1]},e.prototype.huffmanTallyLit=function(t){return this.arrDistances[this.bufferPosition]=0,this.arrLiterals[this.bufferPosition++]=t,this.treeLiteral.codeFrequencies[t]++,this.bufferPosition>=16384},e.prototype.huffmanTallyDist=function(t,e){this.arrDistances[this.bufferPosition]=t,this.arrLiterals[this.bufferPosition++]=e-3;var i=this.huffmanLengthCode(e-3);this.treeLiteral.codeFrequencies[i]++,i>=265&&i<285&&(this.extraBits+=Math.floor((i-261)/4));var r=this.huffmanDistanceCode(t-1);return this.treeDistances.codeFrequencies[r]++,r>=4&&(this.extraBits+=Math.floor(r/2-1)),this.bufferPosition>=16384},e.prototype.huffmanFlushBlock=function(t,e,i,r){this.treeLiteral.codeFrequencies[256]++,this.treeLiteral.buildTree(),this.treeDistances.buildTree(),this.treeLiteral.calculateBLFreq(this.treeCodeLengths),this.treeDistances.calculateBLFreq(this.treeCodeLengths),this.treeCodeLengths.buildTree();for(var n=4,s=18;s>n;s--)this.treeCodeLengths.codeLengths[l.huffCodeLengthOrders[s]]>0&&(n=s+1);var o=14+3*n+this.treeCodeLengths.getEncodedLength()+this.treeLiteral.getEncodedLength()+this.treeDistances.getEncodedLength()+this.extraBits,h=this.extraBits;for(s=0;s<286;s++)h+=this.treeLiteral.codeFrequencies[s]*u[s];for(s=0;s<30;s++)h+=this.treeDistances.codeFrequencies[s]*d[s];o>=h&&(o=h),e>=0&&i+4<o>>3?this.huffmanFlushStoredBlock(t,e,i,r):o==h?(this.pendingBufferWriteBits(2+(r?1:0),3),this.treeLiteral.setStaticCodes(f,u),this.treeDistances.setStaticCodes(c,d),this.huffmanCompressBlock(),this.huffmanReset()):(this.pendingBufferWriteBits(4+(r?1:0),3),this.huffmanSendAllTrees(n),this.huffmanCompressBlock(),this.huffmanReset())},e.prototype.huffmanFlushStoredBlock=function(t,e,i,r){this.pendingBufferWriteBits(0+(r?1:0),3),this.pendingBufferAlignToByte(),this.pendingBufferWriteShort(i),this.pendingBufferWriteShort(~i),this.pendingBufferWriteByteBlock(t,e,i),this.huffmanReset()},e.prototype.huffmanLengthCode=function(t){if(255===t)return 285;for(var e=257;t>=8;)e+=4,t>>=1;return e+t},e.prototype.huffmanDistanceCode=function(t){for(var e=0;t>=4;)e+=2,t>>=1;return e+t},e.prototype.huffmanSendAllTrees=function(t){this.treeCodeLengths.buildCodes(),this.treeLiteral.buildCodes(),this.treeDistances.buildCodes(),this.pendingBufferWriteBits(this.treeLiteral.treeLength-257,5),this.pendingBufferWriteBits(this.treeDistances.treeLength-1,5),this.pendingBufferWriteBits(t-4,4);for(var e=0;e<t;e++)this.pendingBufferWriteBits(this.treeCodeLengths.codeLengths[l.huffCodeLengthOrders[e]],3);this.treeLiteral.writeTree(this.treeCodeLengths),this.treeDistances.writeTree(this.treeCodeLengths)},e.prototype.huffmanReset=function(){this.bufferPosition=0,this.extraBits=0,this.treeLiteral.reset(),this.treeDistances.reset(),this.treeCodeLengths.reset()},e.prototype.huffmanCompressBlock=function(){for(var t=0;t<this.bufferPosition;t++){var e=255&this.arrLiterals[t],i=this.arrDistances[t];if(0!=i--){var r=this.huffmanLengthCode(e);this.treeLiteral.writeCodeToStream(r);var n=Math.floor((r-261)/4);n>0&&n<=5&&this.pendingBufferWriteBits(e&(1<<n)-1,n);var s=this.huffmanDistanceCode(i);this.treeDistances.writeCodeToStream(s),(n=Math.floor(s/2-1))>0&&this.pendingBufferWriteBits(i&(1<<n)-1,n)}else this.treeLiteral.writeCodeToStream(e)}this.treeLiteral.writeCodeToStream(256)},e.prototype.pendingBufferWriteBits=function(t,e){var i=new Uint32Array(1);i[0]=this.pendingBufCache|t<<this.pendingBufBitsInCache,this.pendingBufCache=i[0],this.pendingBufBitsInCache+=e,this.pendingBufferFlushBits()},e.prototype.pendingBufferFlush=function(t){if(this.pendingBufferFlushBits(),this.pendingBufLength>0){var e=new Uint8Array(this.pendingBufLength);e.set(this.pendingBuffer.subarray(0,this.pendingBufLength),0),this.stream.push(e)}this.pendingBufLength=0},e.prototype.pendingBufferFlushBits=function(){for(var t=0;this.pendingBufBitsInCache>=8&&this.pendingBufLength<65536;)this.pendingBuffer[this.pendingBufLength++]=this.pendingBufCache,this.pendingBufCache>>=8,this.pendingBufBitsInCache-=8,t++;return t},e.prototype.pendingBufferWriteByteBlock=function(t,e,i){var r=t.subarray(e,e+i);this.pendingBuffer.set(r,this.pendingBufLength),this.pendingBufLength+=i},e.prototype.pendingBufferWriteShort=function(t){this.pendingBuffer[this.pendingBufLength++]=t,this.pendingBuffer[this.pendingBufLength++]=t>>8},e.prototype.pendingBufferAlignToByte=function(){this.pendingBufBitsInCache>0&&(this.pendingBuffer[this.pendingBufLength++]=this.pendingBufCache),this.pendingBufCache=0,this.pendingBufBitsInCache=0},e.initHuffmanTree=function(){for(var t=0;t<144;)f[t]=l.bitReverse(48+t<<8),u[t++]=8;for(;t<256;)f[t]=l.bitReverse(256+t<<7),u[t++]=9;for(;t<280;)f[t]=l.bitReverse(-256+t<<9),u[t++]=7;for(;t<286;)f[t]=l.bitReverse(-88+t<<8),u[t++]=8;for(t=0;t<30;t++)c[t]=l.bitReverse(t<<11),d[t]=5},e.prototype.close=function(){do{this.pendingBufferFlush(!0),this.compressData(!0)||(this.pendingBufferFlush(!0),this.pendingBufferAlignToByte(),this.noWrap||(this.pendingBufferWriteShortBytes(this.checkSum>>16),this.pendingBufferWriteShortBytes(65535&this.checkSum)),this.pendingBufferFlush(!0))}while(this.inputEnd!==this.inputOffset||0!==this.pendingBufLength)},e.prototype.destroy=function(){this.stream=[],this.stream=void 0,this.pendingBuffer=void 0,this.treeLiteral=void 0,this.treeDistances=void 0,this.treeCodeLengths=void 0,this.arrLiterals=void 0,this.arrDistances=void 0,this.hashHead=void 0,this.hashPrevious=void 0,this.dataWindow=void 0,this.inputBuffer=void 0,this.pendingBufLength=void 0,this.pendingBufCache=void 0,this.pendingBufBitsInCache=void 0,this.bufferPosition=void 0,this.extraBits=void 0,this.currentHash=void 0,this.matchStart=void 0,this.matchLength=void 0,this.matchPrevAvail=void 0,this.blockStart=void 0,this.stringStart=void 0,this.lookAhead=void 0,this.totalBytesIn=void 0,this.inputOffset=void 0,this.inputEnd=void 0,this.windowSize=void 0,this.windowMask=void 0,this.hashSize=void 0,this.hashMask=void 0,this.hashShift=void 0,this.maxDist=void 0,this.checkSum=void 0,this.noWrap=void 0},e.isHuffmanTreeInitiated=!1,e}(),l=function(){function t(t,e,i,r){this.writer=t,this.codeMinCount=i,this.maxLength=r,this.codeFrequency=new Uint16Array(e),this.lengthCount=new Int32Array(r)}return Object.defineProperty(t.prototype,"treeLength",{get:function(){return this.codeCount},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"codeLengths",{get:function(){return this.codeLength},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"codeFrequencies",{get:function(){return this.codeFrequency},enumerable:!0,configurable:!0}),t.prototype.setStaticCodes=function(t,e){var i=new Int16Array(t.length);i.set(t,0),this.codes=i;var r=new Uint8Array(e.length);r.set(e,0),this.codeLength=r},t.prototype.reset=function(){for(var t=0;t<this.codeFrequency.length;t++)this.codeFrequency[t]=0;this.codes=void 0,this.codeLength=void 0},t.prototype.writeCodeToStream=function(t){this.writer.pendingBufferWriteBits(65535&this.codes[t],this.codeLength[t])},t.prototype.buildCodes=function(){var e=new Int32Array(this.maxLength);this.codes=new Int16Array(this.codeCount);for(var i=0,r=0;r<this.maxLength;r++)e[r]=i,i+=this.lengthCount[r]<<15-r;for(var n=0;n<this.codeCount;n++){var s=this.codeLength[n];s>0&&(this.codes[n]=t.bitReverse(e[s-1]),e[s-1]+=1<<16-s)}},t.bitReverse=function(e){return t.reverseBits[15&e]<<12|t.reverseBits[e>>4&15]<<8|t.reverseBits[e>>8&15]<<4|t.reverseBits[e>>12]},t.prototype.getEncodedLength=function(){for(var t=0,e=0;e<this.codeFrequency.length;e++)t+=this.codeFrequency[e]*this.codeLength[e];return t},t.prototype.calculateBLFreq=function(t){for(var e,i,r,n=-1,s=0;s<this.codeCount;){r=1;var o=this.codeLength[s];for(0===o?(e=138,i=3):(e=6,i=3,n!==o&&(t.codeFrequency[o]++,r=0)),n=o,s++;s<this.codeCount&&n===this.codeLength[s]&&(s++,!(++r>=e)););r<i?t.codeFrequency[n]+=r:0!==n?t.codeFrequency[16]++:r<=10?t.codeFrequency[17]++:t.codeFrequency[18]++}},t.prototype.writeTree=function(t){for(var e,i,r,n=-1,s=0;s<this.codeCount;){r=1;var o=this.codeLength[s];for(0===o?(e=138,i=3):(e=6,i=3,n!==o&&(t.writeCodeToStream(o),r=0)),n=o,s++;s<this.codeCount&&n===this.codeLength[s]&&(s++,!(++r>=e)););if(r<i)for(;r-- >0;)t.writeCodeToStream(n);else 0!==n?(t.writeCodeToStream(16),this.writer.pendingBufferWriteBits(r-3,2)):r<=10?(t.writeCodeToStream(17),this.writer.pendingBufferWriteBits(r-3,3)):(t.writeCodeToStream(18),this.writer.pendingBufferWriteBits(r-11,7))}},t.prototype.buildTree=function(){for(var t=this.codeFrequency.length,e=new Int32Array(t),i=0,r=0,n=0;n<t;n++){var s=this.codeFrequency[n];if(0!==s){for(var o=i++,h=0;o>0&&this.codeFrequency[e[h=Math.floor((o-1)/2)]]>s;)e[o]=e[h],o=h;e[o]=n,r=n}}for(;i<2;)e[i++]=r<2?++r:0;this.codeCount=Math.max(r+1,this.codeMinCount);for(var a=i,f=new Int32Array(4*i-2),u=new Int32Array(2*i-1),c=0;c<i;c++){var d=e[c],p=2*c;f[p]=d,f[p+1]=-1,u[c]=this.codeFrequency[d]<<8,e[c]=c}this.constructHuffmanTree(e,i,u,a,f),this.buildLength(f)},t.prototype.constructHuffmanTree=function(t,e,i,r,n){do{for(var s=t[0],o=t[--e],h=i[o],a=0,f=1;f<e;)f+1<e&&i[t[f]]>i[t[f+1]]&&f++,t[a]=t[f],f=2*(a=f)+1;for(;(f=a)>0&&i[t[a=Math.floor((f-1)/2)]]>h;)t[f]=t[a];t[f]=o;var u=t[0];n[2*(o=r++)]=s,n[2*o+1]=u;var c=Math.min(255&i[s],255&i[u]);for(i[o]=h=i[s]+i[u]-c+1,a=0,f=1;f<e;)f+1<e&&i[t[f]]>i[t[f+1]]&&f++,t[a]=t[f],f=2*(a=f)+1;for(;(f=a)>0&&i[t[a=Math.floor((f-1)/2)]]>h;)t[f]=t[a];t[f]=o}while(e>1)},t.prototype.buildLength=function(t){this.codeLength=new Uint8Array(this.codeFrequency.length);for(var e=Math.floor(t.length/2),i=Math.floor((e+1)/2),r=0,n=0;n<this.maxLength;n++)this.lengthCount[n]=0;if(0!==(r=this.calculateOptimalCodeLength(t,r,e))){var s=this.maxLength-1;do{for(;0===this.lengthCount[--s];);do{this.lengthCount[s]--,this.lengthCount[++s]++,r-=1<<this.maxLength-1-s}while(r>0&&s<this.maxLength-1)}while(r>0);this.recreateTree(t,r,i)}},t.prototype.recreateTree=function(t,e,i){this.lengthCount[this.maxLength-1]+=e,this.lengthCount[this.maxLength-2]-=e;for(var r=2*i,n=this.maxLength;0!==n;n--)for(var s=this.lengthCount[n-1];s>0;){var o=2*t[r++];-1===t[o+1]&&(this.codeLength[t[o]]=n,s--)}},t.prototype.calculateOptimalCodeLength=function(t,e,i){var r=new Int32Array(i);r[i-1]=0;for(var n=i-1;n>=0;n--){var s=2*n+1;if(-1!==t[s]){(o=r[n]+1)>this.maxLength&&(o=this.maxLength,e++),r[t[s-1]]=r[t[s]]=o}else{var o=r[n];this.lengthCount[o-1]++,this.codeLength[t[s-1]]=r[n]}}return e},t.reverseBits=[0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15],t.huffCodeLengthOrders=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],t}(),m=function(){function t(){}return t.checksumUpdate=function(e,i,r,n){var s=new Uint32Array(1);s[0]=e;for(var o=s[0],h=s[0]=65535&o,a=s[0]=o>>t.checkSumBitOffset;n>0;){var f=Math.min(n,t.checksumIterationCount);for(n-=f;--f>=0;)a+=h+=s[0]=255&i[r++];h%=t.checksumBase,a%=t.checksumBase}return o=a<<t.checkSumBitOffset|h},t.checkSumBitOffset=16,t.checksumBase=65521,t.checksumIterationCount=3800,t}(),g=function(){function t(t){this.buildTree(t)}return t.init=function(){var e,i;for(e=new Uint8Array(288),i=0;i<144;)e[i++]=8;for(;i<256;)e[i++]=9;for(;i<280;)e[i++]=7;for(;i<288;)e[i++]=8;for(t.m_LengthTree=new t(e),e=new Uint8Array(32),i=0;i<32;)e[i++]=5;t.m_DistanceTree=new t(e)},t.prototype.prepareData=function(e,i,r){for(var n=0,s=512,o=0;o<r.length;o++){var h=r[o];h>0&&e[h]++}for(var a=1;a<=t.MAX_BITLEN;a++){if(i[a]=n,n+=e[a]<<16-a,a>=10)s+=(130944&n)-(130944&i[a])>>16-a}return{code:n,treeSize:s}},t.prototype.treeFromData=function(i,r,n,s,o){for(var h=new Int16Array(o),a=512,f=t.MAX_BITLEN;f>=10;f--)for(var u=130944&s,c=130944&(s-=i[f]<<16-f);c<u;c+=128)h[e.bitReverse(c)]=e.bitConverterInt32ToInt16(-a<<4|f),a+=1<<f-9;for(c=0;c<n.length;c++){if(0!=(f=n[c])){s=r[f];var d=e.bitReverse(s);if(f<=9)do{h[d]=e.bitConverterInt32ToInt16(c<<4|f),d+=1<<f}while(d<512);else{var p=h[511&d],l=1<<(15&p);p=-(p>>4);do{h[p|d>>9]=e.bitConverterInt32ToInt16(c<<4|f),d+=1<<f}while(d<l)}r[f]=s+(1<<16-f)}}return h},t.prototype.buildTree=function(t){var e=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],i=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],r=this.prepareData(e,i,t);this.m_Tree=this.treeFromData(e,i,t,r.code,r.treeSize)},t.prototype.unpackSymbol=function(t){var e,i;if((e=t.peekBits(9))>=0){if((i=this.m_Tree[e])>=0)return t.skipBits(15&i),i>>4;var r=-(i>>4),n=15&i;if((e=t.peekBits(n))>=0)return i=this.m_Tree[r|e>>9],t.skipBits(15&i),i>>4;var s=t.availableBits;return e=t.peekBits(s),(15&(i=this.m_Tree[r|e>>9]))<=s?(t.skipBits(15&i),i>>4):-1}s=t.availableBits;return e=t.peekBits(s),(i=this.m_Tree[e])>=0&&(15&i)<=s?(t.skipBits(15&i),i>>4):-1},Object.defineProperty(t,"lengthTree",{get:function(){return this.m_LengthTree},enumerable:!0,configurable:!0}),Object.defineProperty(t,"distanceTree",{get:function(){return this.m_DistanceTree},enumerable:!0,configurable:!0}),t.MAX_BITLEN=15,t}(),y=function(){function t(){}return t.ChecksumUpdate=function(t,e,i,r){for(var n=t,s=65535&n,o=n>>this.DEF_CHECKSUM_BIT_OFFSET;r>0;){var h=Math.min(r,this.DEF_CHECKSUM_ITERATIONSCOUNT);for(r-=h;--h>=0;)o+=s+=255&e[i++];s%=this.DEF_CHECKSUM_BASE,o%=this.DEF_CHECKSUM_BASE}t=n=o<<this.DEF_CHECKSUM_BIT_OFFSET|s},t.ChecksumGenerate=function(e,i,r){return t.ChecksumUpdate(1,e,i,r),1},t.DEF_CHECKSUM_BIT_OFFSET=16,t.DEF_CHECKSUM_BASE=65521,t.DEF_CHECKSUM_ITERATIONSCOUNT=3800,t}(),B=function(){function t(t,e){if(this.defaultHuffmanDynamicTree=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],this.DEF_HEADER_METHOD_MASK=3840,this.DEF_HEADER_INFO_MASK=61440,this.DEF_HEADER_FLAGS_FCHECK=31,this.DEF_HEADER_FLAGS_FDICT=32,this.DEF_HEADER_FLAGS_FLEVEL=192,this.DEF_MAX_WINDOW_SIZE=65535,this.DEF_HUFFMAN_REPEATE_MAX=258,this.DEF_HUFFMAN_END_BLOCK=256,this.DEF_HUFFMAN_LENGTH_MINIMUMCODE=257,this.DEF_HUFFMAN_LENGTH_MAXIMUMCODE=285,this.DEF_HUFFMAN_DISTANCE_MAXIMUMCODE=29,this.mCheckSum=1,this.tBuffer=0,this.mBufferedBits=0,this.mTempBuffer=new Uint8Array(4),this.mBlockBuffer=new Uint8Array(this.DEF_MAX_WINDOW_SIZE),this.mbNoWrap=!1,this.mWindowSize=0,this.mCurrentPosition=0,this.mDataLength=0,this.mbCanReadNextBlock=!0,this.mbCanReadMoreData=!0,this.mbCheckSumRead=!1,null==t)throw new DOMException("stream");if(0===t.length)throw new DOMException("stream - string can not be empty");g.init(),this.mInputStream=new v(t),this.mbNoWrap=e,this.mbNoWrap||this.readZLibHeader(),this.decodeBlockHeader()}return Object.defineProperty(t.prototype,"mBuffer",{get:function(){return this.tBuffer},set:function(t){this.tBuffer=t},enumerable:!0,configurable:!0}),t.prototype.peekBits=function(t){if(t<0)throw new DOMException("count","Bits count can not be less than zero.");if(t>32)throw new DOMException("count","Count of bits is too large.");if(this.mBufferedBits<t&&this.fillBuffer(),this.mBufferedBits<t)return-1;var i=~(4294967295<<t);return e.bitConverterUintToInt32(this.mBuffer&i)},t.prototype.fillBuffer=function(){var t=4-(this.mBufferedBits>>3)-(7&this.mBufferedBits?1:0);if(0!==t)for(var i=this.mInputStream.read(this.mTempBuffer,0,t),r=0;r<i;r++)this.mBuffer=e.bitConverterInt32ToUint(this.mBuffer|e.bitConverterInt32ToUint(this.mTempBuffer[r]<<this.mBufferedBits)),this.mBufferedBits+=8},t.prototype.skipBits=function(t){if(t<0)throw new DOMException("count","Bits count can not be less than zero.");0!==t&&(t>=this.mBufferedBits?(t-=this.mBufferedBits,this.mBufferedBits=0,this.mBuffer=0,t>0&&(this.mInputStream.position+=t>>3,(t&=7)>0&&(this.fillBuffer(),this.mBufferedBits-=t,this.mBuffer=e.bitConverterInt32ToUint(this.mBuffer>>>t)))):(this.mBufferedBits-=t,this.mBuffer=e.bitConverterInt32ToUint(this.mBuffer>>>t)))},Object.defineProperty(t.prototype,"availableBits",{get:function(){return this.mBufferedBits},enumerable:!0,configurable:!0}),t.prototype.readZLibHeader=function(){var t=this.readInt16();if(-1===t)throw new DOMException("Header of the stream can not be read.");if(t%31!=0)throw new DOMException("Header checksum illegal");if(2048!=(t&this.DEF_HEADER_METHOD_MASK))throw new DOMException("Unsupported compression method.");if(this.mWindowSize=Math.pow(2,8+((t&this.DEF_HEADER_INFO_MASK)>>12)),this.mWindowSize>65535)throw new DOMException("Unsupported window size for deflate compression method.");if((t&this.DEF_HEADER_FLAGS_FDICT)>>5==1)throw new DOMException("Custom dictionary is not supported at the moment.")},t.prototype.readInt16=function(){var t=this.readBits(8)<<8;return t|=this.readBits(8)},t.prototype.readBits=function(t){var i=this.peekBits(t);return-1===i?-1:(this.mBufferedBits-=t,this.mBuffer=e.bitConverterInt32ToUint(this.mBuffer>>>t),i)},t.prototype.decodeBlockHeader=function(){if(!this.mbCanReadNextBlock)return!1;var t=this.readBits(1);if(-1===t)return!1;var e=this.readBits(2);if(-1===e)return!1;switch(this.mbCanReadNextBlock=0===t,e){case 0:this.mbReadingUncompressed=!0,this.skipToBoundary();var i=this.readInt16Inverted();if(i!==(65535^this.readInt16Inverted()))throw new DOMException("Wrong block length.");if(i>65535)throw new DOMException("Uncompressed block length can not be more than 65535.");this.mUncompressedDataLength=i,this.mCurrentLengthTree=null,this.mCurrentDistanceTree=null;break;case 1:this.mbReadingUncompressed=!1,this.mUncompressedDataLength=-1,this.mCurrentLengthTree=g.lengthTree,this.mCurrentDistanceTree=g.distanceTree;break;case 2:this.mbReadingUncompressed=!1,this.mUncompressedDataLength=-1;var r=this.decodeDynamicHeader(this.mCurrentLengthTree,this.mCurrentDistanceTree);this.mCurrentLengthTree=r.lengthTree,this.mCurrentDistanceTree=r.distanceTree;break;default:throw new DOMException("Wrong block type.")}return!0},t.prototype.skipToBoundary=function(){this.mBuffer=e.bitConverterInt32ToUint(this.mBuffer>>>(7&this.mBufferedBits)),this.mBufferedBits&=-8},t.prototype.readInt16Inverted=function(){var t=this.readBits(8);return t|=this.readBits(8)<<8},t.prototype.decodeDynamicHeader=function(e,i){var r=0,n=this.readBits(5),s=this.readBits(5),o=this.readBits(4);if(n<0||s<0||o<0)throw new DOMException("Wrong dynamic huffman codes.");var h=(n+=257)+(s+=1),a=new Uint8Array(h),f=new Uint8Array(19);o+=4;for(var u=0;u<o;){var c=this.readBits(3);if(c<0)throw new DOMException("Wrong dynamic huffman codes.");f[this.defaultHuffmanDynamicTree[u++]]=c}var d=new g(f);for(u=0;;){var p=void 0,l=!1;for(p=d.unpackSymbol(this);!(-16&p);){if(a[u++]=r=p,u===h){l=!0;break}p=d.unpackSymbol(this)}if(l)break;if(p<0)throw new DOMException("Wrong dynamic huffman codes.");if(p>=17)r=0;else if(0===u)throw new DOMException("Wrong dynamic huffman codes.");var m=p-16,y=t.DEF_HUFFMAN_DYNTREE_REPEAT_BITS[m],B=this.readBits(y);if(B<0)throw new DOMException("Wrong dynamic huffman codes.");if(u+(B+=t.DEF_HUFFMAN_DYNTREE_REPEAT_MINIMUMS[m])>h)throw new DOMException("Wrong dynamic huffman codes.");for(;B-- >0;)a[u++]=r;if(u===h)break}var v=new Uint8Array(n);return v.set(a.subarray(0,n),0),e=new g(v),v=a.slice(n,n+s),{lengthTree:e,distanceTree:new g(v)}},t.prototype.readHuffman=function(){for(var e=this.DEF_MAX_WINDOW_SIZE-(this.mDataLength-this.mCurrentPosition),i=!1,r={};e>=this.DEF_HUFFMAN_REPEATE_MAX;){var n=void 0;for(n=this.mCurrentLengthTree.unpackSymbol(this);!(-256&n);){if(r[(this.mDataLength+1)%this.DEF_MAX_WINDOW_SIZE]=n,this.mBlockBuffer[this.mDataLength++%this.DEF_MAX_WINDOW_SIZE]=n,i=!0,--e<this.DEF_HUFFMAN_REPEATE_MAX)return!0;n=this.mCurrentLengthTree.unpackSymbol(this)}if(n<this.DEF_HUFFMAN_LENGTH_MINIMUMCODE){if(n<this.DEF_HUFFMAN_END_BLOCK)throw new DOMException("Illegal code.");var s=i?1:0;return this.mbCanReadMoreData=this.decodeBlockHeader(),!!(s|(this.mbCanReadMoreData?1:0))}if(n>this.DEF_HUFFMAN_LENGTH_MAXIMUMCODE)throw new DOMException("Illegal repeat code length.");var o=t.DEF_HUFFMAN_REPEAT_LENGTH_BASE[n-this.DEF_HUFFMAN_LENGTH_MINIMUMCODE],h=t.DEF_HUFFMAN_REPEAT_LENGTH_EXTENSION[n-this.DEF_HUFFMAN_LENGTH_MINIMUMCODE];if(h>0){if((f=this.readBits(h))<0)throw new DOMException("Wrong data.");o+=f}if((n=this.mCurrentDistanceTree.unpackSymbol(this))<0||n>t.DEF_HUFFMAN_REPEAT_DISTANCE_BASE.length)throw new DOMException("Wrong distance code.");var a=t.DEF_HUFFMAN_REPEAT_DISTANCE_BASE[n];if((h=t.DEF_HUFFMAN_REPEAT_DISTANCE_EXTENSION[n])>0){var f;if((f=this.readBits(h))<0)throw new DOMException("Wrong data.");a+=f}for(var u=0;u<o;u++)this.mBlockBuffer[this.mDataLength%this.DEF_MAX_WINDOW_SIZE]=this.mBlockBuffer[(this.mDataLength-a)%this.DEF_MAX_WINDOW_SIZE],this.mDataLength++,e--;i=!0}return i},t.prototype.read=function(t,i,r){if(null==t)throw new DOMException("buffer");if(i<0||i>t.length-1)throw new DOMException("offset","Offset does not belong to specified buffer.");if(r<0||r>t.length-i)throw new DOMException("length","Length is illegal.");for(var n=r;r>0;)if(this.mCurrentPosition<this.mDataLength){var s=this.mCurrentPosition%this.DEF_MAX_WINDOW_SIZE,o=Math.min(this.DEF_MAX_WINDOW_SIZE-s,this.mDataLength-this.mCurrentPosition);o=Math.min(o,r),e.arrayCopy(this.mBlockBuffer,s,t,i,o),this.mCurrentPosition+=o,i+=o,r-=o}else{if(!this.mbCanReadMoreData)break;var h=this.mDataLength;if(this.mbReadingUncompressed)if(0===this.mUncompressedDataLength){if(this.mbCanReadMoreData=this.decodeBlockHeader(),!this.mbCanReadMoreData)break}else{s=this.mDataLength%this.DEF_MAX_WINDOW_SIZE;var a=Math.min(this.mUncompressedDataLength,this.DEF_MAX_WINDOW_SIZE-s),f=this.readPackedBytes(this.mBlockBuffer,s,a);if(a!==f)throw new DOMException("Not enough data in stream.");this.mUncompressedDataLength-=f,this.mDataLength+=f}else if(!this.readHuffman())break;if(h<this.mDataLength){var u=h%this.DEF_MAX_WINDOW_SIZE,c=this.mDataLength%this.DEF_MAX_WINDOW_SIZE;u<c?this.checksumUpdate(this.mBlockBuffer,u,c-u):(this.checksumUpdate(this.mBlockBuffer,u,this.DEF_MAX_WINDOW_SIZE-u),c>0&&this.checksumUpdate(this.mBlockBuffer,0,c))}}if(!this.mbCanReadMoreData&&!this.mbCheckSumRead&&!this.mbNoWrap){if(this.skipToBoundary(),this.readInt32()!==this.mCheckSum)throw new DOMException("Checksum check failed.");this.mbCheckSumRead=!0}return n-r},t.prototype.readPackedBytes=function(t,i,r){if(null==t)throw new DOMException("buffer");if(i<0||i>t.length-1)throw new DOMException('offset", "Offset can not be less than zero or greater than buffer length - 1.');if(r<0)throw new DOMException('length", "Length can not be less than zero.');if(r>t.length-i)throw new DOMException('length", "Length is too large.');if(7&this.mBufferedBits)throw new DOMException("Reading of unalligned data is not supported.");if(0===r)return 0;for(var n=0;this.mBufferedBits>0&&r>0;)t[i++]=this.mBuffer,this.mBufferedBits-=8,this.mBuffer=e.bitConverterInt32ToUint(this.mBuffer>>>8),r--,n++;return r>0&&(n+=this.mInputStream.read(t,i,r)),n},t.prototype.readInt32=function(){var t=this.readBits(8)<<24;return t|=this.readBits(8)<<16,t|=this.readBits(8)<<8,t|=this.readBits(8)},t.prototype.checksumUpdate=function(t,e,i){y.ChecksumUpdate(this.mCheckSum,t,e,i)},t.DEF_REVERSE_BITS=new Uint8Array([0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15]),t.DEF_HUFFMAN_DYNTREE_REPEAT_MINIMUMS=[3,3,11],t.DEF_HUFFMAN_DYNTREE_REPEAT_BITS=[2,3,7],t.DEF_HUFFMAN_REPEAT_LENGTH_BASE=[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],t.DEF_HUFFMAN_REPEAT_LENGTH_EXTENSION=[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],t.DEF_HUFFMAN_REPEAT_DISTANCE_BASE=[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],t.DEF_HUFFMAN_REPEAT_DISTANCE_EXTENSION=[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],t}(),v=function(){function t(t){this.position=0,this.inputStream=new Uint8Array(t.buffer)}return Object.defineProperty(t.prototype,"length",{get:function(){return this.inputStream.buffer.byteLength},enumerable:!0,configurable:!0}),t.prototype.read=function(t,e,i){var r=new Uint8Array(this.inputStream.buffer,this.position+e).subarray(0,i);return t.set(r,0),this.position+=r.byteLength,r.byteLength},t.prototype.readByte=function(){return this.inputStream[this.position++]},t.prototype.write=function(t,i,r){e.arrayCopy(t,0,this.inputStream,this.position+i,r),this.position+=r},t.prototype.toByteArray=function(){return new Uint8Array(this.inputStream.buffer)},t}()})(),n})())); | ||
| !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("SyncfusionFileUtils")):"function"==typeof define&&define.amd?define(["SyncfusionFileUtils"],e):"object"==typeof exports?exports.SyncfusionCompression=e(require("SyncfusionFileUtils")):t.SyncfusionCompression=e(t.SyncfusionFileUtils)}(self,t=>(()=>{"use strict";var e={115:e=>{e.exports=t}},i={};function r(t){var n=i[t];if(void 0!==n)return n.exports;var s=i[t]={exports:{}};return e[t](s,s.exports,r),s.exports}r.d=(t,e)=>{for(var i in e)r.o(e,i)&&!r.o(t,i)&&Object.defineProperty(t,i,{enumerable:!0,get:e[i]})},r.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var n={};return(()=>{r.r(n),r.d(n,{ChecksumCalculator:()=>m,CompressedStreamReader:()=>B,CompressedStreamWriter:()=>p,CompressorHuffmanTree:()=>l,DecompressorHuffmanTree:()=>g,Stream:()=>v,Utils:()=>e,ZipArchive:()=>o,ZipArchiveItem:()=>a,ZipArchiveItemHelper:()=>h});var t=r(115),e=function(){function t(){}return t.bitReverse=function(e){return t.reverseBits[15&e]<<12|t.reverseBits[e>>4&15]<<8|t.reverseBits[e>>8&15]<<4|t.reverseBits[e>>12]},t.bitConverterToInt32=function(t,e){return t[e]|t[e+1]<<8|t[e+2]<<16|t[e+3]<<24},t.bitConverterToInt16=function(t,e){return t[e]|t[e+1]<<8},t.bitConverterToUInt32=function(t){var e=new Uint32Array(1);return e[0]=t,e[0]},t.bitConverterToUInt16=function(t,e){var i=new Uint16Array(1);return i[0]=t[e]|t[e+1]<<8,i[0]},t.bitConverterUintToInt32=function(t){var e=new Int32Array(1);return e[0]=t,e[0]},t.bitConverterInt32ToUint=function(t){var e=new Uint32Array(1);return e[0]=t,e[0]},t.bitConverterInt32ToInt16=function(t){var e=new Int16Array(1);return e[0]=t,e[0]},t.byteToString=function(t){for(var e="",i=0;i<t.length;i++)e+=String.fromCharCode(t[i]);return e},t.byteIntToString=function(t){for(var e="",i=0;i<t.length;i++)e+=String.fromCharCode(t[i]);return e},t.arrayCopy=function(t,e,i,r,n){var s=new Uint8Array(t.buffer,e).subarray(0,n);i.set(s,r)},t.mergeArray=function(t,e){var i=new Uint8Array(t.length+e.length);return i.set(t),i.set(e,t.length),i},t.encodedString=function(t){var e,i,r,n,s,o,h="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",a=0,f=0,u=3*(t=t.replace(/[^A-Za-z0-9\+\/\=]/g,"")).length/4;if(t.charAt(t.length-1)===h.charAt(64)&&u--,t.charAt(t.length-2)===h.charAt(64)&&u--,u%1!=0)throw new Error("Invalid base64 input, bad content length.");for(var c=new Uint8Array(0|u);a<t.length;)e=h.indexOf(t.charAt(a++))<<2|(n=h.indexOf(t.charAt(a++)))>>4,i=(15&n)<<4|(s=h.indexOf(t.charAt(a++)))>>2,r=(3&s)<<6|(o=h.indexOf(t.charAt(a++))),c[f++]=e,64!==s&&(c[f++]=i),64!==o&&(c[f++]=r);return c},t.reverseBits=[0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15],t.huffCodeLengthOrders=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],t}(),i=[],s=4096,o=function(){function r(){0===i.length&&r.initCrc32Table(),this.files=[],this.level="Normal",t.Save.isMicrosoftBrowser=!!navigator.msSaveBlob}return Object.defineProperty(r.prototype,"items",{get:function(){return this.files},enumerable:!0,configurable:!0}),Object.defineProperty(r.prototype,"compressionLevel",{get:function(){return this.level},set:function(t){this.level=t},enumerable:!0,configurable:!0}),Object.defineProperty(r.prototype,"length",{get:function(){return void 0===this.files?0:this.files.length},enumerable:!0,configurable:!0}),r.prototype.addItem=function(t){if(null==t)throw new Error("ArgumentException: item cannot be null or undefined");for(var e=0;e<this.files.length;e++){var i=this.files[e];if(i instanceof a&&i.name===t.name)throw new Error("item with same name already exist")}this.files.push(t)},r.prototype.addDirectory=function(t){if(null==t)throw new Error("ArgumentException: string cannot be null or undefined");if(0===t.length)throw new Error("ArgumentException: string cannot be empty");if("/"!==t.slice(-1)&&(t+="/"),-1!==this.files.indexOf(t))throw new Error("item with same name already exist");this.files.push(t)},r.prototype.getItem=function(t){if(t>=0&&t<this.files.length)return this.files[t]},r.prototype.contains=function(t){return-1!==this.files.indexOf(t)},r.prototype.open=function(t){var i=e.encodedString(t);if(0==i.length)throw new DOMException("stream");var n=new v(i),s=r.findValueFromEnd(n,101010256,65557);if(s<0)throw new DOMException("Can't locate end of central directory record. Possible wrong file format or archive is corrupt.");n.position=s+12;var o=s-r.ReadInt32(n);n.position=o,this.readCentralDirectoryDataAndExtractItems(n)},r.prototype.readCentralDirectoryDataAndExtractItems=function(t){if(null==t)throw new DOMException("stream");for(var e;33639248==r.ReadInt32(t);)(e=new h).readCentralDirectoryData(t);e.readData(t,e.checkCrc),e.decompressData(),this.files.push(new a(e.unCompressedStream.buffer,e.name))},r.prototype.save=function(t){if(null==t||0===t.length)throw new Error("ArgumentException: fileName cannot be null or undefined");if(0===this.files.length)throw new Error("InvalidOperation");var e=this;return new Promise(function(i,r){e.saveInternal(t,!1).then(function(){i(e)})})},r.prototype.saveAsBlob=function(){var t=this;return new Promise(function(e,i){t.saveInternal("",!0).then(function(t){e(t)})})},r.prototype.saveInternal=function(t,e){var i=this,r=this;return new Promise(function(n,s){for(var o=[],h=0,a=0;a<r.files.length;a++){i.getCompressedData(i.files[a]).then(function(i){if(h=r.constructZippedObject(o,i,h,i.isDirectory),o.length===r.files.length){var s=r.writeZippedContent(t,o,h,e);n(s)}})}})},r.prototype.destroy=function(){if(void 0!==this.files&&this.files.length>0){for(var t=0;t<this.files.length;t++){var e=this.files[t];e instanceof a&&e.destroy(),e=void 0}this.files=[]}this.files=void 0,this.level=void 0},r.prototype.getCompressedData=function(t){var e=this;return new Promise(function(r,n){if(t instanceof a){var s=new FileReader;s.onload=function(){var n=new Uint8Array(s.result),o={fileName:t.name,crc32Value:0,compressedData:[],compressedSize:void 0,uncompressedDataSize:n.length,compressionType:void 0,isDirectory:!1};if("Normal"===e.level){e.compressData(n,o,i);for(var h=0,a=0;a<o.compressedData.length;a++)h+=o.compressedData[a].length;o.compressedSize=h,o.compressionType="\b\0"}else o.compressedSize=n.length,o.crc32Value=e.calculateCrc32Value(0,n,i),o.compressionType="\0\0",o.compressedData.push(n);r(o)},s.readAsArrayBuffer(t.data)}else{r({fileName:t,crc32Value:0,compressedData:"",compressedSize:0,uncompressedDataSize:0,compressionType:"\0\0",isDirectory:!0})}})},r.prototype.compressData=function(t,e,i){var r=new p(!0),n=0,s=0;do{if(n>=t.length){r.close();break}s=Math.min(t.length,n+16384);var o=t.subarray(n,s);e.crc32Value=this.calculateCrc32Value(e.crc32Value,o,i),r.write(o,0,s-n),n=s}while(n<=t.length);e.compressedData=r.compressedData,r.destroy()},r.prototype.constructZippedObject=function(t,e,i,r){var n=0,s=new Date;r&&(n|=16),n|=0;var o=this.writeHeader(e,s),h="PK"+o+e.fileName,a=this.writeCentralDirectory(e,o,i,n);return t.push({localHeader:h,centralDir:a,compressedData:e}),i+h.length+e.compressedSize},r.prototype.writeHeader=function(t,e){var i="";return i+="\n\0\0\0",i+=t.compressionType,i+=this.getBytes(this.getModifiedTime(e),2),i+=this.getBytes(this.getModifiedDate(e),2),i+=this.getBytes(t.crc32Value,4),i+=this.getBytes(t.compressedSize,4),i+=this.getBytes(t.uncompressedDataSize,4),i+=this.getBytes(t.fileName.length,2),i+=this.getBytes(0,2)},r.prototype.writeZippedContent=function(e,i,r,n){for(var s=0,o=[],h=0;h<i.length;h++){var a=i[h];for(s+=a.centralDir.length,o.push(this.getArrayBuffer(a.localHeader));a.compressedData.compressedData.length;)o.push(a.compressedData.compressedData.shift().buffer)}for(h=0;h<i.length;h++)o.push(this.getArrayBuffer(i[h].centralDir));o.push(this.getArrayBuffer(this.writeFooter(i,s,r)));var f=new Blob(o,{type:"application/zip"});return n||t.Save.save(e,f),f},r.prototype.writeCentralDirectory=function(t,e,i,r){return"PK"+this.getBytes(20,2)+e+this.getBytes(0,2)+"\0\0\0\0"+this.getBytes(r,4)+this.getBytes(i,4)+t.fileName},r.prototype.writeFooter=function(t,e,i){return"PK\0\0\0\0"+this.getBytes(t.length,2)+this.getBytes(t.length,2)+this.getBytes(e,4)+this.getBytes(i,4)+this.getBytes(0,2)},r.prototype.getArrayBuffer=function(t){for(var e=new Uint8Array(t.length),i=0;i<t.length;++i)e[i]=255&t.charCodeAt(i);return e.buffer},r.prototype.getBytes=function(t,e){for(var i="",r=0;r<e;r++)i+=String.fromCharCode(255&t),t>>>=8;return i},r.prototype.getModifiedTime=function(t){var e=t.getHours();return e<<=6,e|=t.getMinutes(),(e<<=5)|t.getSeconds()/2},r.prototype.getModifiedDate=function(t){var e=t.getFullYear()-1980;return e<<=4,e|=t.getMonth()+1,(e<<=5)|t.getDate()},r.prototype.calculateCrc32Value=function(t,e,i){t^=-1;for(var r=0;r<e.length;r++)t=t>>>8^i[255&(t^e[r])];return-1^t},r.initCrc32Table=function(){for(var t,e=0;e<256;e++){t=e;for(var r=0;r<8;r++)t=1&t?3988292384^t>>>1:t>>>1;i[e]=t}},r.findValueFromEnd=function(t,e,i){if(null==t)throw new DOMException("stream");var r=t.inputStream.buffer.byteLength;if(r<4)return-1;var n=new Uint8Array(4),s=Math.max(0,r-i),o=r-1-4;t.position=o,t.read(n,0,4);var h=n[0],a=h==e;if(!a)for(;o>s;)if(h<<=8,o--,t.position=o,(h+=t.readByte())==e){a=!0;break}return a?o:-1},r.ReadInt32=function(t){var i=new Uint8Array(4);if(4!=t.read(i,0,4))throw new DOMException("Unable to read value at the specified position - end of stream was reached.");return e.bitConverterToInt32(i,0)},r.ReadInt16=function(t){var i=new Uint8Array(2);if(2!=t.read(i,0,2))throw new DOMException("Unable to read value at the specified position - end of stream was reached.");return e.bitConverterToInt16(i,0)},r.ReadUInt16=function(t){var i=new Uint8Array(2);if(2!=t.read(i,0,2))throw new DOMException("Unable to read value at the specified position - end of stream was reached.");return e.bitConverterToInt16(i,0)},r}(),h=function(){function t(){this.headerSignature=67324752,this.checkCrc=!0,this.crc32=0}return t.prototype.readCentralDirectoryData=function(t){t.position+=4,this.options=o.ReadInt16(t),this.compressionMethod=o.ReadInt16(t),this.checkCrc=99!=this.compressionMethod;o.ReadInt32(t);this.crc32=e.bitConverterToUInt32(o.ReadInt32(t)),this.compressedSize=o.ReadInt32(t),this.originalSize=o.ReadInt32(t);var i=o.ReadInt16(t),r=o.ReadInt16(t),n=o.ReadInt16(t);t.position+=4,this.externalAttributes=o.ReadInt32(t),this.localHeaderOffset=o.ReadInt32(t);var s=new Uint8Array(i);t.read(s,0,i);var h=e.byteToString(s);h=h.replace("\\","/"),this.name=h,t.position+=r+n,0!=this.options&&(this.options=0)},t.prototype.readData=function(t,e){if(0==t.length)throw new DOMException("stream");t.position=this.localHeaderOffset,this.checkCrc=e,this.readLocalHeader(t),this.readCompressedData(t)},t.prototype.decompressData=function(){8==this.compressionMethod&&this.originalSize>0&&this.decompressDataOld()},t.prototype.decompressDataOld=function(){var t,e=new B(this.compressedStream,!0);this.originalSize>0&&(t=new v(new Uint8Array(this.originalSize)));var i,r=new Uint8Array(s);for(new Uint8Array(0);(i=e.read(r,0,s))>0;)t.write(r.subarray(0,i),0,i);this.unCompressedStream=t.toByteArray(),this.checkCrc},t.prototype.readLocalHeader=function(t){if(0==t.length)throw new DOMException("stream");if(o.ReadInt32(t)!=this.headerSignature)throw new DOMException("Can't find local header signature - wrong file format or file is corrupt.");t.position+=22;var e=o.ReadInt16(t),i=o.ReadUInt16(t);if(99==this.compressionMethod);else if(i>2){if(t.position+=e,23==o.ReadInt16(t))throw new DOMException("UnSupported");t.position+=i-2}else t.position+=e+i},t.prototype.readCompressedData=function(t){var e;if(this.compressedSize>0){var i=this.compressedSize;e=new v(new Uint8Array(i));for(var r=new Uint8Array(s);i>0;){var n=Math.min(i,s);if(t.read(r,0,n)!=n)throw new DOMException("End of file reached - wrong file format or file is corrupt.");e.write(r.subarray(0,n),0,n),i-=n}this.compressedStream=new Uint8Array(e.inputStream)}else this.compressedSize<0||this.compressedSize},t}(),a=function(){function t(t,e){if(null==t)throw new Error("ArgumentException: data cannot be null or undefined");if(null==e)throw new Error("ArgumentException: string cannot be null or undefined");if(0===e.length)throw new Error("string cannot be empty");this.data=t,this.name=e}return Object.defineProperty(t.prototype,"dataStream",{get:function(){return this.decompressedStream},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"name",{get:function(){return this.fileName},set:function(t){this.fileName=t},enumerable:!0,configurable:!0}),t.prototype.destroy=function(){this.fileName=void 0,this.data=void 0},t}(),f=new Int16Array(286),u=new Uint8Array(286),c=new Int16Array(30),d=new Uint8Array(30),p=function(){function e(t){this.pendingBuffer=new Uint8Array(65536),this.pendingBufLength=0,this.pendingBufCache=0,this.pendingBufBitsInCache=0,this.bufferPosition=0,this.extraBits=0,this.currentHash=0,this.matchStart=0,this.matchLength=0,this.matchPrevAvail=!1,this.blockStart=0,this.stringStart=0,this.lookAhead=0,this.totalBytesIn=0,this.inputOffset=0,this.inputEnd=0,this.windowSize=32768,this.windowMask=this.windowSize-1,this.hashSize=32768,this.hashMask=this.hashSize-1,this.hashShift=Math.floor(17/3),this.maxDist=this.windowSize-262,this.checkSum=1,this.noWrap=!1,e.isHuffmanTreeInitiated||(e.initHuffmanTree(),e.isHuffmanTreeInitiated=!0),this.treeLiteral=new l(this,286,257,15),this.treeDistances=new l(this,30,1,15),this.treeCodeLengths=new l(this,19,4,7),this.arrDistances=new Uint16Array(16384),this.arrLiterals=new Uint8Array(16384),this.stream=[],this.dataWindow=new Uint8Array(2*this.windowSize),this.hashHead=new Int16Array(this.hashSize),this.hashPrevious=new Int16Array(this.windowSize),this.blockStart=this.stringStart=1,this.noWrap=t,t||this.writeZLibHeader()}return Object.defineProperty(e.prototype,"compressedData",{get:function(){return this.stream},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"getCompressedString",{get:function(){var t="";if(void 0!==this.stream)for(var e=0;e<this.stream.length;e++)t+=String.fromCharCode.apply(null,this.stream[e]);return t},enumerable:!0,configurable:!0}),e.prototype.write=function(e,i,r){if(null==e)throw new Error("ArgumentException: data cannot null or undefined");var n=i+r;if(0>i||i>n||n>e.length)throw new Error("ArgumentOutOfRangeException: Offset or length is incorrect");if("string"==typeof e){var s=new t.Encoding(!1);s.type="Utf8",n=i+(e=new Uint8Array(s.getBytes(e,0,e.length))).length}for(this.inputBuffer=e,this.inputOffset=i,this.inputEnd=n,this.noWrap||(this.checkSum=m.checksumUpdate(this.checkSum,this.inputBuffer,this.inputOffset,n));this.inputEnd!==this.inputOffset||0!==this.pendingBufLength;)this.pendingBufferFlush(),this.compressData(!1)},e.prototype.writeZLibHeader=function(){var t=30720;t|=64,t+=31-t%31,this.pendingBufferWriteShortBytes(t)},e.prototype.pendingBufferWriteShortBytes=function(t){this.pendingBuffer[this.pendingBufLength++]=t>>8,this.pendingBuffer[this.pendingBufLength++]=t},e.prototype.compressData=function(t){var e;do{this.fillWindow();var i=t&&this.inputEnd===this.inputOffset;e=this.compressSlow(i,t)}while(0===this.pendingBufLength&&e);return e},e.prototype.compressSlow=function(t,e){if(this.lookAhead<262&&!t)return!1;for(;this.lookAhead>=262||t;){if(0===this.lookAhead)return this.lookAheadCompleted(e);this.stringStart>=2*this.windowSize-262&&this.slideWindow();var i=this.matchStart,r=this.matchLength;if(this.lookAhead>=3&&this.discardMatch(),r>=3&&this.matchLength<=r?r=this.matchPreviousBest(i,r):this.matchPreviousAvailable(),this.bufferPosition>=16384)return this.huffmanIsFull(e)}return!0},e.prototype.discardMatch=function(){var t=this.insertString();0!==t&&this.stringStart-t<=this.maxDist&&this.findLongestMatch(t)&&this.matchLength<=5&&3===this.matchLength&&this.stringStart-this.matchStart>4096&&(this.matchLength=2)},e.prototype.matchPreviousAvailable=function(){this.matchPrevAvail&&this.huffmanTallyLit(255&this.dataWindow[this.stringStart-1]),this.matchPrevAvail=!0,this.stringStart++,this.lookAhead--},e.prototype.matchPreviousBest=function(t,e){this.huffmanTallyDist(this.stringStart-1-t,e),e-=2;do{this.stringStart++,this.lookAhead--,this.lookAhead>=3&&this.insertString()}while(--e>0);return this.stringStart++,this.lookAhead--,this.matchPrevAvail=!1,this.matchLength=2,e},e.prototype.lookAheadCompleted=function(t){return this.matchPrevAvail&&this.huffmanTallyLit(255&this.dataWindow[this.stringStart-1]),this.matchPrevAvail=!1,this.huffmanFlushBlock(this.dataWindow,this.blockStart,this.stringStart-this.blockStart,t),this.blockStart=this.stringStart,!1},e.prototype.huffmanIsFull=function(t){var e=this.stringStart-this.blockStart;this.matchPrevAvail&&e--;var i=t&&0===this.lookAhead&&!this.matchPrevAvail;return this.huffmanFlushBlock(this.dataWindow,this.blockStart,e,i),this.blockStart+=e,!i},e.prototype.fillWindow=function(){for(this.stringStart>=this.windowSize+this.maxDist&&this.slideWindow();this.lookAhead<262&&this.inputOffset<this.inputEnd;){var t=2*this.windowSize-this.lookAhead-this.stringStart;t>this.inputEnd-this.inputOffset&&(t=this.inputEnd-this.inputOffset),this.dataWindow.set(this.inputBuffer.subarray(this.inputOffset,this.inputOffset+t),this.stringStart+this.lookAhead),this.inputOffset+=t,this.totalBytesIn+=t,this.lookAhead+=t}this.lookAhead>=3&&this.updateHash()},e.prototype.slideWindow=function(){this.dataWindow.set(this.dataWindow.subarray(this.windowSize,this.windowSize+this.windowSize),0),this.matchStart-=this.windowSize,this.stringStart-=this.windowSize,this.blockStart-=this.windowSize;for(var t=0;t<this.hashSize;++t){var e=65535&this.hashHead[t];this.hashHead[t]=e>=this.windowSize?e-this.windowSize:0}for(t=0;t<this.windowSize;t++){e=65535&this.hashPrevious[t];this.hashPrevious[t]=e>=this.windowSize?e-this.windowSize:0}},e.prototype.insertString=function(){var t,e=(this.currentHash<<this.hashShift^this.dataWindow[this.stringStart+2])&this.hashMask;return this.hashPrevious[this.stringStart&this.windowMask]=t=this.hashHead[e],this.hashHead[e]=this.stringStart,this.currentHash=e,65535&t},e.prototype.findLongestMatch=function(t){var e,i=4096,r=258,n=this.stringStart,s=this.stringStart+this.matchLength,o=Math.max(this.matchLength,2),h=Math.max(this.stringStart-this.maxDist,0),a=this.stringStart+258-1,f=this.dataWindow[s-1],u=this.dataWindow[s],c=this.dataWindow;o>=32&&(i>>=2),r>this.lookAhead&&(r=this.lookAhead);do{if(c[t+o]===u&&c[t+o-1]===f&&c[t]===c[n]&&c[t+1]===c[n+1]){for(e=t+2,n+=2;c[++n]===c[++e]&&c[++n]===c[++e]&&c[++n]===c[++e]&&c[++n]===c[++e]&&c[++n]===c[++e]&&c[++n]===c[++e]&&c[++n]===c[++e]&&c[++n]===c[++e]&&n<a;);if(n>s){if(this.matchStart=t,s=n,(o=n-this.stringStart)>=r)break;f=c[s-1],u=c[s]}n=this.stringStart}}while((t=65535&this.hashPrevious[t&this.windowMask])>h&&0!==--i);return this.matchLength=Math.min(o,this.lookAhead),this.matchLength>=3},e.prototype.updateHash=function(){this.currentHash=this.dataWindow[this.stringStart]<<this.hashShift^this.dataWindow[this.stringStart+1]},e.prototype.huffmanTallyLit=function(t){return this.arrDistances[this.bufferPosition]=0,this.arrLiterals[this.bufferPosition++]=t,this.treeLiteral.codeFrequencies[t]++,this.bufferPosition>=16384},e.prototype.huffmanTallyDist=function(t,e){this.arrDistances[this.bufferPosition]=t,this.arrLiterals[this.bufferPosition++]=e-3;var i=this.huffmanLengthCode(e-3);this.treeLiteral.codeFrequencies[i]++,i>=265&&i<285&&(this.extraBits+=Math.floor((i-261)/4));var r=this.huffmanDistanceCode(t-1);return this.treeDistances.codeFrequencies[r]++,r>=4&&(this.extraBits+=Math.floor(r/2-1)),this.bufferPosition>=16384},e.prototype.huffmanFlushBlock=function(t,e,i,r){this.treeLiteral.codeFrequencies[256]++,this.treeLiteral.buildTree(),this.treeDistances.buildTree(),this.treeLiteral.calculateBLFreq(this.treeCodeLengths),this.treeDistances.calculateBLFreq(this.treeCodeLengths),this.treeCodeLengths.buildTree();for(var n=4,s=18;s>n;s--)this.treeCodeLengths.codeLengths[l.huffCodeLengthOrders[s]]>0&&(n=s+1);var o=14+3*n+this.treeCodeLengths.getEncodedLength()+this.treeLiteral.getEncodedLength()+this.treeDistances.getEncodedLength()+this.extraBits,h=this.extraBits;for(s=0;s<286;s++)h+=this.treeLiteral.codeFrequencies[s]*u[s];for(s=0;s<30;s++)h+=this.treeDistances.codeFrequencies[s]*d[s];o>=h&&(o=h),e>=0&&i+4<o>>3?this.huffmanFlushStoredBlock(t,e,i,r):o==h?(this.pendingBufferWriteBits(2+(r?1:0),3),this.treeLiteral.setStaticCodes(f,u),this.treeDistances.setStaticCodes(c,d),this.huffmanCompressBlock(),this.huffmanReset()):(this.pendingBufferWriteBits(4+(r?1:0),3),this.huffmanSendAllTrees(n),this.huffmanCompressBlock(),this.huffmanReset())},e.prototype.huffmanFlushStoredBlock=function(t,e,i,r){this.pendingBufferWriteBits(0+(r?1:0),3),this.pendingBufferAlignToByte(),this.pendingBufferWriteShort(i),this.pendingBufferWriteShort(~i),this.pendingBufferWriteByteBlock(t,e,i),this.huffmanReset()},e.prototype.huffmanLengthCode=function(t){if(255===t)return 285;for(var e=257;t>=8;)e+=4,t>>=1;return e+t},e.prototype.huffmanDistanceCode=function(t){for(var e=0;t>=4;)e+=2,t>>=1;return e+t},e.prototype.huffmanSendAllTrees=function(t){this.treeCodeLengths.buildCodes(),this.treeLiteral.buildCodes(),this.treeDistances.buildCodes(),this.pendingBufferWriteBits(this.treeLiteral.treeLength-257,5),this.pendingBufferWriteBits(this.treeDistances.treeLength-1,5),this.pendingBufferWriteBits(t-4,4);for(var e=0;e<t;e++)this.pendingBufferWriteBits(this.treeCodeLengths.codeLengths[l.huffCodeLengthOrders[e]],3);this.treeLiteral.writeTree(this.treeCodeLengths),this.treeDistances.writeTree(this.treeCodeLengths)},e.prototype.huffmanReset=function(){this.bufferPosition=0,this.extraBits=0,this.treeLiteral.reset(),this.treeDistances.reset(),this.treeCodeLengths.reset()},e.prototype.huffmanCompressBlock=function(){for(var t=0;t<this.bufferPosition;t++){var e=255&this.arrLiterals[t],i=this.arrDistances[t];if(0!==i--){var r=this.huffmanLengthCode(e);this.treeLiteral.writeCodeToStream(r);var n=Math.floor((r-261)/4);n>0&&n<=5&&this.pendingBufferWriteBits(e&(1<<n)-1,n);var s=this.huffmanDistanceCode(i);this.treeDistances.writeCodeToStream(s),(n=Math.floor(s/2-1))>0&&this.pendingBufferWriteBits(i&(1<<n)-1,n)}else this.treeLiteral.writeCodeToStream(e)}this.treeLiteral.writeCodeToStream(256)},e.prototype.pendingBufferWriteBits=function(t,e){var i=new Uint32Array(1);i[0]=this.pendingBufCache|t<<this.pendingBufBitsInCache,this.pendingBufCache=i[0],this.pendingBufBitsInCache+=e,this.pendingBufferFlushBits()},e.prototype.pendingBufferFlush=function(t){if(this.pendingBufferFlushBits(),this.pendingBufLength>0){var e=new Uint8Array(this.pendingBufLength);e.set(this.pendingBuffer.subarray(0,this.pendingBufLength),0),this.stream.push(e)}this.pendingBufLength=0},e.prototype.pendingBufferFlushBits=function(){for(var t=0;this.pendingBufBitsInCache>=8&&this.pendingBufLength<65536;)this.pendingBuffer[this.pendingBufLength++]=this.pendingBufCache,this.pendingBufCache>>=8,this.pendingBufBitsInCache-=8,t++;return t},e.prototype.pendingBufferWriteByteBlock=function(t,e,i){var r=t.subarray(e,e+i);this.pendingBuffer.set(r,this.pendingBufLength),this.pendingBufLength+=i},e.prototype.pendingBufferWriteShort=function(t){this.pendingBuffer[this.pendingBufLength++]=t,this.pendingBuffer[this.pendingBufLength++]=t>>8},e.prototype.pendingBufferAlignToByte=function(){this.pendingBufBitsInCache>0&&(this.pendingBuffer[this.pendingBufLength++]=this.pendingBufCache),this.pendingBufCache=0,this.pendingBufBitsInCache=0},e.initHuffmanTree=function(){for(var t=0;t<144;)f[t]=l.bitReverse(48+t<<8),u[t++]=8;for(;t<256;)f[t]=l.bitReverse(256+t<<7),u[t++]=9;for(;t<280;)f[t]=l.bitReverse(-256+t<<9),u[t++]=7;for(;t<286;)f[t]=l.bitReverse(-88+t<<8),u[t++]=8;for(t=0;t<30;t++)c[t]=l.bitReverse(t<<11),d[t]=5},e.prototype.close=function(){do{this.pendingBufferFlush(!0),this.compressData(!0)||(this.pendingBufferFlush(!0),this.pendingBufferAlignToByte(),this.noWrap||(this.pendingBufferWriteShortBytes(this.checkSum>>16),this.pendingBufferWriteShortBytes(65535&this.checkSum)),this.pendingBufferFlush(!0))}while(this.inputEnd!==this.inputOffset||0!==this.pendingBufLength)},e.prototype.destroy=function(){this.stream=[],this.stream=void 0,this.pendingBuffer=void 0,this.treeLiteral=void 0,this.treeDistances=void 0,this.treeCodeLengths=void 0,this.arrLiterals=void 0,this.arrDistances=void 0,this.hashHead=void 0,this.hashPrevious=void 0,this.dataWindow=void 0,this.inputBuffer=void 0,this.pendingBufLength=void 0,this.pendingBufCache=void 0,this.pendingBufBitsInCache=void 0,this.bufferPosition=void 0,this.extraBits=void 0,this.currentHash=void 0,this.matchStart=void 0,this.matchLength=void 0,this.matchPrevAvail=void 0,this.blockStart=void 0,this.stringStart=void 0,this.lookAhead=void 0,this.totalBytesIn=void 0,this.inputOffset=void 0,this.inputEnd=void 0,this.windowSize=void 0,this.windowMask=void 0,this.hashSize=void 0,this.hashMask=void 0,this.hashShift=void 0,this.maxDist=void 0,this.checkSum=void 0,this.noWrap=void 0},e.isHuffmanTreeInitiated=!1,e}(),l=function(){function t(t,e,i,r){this.writer=t,this.codeMinCount=i,this.maxLength=r,this.codeFrequency=new Uint16Array(e),this.lengthCount=new Int32Array(r)}return Object.defineProperty(t.prototype,"treeLength",{get:function(){return this.codeCount},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"codeLengths",{get:function(){return this.codeLength},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"codeFrequencies",{get:function(){return this.codeFrequency},enumerable:!0,configurable:!0}),t.prototype.setStaticCodes=function(t,e){var i=new Int16Array(t.length);i.set(t,0),this.codes=i;var r=new Uint8Array(e.length);r.set(e,0),this.codeLength=r},t.prototype.reset=function(){for(var t=0;t<this.codeFrequency.length;t++)this.codeFrequency[t]=0;this.codes=void 0,this.codeLength=void 0},t.prototype.writeCodeToStream=function(t){this.writer.pendingBufferWriteBits(65535&this.codes[t],this.codeLength[t])},t.prototype.buildCodes=function(){var e=new Int32Array(this.maxLength);this.codes=new Int16Array(this.codeCount);for(var i=0,r=0;r<this.maxLength;r++)e[r]=i,i+=this.lengthCount[r]<<15-r;for(var n=0;n<this.codeCount;n++){var s=this.codeLength[n];s>0&&(this.codes[n]=t.bitReverse(e[s-1]),e[s-1]+=1<<16-s)}},t.bitReverse=function(e){return t.reverseBits[15&e]<<12|t.reverseBits[e>>4&15]<<8|t.reverseBits[e>>8&15]<<4|t.reverseBits[e>>12]},t.prototype.getEncodedLength=function(){for(var t=0,e=0;e<this.codeFrequency.length;e++)t+=this.codeFrequency[e]*this.codeLength[e];return t},t.prototype.calculateBLFreq=function(t){for(var e,i,r,n=-1,s=0;s<this.codeCount;){r=1;var o=this.codeLength[s];for(0===o?(e=138,i=3):(e=6,i=3,n!==o&&(t.codeFrequency[o]++,r=0)),n=o,s++;s<this.codeCount&&n===this.codeLength[s]&&(s++,!(++r>=e)););r<i?t.codeFrequency[n]+=r:0!==n?t.codeFrequency[16]++:r<=10?t.codeFrequency[17]++:t.codeFrequency[18]++}},t.prototype.writeTree=function(t){for(var e,i,r,n=-1,s=0;s<this.codeCount;){r=1;var o=this.codeLength[s];for(0===o?(e=138,i=3):(e=6,i=3,n!==o&&(t.writeCodeToStream(o),r=0)),n=o,s++;s<this.codeCount&&n===this.codeLength[s]&&(s++,!(++r>=e)););if(r<i)for(;r-- >0;)t.writeCodeToStream(n);else 0!==n?(t.writeCodeToStream(16),this.writer.pendingBufferWriteBits(r-3,2)):r<=10?(t.writeCodeToStream(17),this.writer.pendingBufferWriteBits(r-3,3)):(t.writeCodeToStream(18),this.writer.pendingBufferWriteBits(r-11,7))}},t.prototype.buildTree=function(){for(var t=this.codeFrequency.length,e=new Int32Array(t),i=0,r=0,n=0;n<t;n++){var s=this.codeFrequency[n];if(0!==s){for(var o=i++,h=0;o>0&&this.codeFrequency[e[h=Math.floor((o-1)/2)]]>s;)e[o]=e[h],o=h;e[o]=n,r=n}}for(;i<2;)e[i++]=r<2?++r:0;this.codeCount=Math.max(r+1,this.codeMinCount);for(var a=i,f=new Int32Array(4*i-2),u=new Int32Array(2*i-1),c=0;c<i;c++){var d=e[c],p=2*c;f[p]=d,f[p+1]=-1,u[c]=this.codeFrequency[d]<<8,e[c]=c}this.constructHuffmanTree(e,i,u,a,f),this.buildLength(f)},t.prototype.constructHuffmanTree=function(t,e,i,r,n){do{for(var s=t[0],o=t[--e],h=i[o],a=0,f=1;f<e;)f+1<e&&i[t[f]]>i[t[f+1]]&&f++,t[a]=t[f],f=2*(a=f)+1;for(;(f=a)>0&&i[t[a=Math.floor((f-1)/2)]]>h;)t[f]=t[a];t[f]=o;var u=t[0];n[2*(o=r++)]=s,n[2*o+1]=u;var c=Math.min(255&i[s],255&i[u]);for(i[o]=h=i[s]+i[u]-c+1,a=0,f=1;f<e;)f+1<e&&i[t[f]]>i[t[f+1]]&&f++,t[a]=t[f],f=2*(a=f)+1;for(;(f=a)>0&&i[t[a=Math.floor((f-1)/2)]]>h;)t[f]=t[a];t[f]=o}while(e>1)},t.prototype.buildLength=function(t){this.codeLength=new Uint8Array(this.codeFrequency.length);for(var e=Math.floor(t.length/2),i=Math.floor((e+1)/2),r=0,n=0;n<this.maxLength;n++)this.lengthCount[n]=0;if(0!==(r=this.calculateOptimalCodeLength(t,r,e))){var s=this.maxLength-1;do{for(;0===this.lengthCount[--s];);do{this.lengthCount[s]--,this.lengthCount[++s]++,r-=1<<this.maxLength-1-s}while(r>0&&s<this.maxLength-1)}while(r>0);this.recreateTree(t,r,i)}},t.prototype.recreateTree=function(t,e,i){this.lengthCount[this.maxLength-1]+=e,this.lengthCount[this.maxLength-2]-=e;for(var r=2*i,n=this.maxLength;0!==n;n--)for(var s=this.lengthCount[n-1];s>0;){var o=2*t[r++];-1===t[o+1]&&(this.codeLength[t[o]]=n,s--)}},t.prototype.calculateOptimalCodeLength=function(t,e,i){var r=new Int32Array(i);r[i-1]=0;for(var n=i-1;n>=0;n--){var s=2*n+1;if(-1!==t[s]){(o=r[n]+1)>this.maxLength&&(o=this.maxLength,e++),r[t[s-1]]=r[t[s]]=o}else{var o=r[n];this.lengthCount[o-1]++,this.codeLength[t[s-1]]=r[n]}}return e},t.reverseBits=[0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15],t.huffCodeLengthOrders=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],t}(),m=function(){function t(){}return t.checksumUpdate=function(e,i,r,n){var s=new Uint32Array(1);s[0]=e;for(var o=s[0],h=s[0]=65535&o,a=s[0]=o>>t.checkSumBitOffset;n>0;){var f=Math.min(n,t.checksumIterationCount);for(n-=f;--f>=0;)a+=h+=s[0]=255&i[r++];h%=t.checksumBase,a%=t.checksumBase}return o=a<<t.checkSumBitOffset|h},t.checkSumBitOffset=16,t.checksumBase=65521,t.checksumIterationCount=3800,t}(),g=function(){function t(t){this.buildTree(t)}return t.init=function(){var e,i;for(e=new Uint8Array(288),i=0;i<144;)e[i++]=8;for(;i<256;)e[i++]=9;for(;i<280;)e[i++]=7;for(;i<288;)e[i++]=8;for(t.m_LengthTree=new t(e),e=new Uint8Array(32),i=0;i<32;)e[i++]=5;t.m_DistanceTree=new t(e)},t.prototype.prepareData=function(e,i,r){for(var n=0,s=512,o=0;o<r.length;o++){var h=r[o];h>0&&e[h]++}for(var a=1;a<=t.MAX_BITLEN;a++){if(i[a]=n,n+=e[a]<<16-a,a>=10)s+=(130944&n)-(130944&i[a])>>16-a}return{code:n,treeSize:s}},t.prototype.treeFromData=function(i,r,n,s,o){for(var h=new Int16Array(o),a=512,f=t.MAX_BITLEN;f>=10;f--)for(var u=130944&s,c=130944&(s-=i[f]<<16-f);c<u;c+=128)h[e.bitReverse(c)]=e.bitConverterInt32ToInt16(-a<<4|f),a+=1<<f-9;for(c=0;c<n.length;c++){if(0!=(f=n[c])){s=r[f];var d=e.bitReverse(s);if(f<=9)do{h[d]=e.bitConverterInt32ToInt16(c<<4|f),d+=1<<f}while(d<512);else{var p=h[511&d],l=1<<(15&p);p=-(p>>4);do{h[p|d>>9]=e.bitConverterInt32ToInt16(c<<4|f),d+=1<<f}while(d<l)}r[f]=s+(1<<16-f)}}return h},t.prototype.buildTree=function(t){var e=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],i=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],r=this.prepareData(e,i,t);this.m_Tree=this.treeFromData(e,i,t,r.code,r.treeSize)},t.prototype.unpackSymbol=function(t){var e,i;if((e=t.peekBits(9))>=0){if((i=this.m_Tree[e])>=0)return t.skipBits(15&i),i>>4;var r=-(i>>4),n=15&i;if((e=t.peekBits(n))>=0)return i=this.m_Tree[r|e>>9],t.skipBits(15&i),i>>4;var s=t.availableBits;return e=t.peekBits(s),(15&(i=this.m_Tree[r|e>>9]))<=s?(t.skipBits(15&i),i>>4):-1}s=t.availableBits;return e=t.peekBits(s),(i=this.m_Tree[e])>=0&&(15&i)<=s?(t.skipBits(15&i),i>>4):-1},Object.defineProperty(t,"lengthTree",{get:function(){return this.m_LengthTree},enumerable:!0,configurable:!0}),Object.defineProperty(t,"distanceTree",{get:function(){return this.m_DistanceTree},enumerable:!0,configurable:!0}),t.MAX_BITLEN=15,t}(),y=function(){function t(){}return t.ChecksumUpdate=function(t,e,i,r){for(var n=t,s=65535&n,o=n>>this.DEF_CHECKSUM_BIT_OFFSET;r>0;){var h=Math.min(r,this.DEF_CHECKSUM_ITERATIONSCOUNT);for(r-=h;--h>=0;)o+=s+=255&e[i++];s%=this.DEF_CHECKSUM_BASE,o%=this.DEF_CHECKSUM_BASE}t=n=o<<this.DEF_CHECKSUM_BIT_OFFSET|s},t.ChecksumGenerate=function(e,i,r){return t.ChecksumUpdate(1,e,i,r),1},t.DEF_CHECKSUM_BIT_OFFSET=16,t.DEF_CHECKSUM_BASE=65521,t.DEF_CHECKSUM_ITERATIONSCOUNT=3800,t}(),B=function(){function t(t,e){if(this.defaultHuffmanDynamicTree=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],this.DEF_HEADER_METHOD_MASK=3840,this.DEF_HEADER_INFO_MASK=61440,this.DEF_HEADER_FLAGS_FCHECK=31,this.DEF_HEADER_FLAGS_FDICT=32,this.DEF_HEADER_FLAGS_FLEVEL=192,this.DEF_MAX_WINDOW_SIZE=65535,this.DEF_HUFFMAN_REPEATE_MAX=258,this.DEF_HUFFMAN_END_BLOCK=256,this.DEF_HUFFMAN_LENGTH_MINIMUMCODE=257,this.DEF_HUFFMAN_LENGTH_MAXIMUMCODE=285,this.DEF_HUFFMAN_DISTANCE_MAXIMUMCODE=29,this.mCheckSum=1,this.tBuffer=0,this.mBufferedBits=0,this.mTempBuffer=new Uint8Array(4),this.mBlockBuffer=new Uint8Array(this.DEF_MAX_WINDOW_SIZE),this.mbNoWrap=!1,this.mWindowSize=0,this.mCurrentPosition=0,this.mDataLength=0,this.mbCanReadNextBlock=!0,this.mbCanReadMoreData=!0,this.mbCheckSumRead=!1,null==t)throw new DOMException("stream");if(0===t.length)throw new DOMException("stream - string can not be empty");g.init(),this.mInputStream=new v(t),this.mbNoWrap=e,this.mbNoWrap||this.readZLibHeader(),this.decodeBlockHeader()}return Object.defineProperty(t.prototype,"mBuffer",{get:function(){return this.tBuffer},set:function(t){this.tBuffer=t},enumerable:!0,configurable:!0}),t.prototype.peekBits=function(t){if(t<0)throw new DOMException("count","Bits count can not be less than zero.");if(t>32)throw new DOMException("count","Count of bits is too large.");if(this.mBufferedBits<t&&this.fillBuffer(),this.mBufferedBits<t)return-1;var i=~(4294967295<<t);return e.bitConverterUintToInt32(this.mBuffer&i)},t.prototype.fillBuffer=function(){var t=4-(this.mBufferedBits>>3)-(7&this.mBufferedBits?1:0);if(0!==t)for(var i=this.mInputStream.read(this.mTempBuffer,0,t),r=0;r<i;r++)this.mBuffer=e.bitConverterInt32ToUint(this.mBuffer|e.bitConverterInt32ToUint(this.mTempBuffer[r]<<this.mBufferedBits)),this.mBufferedBits+=8},t.prototype.skipBits=function(t){if(t<0)throw new DOMException("count","Bits count can not be less than zero.");0!==t&&(t>=this.mBufferedBits?(t-=this.mBufferedBits,this.mBufferedBits=0,this.mBuffer=0,t>0&&(this.mInputStream.position+=t>>3,(t&=7)>0&&(this.fillBuffer(),this.mBufferedBits-=t,this.mBuffer=e.bitConverterInt32ToUint(this.mBuffer>>>t)))):(this.mBufferedBits-=t,this.mBuffer=e.bitConverterInt32ToUint(this.mBuffer>>>t)))},Object.defineProperty(t.prototype,"availableBits",{get:function(){return this.mBufferedBits},enumerable:!0,configurable:!0}),t.prototype.readZLibHeader=function(){var t=this.readInt16();if(-1===t)throw new DOMException("Header of the stream can not be read.");if(t%31!=0)throw new DOMException("Header checksum illegal");if(2048!==(t&this.DEF_HEADER_METHOD_MASK))throw new DOMException("Unsupported compression method.");if(this.mWindowSize=Math.pow(2,8+((t&this.DEF_HEADER_INFO_MASK)>>12)),this.mWindowSize>65535)throw new DOMException("Unsupported window size for deflate compression method.");if((t&this.DEF_HEADER_FLAGS_FDICT)>>5==1)throw new DOMException("Custom dictionary is not supported at the moment.")},t.prototype.readInt16=function(){var t=this.readBits(8)<<8;return t|=this.readBits(8)},t.prototype.readBits=function(t){var i=this.peekBits(t);return-1===i?-1:(this.mBufferedBits-=t,this.mBuffer=e.bitConverterInt32ToUint(this.mBuffer>>>t),i)},t.prototype.decodeBlockHeader=function(){if(!this.mbCanReadNextBlock)return!1;var t=this.readBits(1);if(-1===t)return!1;var e=this.readBits(2);if(-1===e)return!1;switch(this.mbCanReadNextBlock=0===t,e){case 0:this.mbReadingUncompressed=!0,this.skipToBoundary();var i=this.readInt16Inverted();if(i!==(65535^this.readInt16Inverted()))throw new DOMException("Wrong block length.");if(i>65535)throw new DOMException("Uncompressed block length can not be more than 65535.");this.mUncompressedDataLength=i,this.mCurrentLengthTree=null,this.mCurrentDistanceTree=null;break;case 1:this.mbReadingUncompressed=!1,this.mUncompressedDataLength=-1,this.mCurrentLengthTree=g.lengthTree,this.mCurrentDistanceTree=g.distanceTree;break;case 2:this.mbReadingUncompressed=!1,this.mUncompressedDataLength=-1;var r=this.decodeDynamicHeader(this.mCurrentLengthTree,this.mCurrentDistanceTree);this.mCurrentLengthTree=r.lengthTree,this.mCurrentDistanceTree=r.distanceTree;break;default:throw new DOMException("Wrong block type.")}return!0},t.prototype.skipToBoundary=function(){this.mBuffer=e.bitConverterInt32ToUint(this.mBuffer>>>(7&this.mBufferedBits)),this.mBufferedBits&=-8},t.prototype.readInt16Inverted=function(){var t=this.readBits(8);return t|=this.readBits(8)<<8},t.prototype.decodeDynamicHeader=function(e,i){var r=0,n=this.readBits(5),s=this.readBits(5),o=this.readBits(4);if(n<0||s<0||o<0)throw new DOMException("Wrong dynamic huffman codes.");var h=(n+=257)+(s+=1),a=new Uint8Array(h),f=new Uint8Array(19);o+=4;for(var u=0;u<o;){var c=this.readBits(3);if(c<0)throw new DOMException("Wrong dynamic huffman codes.");f[this.defaultHuffmanDynamicTree[u++]]=c}var d=new g(f);for(u=0;;){var p=void 0,l=!1;for(p=d.unpackSymbol(this);!(-16&p);){if(a[u++]=r=p,u===h){l=!0;break}p=d.unpackSymbol(this)}if(l)break;if(p<0)throw new DOMException("Wrong dynamic huffman codes.");if(p>=17)r=0;else if(0===u)throw new DOMException("Wrong dynamic huffman codes.");var m=p-16,y=t.DEF_HUFFMAN_DYNTREE_REPEAT_BITS[m],B=this.readBits(y);if(B<0)throw new DOMException("Wrong dynamic huffman codes.");if(u+(B+=t.DEF_HUFFMAN_DYNTREE_REPEAT_MINIMUMS[m])>h)throw new DOMException("Wrong dynamic huffman codes.");for(;B-- >0;)a[u++]=r;if(u===h)break}var v=new Uint8Array(n);return v.set(a.subarray(0,n),0),e=new g(v),v=a.slice(n,n+s),{lengthTree:e,distanceTree:new g(v)}},t.prototype.readHuffman=function(){for(var e=this.DEF_MAX_WINDOW_SIZE-(this.mDataLength-this.mCurrentPosition),i=!1,r={};e>=this.DEF_HUFFMAN_REPEATE_MAX;){var n=void 0;for(n=this.mCurrentLengthTree.unpackSymbol(this);!(-256&n);){if(r[(this.mDataLength+1)%this.DEF_MAX_WINDOW_SIZE]=n,this.mBlockBuffer[this.mDataLength++%this.DEF_MAX_WINDOW_SIZE]=n,i=!0,--e<this.DEF_HUFFMAN_REPEATE_MAX)return!0;n=this.mCurrentLengthTree.unpackSymbol(this)}if(n<this.DEF_HUFFMAN_LENGTH_MINIMUMCODE){if(n<this.DEF_HUFFMAN_END_BLOCK)throw new DOMException("Illegal code.");var s=i?1:0;return this.mbCanReadMoreData=this.decodeBlockHeader(),!!(s|(this.mbCanReadMoreData?1:0))}if(n>this.DEF_HUFFMAN_LENGTH_MAXIMUMCODE)throw new DOMException("Illegal repeat code length.");var o=t.DEF_HUFFMAN_REPEAT_LENGTH_BASE[n-this.DEF_HUFFMAN_LENGTH_MINIMUMCODE],h=t.DEF_HUFFMAN_REPEAT_LENGTH_EXTENSION[n-this.DEF_HUFFMAN_LENGTH_MINIMUMCODE];if(h>0){if((f=this.readBits(h))<0)throw new DOMException("Wrong data.");o+=f}if((n=this.mCurrentDistanceTree.unpackSymbol(this))<0||n>t.DEF_HUFFMAN_REPEAT_DISTANCE_BASE.length)throw new DOMException("Wrong distance code.");var a=t.DEF_HUFFMAN_REPEAT_DISTANCE_BASE[n];if((h=t.DEF_HUFFMAN_REPEAT_DISTANCE_EXTENSION[n])>0){var f;if((f=this.readBits(h))<0)throw new DOMException("Wrong data.");a+=f}for(var u=0;u<o;u++)this.mBlockBuffer[this.mDataLength%this.DEF_MAX_WINDOW_SIZE]=this.mBlockBuffer[(this.mDataLength-a)%this.DEF_MAX_WINDOW_SIZE],this.mDataLength++,e--;i=!0}return i},t.prototype.read=function(t,i,r){if(null==t)throw new DOMException("buffer");if(i<0||i>t.length-1)throw new DOMException("offset","Offset does not belong to specified buffer.");if(r<0||r>t.length-i)throw new DOMException("length","Length is illegal.");for(var n=r;r>0;)if(this.mCurrentPosition<this.mDataLength){var s=this.mCurrentPosition%this.DEF_MAX_WINDOW_SIZE,o=Math.min(this.DEF_MAX_WINDOW_SIZE-s,this.mDataLength-this.mCurrentPosition);o=Math.min(o,r),e.arrayCopy(this.mBlockBuffer,s,t,i,o),this.mCurrentPosition+=o,i+=o,r-=o}else{if(!this.mbCanReadMoreData)break;var h=this.mDataLength;if(this.mbReadingUncompressed)if(0===this.mUncompressedDataLength){if(this.mbCanReadMoreData=this.decodeBlockHeader(),!this.mbCanReadMoreData)break}else{s=this.mDataLength%this.DEF_MAX_WINDOW_SIZE;var a=Math.min(this.mUncompressedDataLength,this.DEF_MAX_WINDOW_SIZE-s),f=this.readPackedBytes(this.mBlockBuffer,s,a);if(a!==f)throw new DOMException("Not enough data in stream.");this.mUncompressedDataLength-=f,this.mDataLength+=f}else if(!this.readHuffman())break;if(h<this.mDataLength){var u=h%this.DEF_MAX_WINDOW_SIZE,c=this.mDataLength%this.DEF_MAX_WINDOW_SIZE;u<c?this.checksumUpdate(this.mBlockBuffer,u,c-u):(this.checksumUpdate(this.mBlockBuffer,u,this.DEF_MAX_WINDOW_SIZE-u),c>0&&this.checksumUpdate(this.mBlockBuffer,0,c))}}if(!this.mbCanReadMoreData&&!this.mbCheckSumRead&&!this.mbNoWrap){if(this.skipToBoundary(),this.readInt32()!==this.mCheckSum)throw new DOMException("Checksum check failed.");this.mbCheckSumRead=!0}return n-r},t.prototype.readPackedBytes=function(t,i,r){if(null==t)throw new DOMException("buffer");if(i<0||i>t.length-1)throw new DOMException('offset", "Offset can not be less than zero or greater than buffer length - 1.');if(r<0)throw new DOMException('length", "Length can not be less than zero.');if(r>t.length-i)throw new DOMException('length", "Length is too large.');if(7&this.mBufferedBits)throw new DOMException("Reading of unalligned data is not supported.");if(0===r)return 0;for(var n=0;this.mBufferedBits>0&&r>0;)t[i++]=this.mBuffer,this.mBufferedBits-=8,this.mBuffer=e.bitConverterInt32ToUint(this.mBuffer>>>8),r--,n++;return r>0&&(n+=this.mInputStream.read(t,i,r)),n},t.prototype.readInt32=function(){var t=this.readBits(8)<<24;return t|=this.readBits(8)<<16,t|=this.readBits(8)<<8,t|=this.readBits(8)},t.prototype.checksumUpdate=function(t,e,i){y.ChecksumUpdate(this.mCheckSum,t,e,i)},t.DEF_REVERSE_BITS=new Uint8Array([0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15]),t.DEF_HUFFMAN_DYNTREE_REPEAT_MINIMUMS=[3,3,11],t.DEF_HUFFMAN_DYNTREE_REPEAT_BITS=[2,3,7],t.DEF_HUFFMAN_REPEAT_LENGTH_BASE=[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],t.DEF_HUFFMAN_REPEAT_LENGTH_EXTENSION=[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],t.DEF_HUFFMAN_REPEAT_DISTANCE_BASE=[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],t.DEF_HUFFMAN_REPEAT_DISTANCE_EXTENSION=[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],t}(),v=function(){function t(t){this.position=0,this.inputStream=new Uint8Array(t.buffer)}return Object.defineProperty(t.prototype,"length",{get:function(){return this.inputStream.buffer.byteLength},enumerable:!0,configurable:!0}),t.prototype.read=function(t,e,i){var r=new Uint8Array(this.inputStream.buffer,this.position+e).subarray(0,i);return t.set(r,0),this.position+=r.byteLength,r.byteLength},t.prototype.readByte=function(){return this.inputStream[this.position++]},t.prototype.write=function(t,i,r){e.arrayCopy(t,0,this.inputStream,this.position+i,r),this.position+=r},t.prototype.toByteArray=function(){return new Uint8Array(this.inputStream.buffer)},t}()})(),n})()); |
| /*! | ||
| * filename: ej2-compression.umd.min.js | ||
| * version : 31.2.2 | ||
| * version : 31.2.12 | ||
| * Copyright Syncfusion Inc. 2001 - 2025. All rights reserved. | ||
@@ -5,0 +5,0 @@ * Use of this code is subject to the terms of our license. |
| /*! | ||
| * filename: ej2-compression.min.js | ||
| * version : 31.2.2 | ||
| * version : 31.2.12 | ||
| * Copyright Syncfusion Inc. 2001 - 2025. All rights reserved. | ||
@@ -5,0 +5,0 @@ * Use of this code is subject to the terms of our license. |
| /*! | ||
| * filename: index.d.ts | ||
| * version : 31.2.2 | ||
| * version : 31.2.12 | ||
| * Copyright Syncfusion Inc. 2001 - 2025. All rights reserved. | ||
@@ -5,0 +5,0 @@ * Use of this code is subject to the terms of our license. |
+7
-46
| { | ||
| "_from": "@syncfusion/ej2-compression@*", | ||
| "_id": "@syncfusion/ej2-compression@31.1.1", | ||
| "_inBundle": false, | ||
| "_integrity": "sha512-ALmywvzduNe305dopQ5SGBMEnw2VHn9ZNDTbeemXUZVkzb2mHew7NVuSLaE3rVpH+CNLna1hizLEvJAhCicxuQ==", | ||
| "_location": "/@syncfusion/ej2-compression", | ||
| "_phantomChildren": {}, | ||
| "_requested": { | ||
| "type": "range", | ||
| "registry": true, | ||
| "raw": "@syncfusion/ej2-compression@*", | ||
| "name": "@syncfusion/ej2-compression", | ||
| "escapedName": "@syncfusion%2fej2-compression", | ||
| "scope": "@syncfusion", | ||
| "rawSpec": "*", | ||
| "saveSpec": null, | ||
| "fetchSpec": "*" | ||
| }, | ||
| "_requiredBy": [ | ||
| "/", | ||
| "/@syncfusion/ej2", | ||
| "/@syncfusion/ej2-documenteditor", | ||
| "/@syncfusion/ej2-excel-export", | ||
| "/@syncfusion/ej2-grids", | ||
| "/@syncfusion/ej2-heatmap", | ||
| "/@syncfusion/ej2-maps", | ||
| "/@syncfusion/ej2-pdf", | ||
| "/@syncfusion/ej2-pdf-data-extract", | ||
| "/@syncfusion/ej2-pdf-export", | ||
| "/@syncfusion/ej2-pivotview", | ||
| "/@syncfusion/ej2-treemap" | ||
| ], | ||
| "_resolved": "https://nexus.syncfusioninternal.com/repository/ej2-release/@syncfusion/ej2-compression/-/ej2-compression-31.1.1.tgz", | ||
| "_shasum": "1db4db5b09f8cbbb7ae35f86c705f49873e2f77d", | ||
| "_spec": "@syncfusion/ej2-compression@*", | ||
| "_where": "D:\\SF3992\\WFH\\Nexus\\release", | ||
| "author": { | ||
| "name": "Syncfusion Inc." | ||
| }, | ||
| "bundleDependencies": false, | ||
| "name": "@syncfusion/ej2-compression", | ||
| "version": "31.2.12", | ||
| "description": "Essential JS 2 Compression library", | ||
| "author": "Syncfusion Inc.", | ||
| "license": "SEE LICENSE IN license", | ||
| "dependencies": { | ||
| "@syncfusion/ej2-file-utils": "~31.2.2" | ||
| "@syncfusion/ej2-file-utils": "~31.2.12" | ||
| }, | ||
| "deprecated": false, | ||
| "description": "Essential JS 2 Compression library", | ||
| "devDependencies": {}, | ||
| "es2015": "./dist/es6/ej2-compression.es5.js", | ||
| "license": "SEE LICENSE IN license", | ||
| "main": "./dist/ej2-compression.umd.min.js", | ||
| "module": "./index.js", | ||
| "name": "@syncfusion/ej2-compression", | ||
| "es2015": "./dist/es6/ej2-compression.es5.js", | ||
| "typings": "index.d.ts", | ||
| "version": "31.2.2", | ||
| "sideEffects": false, | ||
| "homepage": "https://www.syncfusion.com/javascript-ui-controls" | ||
| } |
| export declare class ChecksumCalculator { | ||
| private static DEF_CHECKSUM_BIT_OFFSET; | ||
| private static DEF_CHECKSUM_BASE; | ||
| private static DEF_CHECKSUM_ITERATIONSCOUNT; | ||
| static ChecksumUpdate(checksum: number, buffer: Uint8Array, offset: number, length: number): void; | ||
| static ChecksumGenerate(buffer: Uint8Array, offset: number, length: number): number; | ||
| } |
| /* eslint-disable */ | ||
| /// <summary> | ||
| /// Checksum calculator, based on Adler32 algorithm. | ||
| /// </summary> | ||
| export class ChecksumCalculator { | ||
| /// <summary> | ||
| /// Bits offset, used in adler checksum calculation. | ||
| /// </summary> | ||
| private static DEF_CHECKSUM_BIT_OFFSET: number = 16; | ||
| /// <summary> | ||
| /// Lagrest prime, less than 65535 | ||
| /// </summary> | ||
| private static DEF_CHECKSUM_BASE: number = 65521; | ||
| /// <summary> | ||
| /// Count of iteration used in calculated of the adler checksumm. | ||
| /// </summary> | ||
| private static DEF_CHECKSUM_ITERATIONSCOUNT: number = 3800; | ||
| /// <summary> | ||
| /// Updates checksum by calculating checksum of the | ||
| /// given buffer and adding it to current value. | ||
| /// </summary> | ||
| /// <param name="checksum">Current checksum.</param> | ||
| /// <param name="buffer">Data byte array.</param> | ||
| /// <param name="offset">Offset in the buffer.</param> | ||
| /// <param name="length">Length of data to be used from the stream.</param> | ||
| public static ChecksumUpdate(checksum: number, buffer: Uint8Array, offset: number, length: number): void { | ||
| let checkSumUInt: number = checksum; | ||
| let s1: number = checkSumUInt & 65535; | ||
| let s2: number = checkSumUInt >> this.DEF_CHECKSUM_BIT_OFFSET; | ||
| while (length > 0) { | ||
| let steps: number = Math.min(length, this.DEF_CHECKSUM_ITERATIONSCOUNT); | ||
| length -= steps; | ||
| while (--steps >= 0) { | ||
| s1 = s1 + (buffer[offset++] & 255); | ||
| s2 = s2 + s1; | ||
| } | ||
| s1 %= this.DEF_CHECKSUM_BASE; | ||
| s2 %= this.DEF_CHECKSUM_BASE; | ||
| } | ||
| checkSumUInt = (s2 << this.DEF_CHECKSUM_BIT_OFFSET) | s1; | ||
| checksum = checkSumUInt; | ||
| } | ||
| /// <summary> | ||
| /// Generates checksum by calculating checksum of the | ||
| /// given buffer. | ||
| /// </summary> | ||
| /// <param name="buffer">Data byte array.</param> | ||
| /// <param name="offset">Offset in the buffer.</param> | ||
| /// <param name="length">Length of data to be used from the stream.</param> | ||
| public static ChecksumGenerate(buffer: Uint8Array, offset: number, length: number): number { | ||
| const result: number = 1; | ||
| ChecksumCalculator.ChecksumUpdate(result, buffer, offset, length); | ||
| return result; | ||
| } | ||
| } | ||
| /* eslint-enable */ |
| import { DecompressorHuffmanTree } from './decompressor-huffman-tree'; | ||
| export declare class CompressedStreamReader { | ||
| private static readonly DEF_REVERSE_BITS; | ||
| defaultHuffmanDynamicTree: number[]; | ||
| private DEF_HEADER_METHOD_MASK; | ||
| private DEF_HEADER_INFO_MASK; | ||
| private DEF_HEADER_FLAGS_FCHECK; | ||
| private DEF_HEADER_FLAGS_FDICT; | ||
| private DEF_HEADER_FLAGS_FLEVEL; | ||
| private static readonly DEF_HUFFMAN_DYNTREE_REPEAT_MINIMUMS; | ||
| private static readonly DEF_HUFFMAN_DYNTREE_REPEAT_BITS; | ||
| private DEF_MAX_WINDOW_SIZE; | ||
| private static readonly DEF_HUFFMAN_REPEAT_LENGTH_BASE; | ||
| private static readonly DEF_HUFFMAN_REPEAT_LENGTH_EXTENSION; | ||
| private static readonly DEF_HUFFMAN_REPEAT_DISTANCE_BASE; | ||
| private static readonly DEF_HUFFMAN_REPEAT_DISTANCE_EXTENSION; | ||
| private DEF_HUFFMAN_REPEATE_MAX; | ||
| private DEF_HUFFMAN_END_BLOCK; | ||
| private DEF_HUFFMAN_LENGTH_MINIMUMCODE; | ||
| private DEF_HUFFMAN_LENGTH_MAXIMUMCODE; | ||
| private DEF_HUFFMAN_DISTANCE_MAXIMUMCODE; | ||
| private mInputStream; | ||
| private mCheckSum; | ||
| private tBuffer; | ||
| mBuffer: number; | ||
| private mBufferedBits; | ||
| private mTempBuffer; | ||
| private mBlockBuffer; | ||
| private mbNoWrap; | ||
| private mWindowSize; | ||
| private mCurrentPosition; | ||
| private mDataLength; | ||
| private mbReadingUncompressed; | ||
| private mUncompressedDataLength; | ||
| private mbCanReadNextBlock; | ||
| private mbCanReadMoreData; | ||
| private mCurrentLengthTree; | ||
| private mCurrentDistanceTree; | ||
| private mbCheckSumRead; | ||
| /** | ||
| * Initializes compressor and writes ZLib header if needed. | ||
| * @param {boolean} noWrap - optional if true, ZLib header and checksum will not be written. | ||
| */ | ||
| peekBits(count: number): number; | ||
| protected fillBuffer(): void; | ||
| skipBits(count: number): void; | ||
| readonly availableBits: number; | ||
| constructor(stream: Uint8Array, bNoWrap: boolean); | ||
| protected readZLibHeader(): void; | ||
| protected readInt16(): number; | ||
| protected readBits(count: number): number; | ||
| protected decodeBlockHeader(): boolean; | ||
| protected skipToBoundary(): void; | ||
| protected readInt16Inverted(): number; | ||
| protected decodeDynamicHeader(lengthTree: DecompressorHuffmanTree, distanceTree: DecompressorHuffmanTree): any; | ||
| private readHuffman; | ||
| read(buffer: Uint8Array, offset: number, length: number): number; | ||
| protected readPackedBytes(buffer: Uint8Array, offset: number, length: number): number; | ||
| protected readInt32(): number; | ||
| protected checksumUpdate(buffer: Uint8Array, offset: number, length: number): void; | ||
| } | ||
| export declare class Stream { | ||
| inputStream: Uint8Array; | ||
| readonly length: number; | ||
| position: number; | ||
| constructor(input: Uint8Array); | ||
| read(buffer: Uint8Array, start: number, length: number): number; | ||
| readByte(): number; | ||
| write(inputBuffer: Uint8Array, offset: number, count: number): void; | ||
| toByteArray(): Uint8Array; | ||
| } |
| /* eslint-disable */ | ||
| import { DecompressorHuffmanTree } from './decompressor-huffman-tree'; | ||
| import { Utils } from './utils'; | ||
| import { ChecksumCalculator } from './checksum-calculator'; | ||
| export class CompressedStreamReader { | ||
| private static readonly DEF_REVERSE_BITS: Uint8Array = new Uint8Array([0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15]); | ||
| /// <summary> | ||
| /// Code lengths for the code length alphabet. | ||
| /// </summary> | ||
| public defaultHuffmanDynamicTree: number[] = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]; | ||
| /// <summary> | ||
| /// Mask for compression method to be decoded from 16-bit header. | ||
| /// </summary> | ||
| private DEF_HEADER_METHOD_MASK: number = 15 << 8; | ||
| /// <summary> | ||
| /// Mask for compression info to be decoded from 16-bit header. | ||
| /// </summary> | ||
| private DEF_HEADER_INFO_MASK: number = 240 << 8; | ||
| /// <summary> | ||
| /// Mask for check bits to be decoded from 16-bit header. | ||
| /// </summary> | ||
| private DEF_HEADER_FLAGS_FCHECK: number = 31; | ||
| /// <summary> | ||
| /// Mask for dictionary presence to be decoded from 16-bit header. | ||
| /// </summary> | ||
| private DEF_HEADER_FLAGS_FDICT: number = 32; | ||
| /// <summary> | ||
| /// Mask for compression level to be decoded from 16-bit header. | ||
| /// </summary> | ||
| private DEF_HEADER_FLAGS_FLEVEL: number = 192; | ||
| /// <summary> | ||
| /// Minimum count of repetions. | ||
| /// </summary> | ||
| private static readonly DEF_HUFFMAN_DYNTREE_REPEAT_MINIMUMS: number[] = [3, 3, 11]; | ||
| /// <summary> | ||
| /// Bits, that responds for different repetion modes. | ||
| /// </summary> | ||
| private static readonly DEF_HUFFMAN_DYNTREE_REPEAT_BITS: number[] = [2, 3, 7]; | ||
| /// <summary> | ||
| /// Maximum size of the data window. | ||
| /// </summary> | ||
| private DEF_MAX_WINDOW_SIZE: number = 65535; | ||
| /// <summary> | ||
| /// Length bases. | ||
| /// </summary> | ||
| private static readonly DEF_HUFFMAN_REPEAT_LENGTH_BASE: number[] = | ||
| [ | ||
| 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 | ||
| ]; | ||
| /// <summary> | ||
| /// Length extended bits count. | ||
| /// </summary> | ||
| private static readonly DEF_HUFFMAN_REPEAT_LENGTH_EXTENSION: number[] = | ||
| [ | ||
| 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 | ||
| ]; | ||
| /// <summary> | ||
| /// Distance bases. | ||
| /// </summary> | ||
| private static readonly DEF_HUFFMAN_REPEAT_DISTANCE_BASE: number[] = | ||
| [ | ||
| 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 | ||
| ]; | ||
| /// <summary> | ||
| /// Distance extanded bits count. | ||
| /// </summary> | ||
| private static readonly DEF_HUFFMAN_REPEAT_DISTANCE_EXTENSION: number[] = | ||
| [ | ||
| 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 | ||
| ]; | ||
| /// <summary> | ||
| /// Maximum length of the repeatable block. | ||
| /// </summary> | ||
| private DEF_HUFFMAN_REPEATE_MAX: number = 258; | ||
| /// <summary> | ||
| /// End of the block sign. | ||
| /// </summary> | ||
| private DEF_HUFFMAN_END_BLOCK: number = 256; | ||
| /// <summary> | ||
| /// Minimal length code. | ||
| /// </summary> | ||
| private DEF_HUFFMAN_LENGTH_MINIMUMCODE: number = 257; | ||
| /// <summary> | ||
| /// Maximal length code. | ||
| /// </summary> | ||
| private DEF_HUFFMAN_LENGTH_MAXIMUMCODE: number = 285; | ||
| /// <summary> | ||
| /// Maximal distance code. | ||
| /// </summary> | ||
| private DEF_HUFFMAN_DISTANCE_MAXIMUMCODE: number = 29; | ||
| /// <summary> | ||
| /// Input stream. | ||
| /// </summary> | ||
| private mInputStream: Stream; | ||
| /// <summary> | ||
| /// Currently calculated checksum, | ||
| /// based on Adler32 algorithm. | ||
| /// </summary> | ||
| private mCheckSum: number = 1; | ||
| /// <summary> | ||
| /// Currently read 4 bytes. | ||
| /// </summary> | ||
| private tBuffer: number = 0; | ||
| public get mBuffer(): number { | ||
| return this.tBuffer; | ||
| } | ||
| public set mBuffer(value: number) { | ||
| this.tBuffer = value; | ||
| } | ||
| /// <summary> | ||
| /// Count of bits that are in buffer. | ||
| /// </summary> | ||
| private mBufferedBits: number = 0; | ||
| /// <summary> | ||
| /// Temporary buffer. | ||
| /// </summary> | ||
| private mTempBuffer: Uint8Array = new Uint8Array(4); | ||
| /// <summary> | ||
| /// 32k buffer for unpacked data. | ||
| /// </summary> | ||
| private mBlockBuffer: Uint8Array = new Uint8Array(this.DEF_MAX_WINDOW_SIZE); | ||
| /// <summary> | ||
| /// No wrap mode. | ||
| /// </summary> | ||
| private mbNoWrap: boolean = false; | ||
| /// <summary> | ||
| /// Window size, can not be larger than 32k. | ||
| /// </summary> | ||
| private mWindowSize: number = 0; | ||
| /// <summary> | ||
| /// Current position in output stream. | ||
| /// Current in-block position can be extracted by applying Int16.MaxValue mask. | ||
| /// </summary> | ||
| private mCurrentPosition: number = 0; | ||
| /// <summary> | ||
| /// Data length. | ||
| /// Current in-block position can be extracted by applying Int16.MaxValue mask. | ||
| /// </summary> | ||
| private mDataLength: number = 0; | ||
| /// <summary> | ||
| /// Sign of uncompressed data reading. | ||
| /// </summary> | ||
| private mbReadingUncompressed: boolean; | ||
| /// <summary> | ||
| /// Size of the block with uncompressed data. | ||
| /// </summary> | ||
| private mUncompressedDataLength: number; | ||
| /// <summary> | ||
| /// Specifies wheather next block can to be read. | ||
| /// Reading can be denied because the header of the last block have been read. | ||
| /// </summary> | ||
| private mbCanReadNextBlock: boolean = true; | ||
| /// <summary> | ||
| /// Specifies wheather user can read more data from stream. | ||
| /// </summary> | ||
| private mbCanReadMoreData: boolean = true; | ||
| /// <summary> | ||
| /// Current lengths huffman tree. | ||
| /// </summary> | ||
| private mCurrentLengthTree: DecompressorHuffmanTree; | ||
| /// <summary> | ||
| /// Current distances huffman tree. | ||
| /// </summary> | ||
| private mCurrentDistanceTree: DecompressorHuffmanTree; | ||
| /// <summary> | ||
| /// Specifies wheather checksum has been read. | ||
| /// </summary> | ||
| private mbCheckSumRead: boolean = false; | ||
| /** | ||
| * Initializes compressor and writes ZLib header if needed. | ||
| * @param {boolean} noWrap - optional if true, ZLib header and checksum will not be written. | ||
| */ | ||
| /// <summary> | ||
| /// Reads specified count of bits without adjusting position. | ||
| /// </summary> | ||
| /// <param name="count">Count of bits to be read.</param> | ||
| /// <returns>Read value.</returns> | ||
| public peekBits(count: number): number { | ||
| if (count < 0) { | ||
| throw new DOMException('count', 'Bits count can not be less than zero.'); | ||
| } | ||
| if (count > 32) { | ||
| throw new DOMException('count', 'Count of bits is too large.'); | ||
| } | ||
| // If buffered data is not enough to give result, | ||
| // fill buffer. | ||
| if (this.mBufferedBits < count) { | ||
| this.fillBuffer(); | ||
| } | ||
| // If you want to read 4 bytes and there is partial data in | ||
| // buffer, than you will fail. | ||
| if (this.mBufferedBits < count) { | ||
| return -1; | ||
| } | ||
| // Create bitmask for reading of count bits | ||
| const bitMask: number = ~(4294967295 << count); | ||
| const result: number = Utils.bitConverterUintToInt32(this.mBuffer & bitMask); | ||
| //Debug.WriteLine( /*new string( ' ', 32 - mBufferedBits + (int)( ( 32 - mBufferedBits ) / 8 ) ) + BitsToString( (int)mBuffer, mBufferedBits ) + " " + BitsToString( result, count ) +*/ " " + result.ToString() ); | ||
| return result; | ||
| } | ||
| protected fillBuffer(): void { | ||
| const length: number = 4 - (this.mBufferedBits >> 3) - | ||
| (((this.mBufferedBits & 7) !== 0) ? 1 : 0); | ||
| if (length === 0) { | ||
| return; | ||
| } | ||
| //TODO: fix this | ||
| const bytesRead: number = this.mInputStream.read(this.mTempBuffer, 0, length); | ||
| for (let i: number = 0; i < bytesRead; i++) { | ||
| this.mBuffer = Utils.bitConverterInt32ToUint(this.mBuffer | | ||
| (Utils.bitConverterInt32ToUint(this.mTempBuffer[i] << this.mBufferedBits))); | ||
| this.mBufferedBits += 8; | ||
| } | ||
| //TODO: fix this | ||
| } | ||
| /// <summary> | ||
| /// Skips specified count of bits. | ||
| /// </summary> | ||
| /// <param name="count">Count of bits to be skipped.</param> | ||
| public skipBits(count: number): void { | ||
| if (count < 0) { | ||
| throw new DOMException('count', 'Bits count can not be less than zero.'); | ||
| } | ||
| if (count === 0) { | ||
| return; | ||
| } | ||
| if (count >= this.mBufferedBits) { | ||
| count -= this.mBufferedBits; | ||
| this.mBufferedBits = 0; | ||
| this.mBuffer = 0; | ||
| // if something left, skip it. | ||
| if (count > 0) { | ||
| // Skip entire bytes. | ||
| this.mInputStream.position += (count >> 3); //TODO: fix this | ||
| count &= 7; | ||
| // Skip bits. | ||
| if (count > 0) { | ||
| this.fillBuffer(); | ||
| this.mBufferedBits -= count; | ||
| this.mBuffer = Utils.bitConverterInt32ToUint(this.mBuffer >>> count); | ||
| } | ||
| } | ||
| } | ||
| else { | ||
| this.mBufferedBits -= count; | ||
| this.mBuffer = Utils.bitConverterInt32ToUint(this.mBuffer >>> count); | ||
| } | ||
| } | ||
| public get availableBits(): number { | ||
| return this.mBufferedBits; | ||
| } | ||
| constructor(stream: Uint8Array, bNoWrap: boolean) { | ||
| if (stream == null) { | ||
| throw new DOMException('stream'); | ||
| } | ||
| if (stream.length === 0) { | ||
| throw new DOMException('stream - string can not be empty'); | ||
| } | ||
| DecompressorHuffmanTree.init(); | ||
| this.mInputStream = new Stream(stream); | ||
| this.mbNoWrap = bNoWrap; | ||
| if (!this.mbNoWrap) { | ||
| this.readZLibHeader(); | ||
| } | ||
| this.decodeBlockHeader(); | ||
| } | ||
| /// <summary> | ||
| /// Reads ZLib header with compression method and flags. | ||
| /// </summary> | ||
| protected readZLibHeader(): void { | ||
| // first 8 bits - compression Method and flags | ||
| // 8 other - flags | ||
| const header: number = this.readInt16(); | ||
| //Debug.WriteLine( BitsToString( header ) ); | ||
| if (header === -1) { | ||
| throw new DOMException('Header of the stream can not be read.'); | ||
| } | ||
| if (header % 31 !== 0) { | ||
| throw new DOMException('Header checksum illegal'); | ||
| } | ||
| if ((header & this.DEF_HEADER_METHOD_MASK) !== (8 << 8)) { | ||
| throw new DOMException('Unsupported compression method.'); | ||
| } | ||
| this.mWindowSize = Math.pow(2, ((header & this.DEF_HEADER_INFO_MASK) >> 12) + 8); | ||
| if (this.mWindowSize > 65535) { | ||
| throw new DOMException('Unsupported window size for deflate compression method.'); | ||
| } | ||
| if ((header & this.DEF_HEADER_FLAGS_FDICT) >> 5 === 1) { | ||
| // Get dictionary. | ||
| throw new DOMException('Custom dictionary is not supported at the moment.'); | ||
| } | ||
| } | ||
| /// <summary> | ||
| /// TODO: place correct comment here | ||
| /// </summary> | ||
| /// <returns> | ||
| /// TODO: place correct comment here | ||
| /// </returns> | ||
| protected readInt16(): number { | ||
| let result: number = (this.readBits(8) << 8); | ||
| result |= this.readBits(8); | ||
| return result; | ||
| } | ||
| /// <summary> | ||
| /// Reads specified count of bits from stream. | ||
| /// </summary> | ||
| /// <param name="count">Count of bits to be read.</param> | ||
| /// <returns> | ||
| /// TODO: place correct comment here | ||
| /// </returns> | ||
| protected readBits(count: number): number { | ||
| const result: number = this.peekBits(count); | ||
| if (result === -1) { | ||
| return -1; | ||
| } | ||
| this.mBufferedBits -= count; | ||
| this.mBuffer = Utils.bitConverterInt32ToUint(this.mBuffer >>> count); | ||
| return result; | ||
| } | ||
| /// <summary> | ||
| /// Reads and decodes block of data. | ||
| /// </summary> | ||
| /// <returns>True if buffer was empty and new data was read, otherwise - False.</returns> | ||
| protected decodeBlockHeader(): boolean { | ||
| if (!this.mbCanReadNextBlock) { | ||
| return false; | ||
| } | ||
| const bFinalBlock: number = this.readBits(1); | ||
| if (bFinalBlock === -1) { | ||
| return false; | ||
| } | ||
| const blockType: number = this.readBits(2); | ||
| if (blockType === -1) { | ||
| return false; | ||
| } | ||
| this.mbCanReadNextBlock = (bFinalBlock === 0); | ||
| // ChecksumReset(); | ||
| switch (blockType) { | ||
| case 0: | ||
| // Uncompressed data | ||
| this.mbReadingUncompressed = true; | ||
| this.skipToBoundary(); | ||
| const length: number = this.readInt16Inverted(); | ||
| const lengthComplement: number = this.readInt16Inverted(); | ||
| if (length !== (lengthComplement ^ 0xffff)) { | ||
| throw new DOMException('Wrong block length.'); | ||
| } | ||
| if (length > 65535) { | ||
| throw new DOMException('Uncompressed block length can not be more than 65535.'); | ||
| } | ||
| this.mUncompressedDataLength = length; | ||
| this.mCurrentLengthTree = null; | ||
| this.mCurrentDistanceTree = null; | ||
| break; | ||
| case 1: | ||
| // Compressed data with fixed huffman codes. | ||
| this.mbReadingUncompressed = false; | ||
| this.mUncompressedDataLength = -1; | ||
| this.mCurrentLengthTree = DecompressorHuffmanTree.lengthTree; | ||
| this.mCurrentDistanceTree = DecompressorHuffmanTree.distanceTree; | ||
| break; | ||
| case 2: | ||
| // Compressed data with dynamic huffman codes. | ||
| this.mbReadingUncompressed = false; | ||
| this.mUncompressedDataLength = -1; | ||
| const trees: any = this.decodeDynamicHeader(this.mCurrentLengthTree, this.mCurrentDistanceTree); | ||
| this.mCurrentLengthTree = trees.lengthTree; | ||
| this.mCurrentDistanceTree = trees.distanceTree; | ||
| break; | ||
| default: | ||
| throw new DOMException('Wrong block type.'); | ||
| } | ||
| return true; | ||
| } | ||
| /// <summary> | ||
| /// Discards left-most partially used byte. | ||
| /// </summary> | ||
| protected skipToBoundary(): void { | ||
| this.mBuffer = Utils.bitConverterInt32ToUint(this.mBuffer >>> (this.mBufferedBits & 7)); | ||
| this.mBufferedBits &= ~7; | ||
| } | ||
| /// <summary> | ||
| /// TODO: place correct comment here | ||
| /// </summary> | ||
| /// <returns> | ||
| /// TODO: place correct comment here | ||
| /// </returns> | ||
| protected readInt16Inverted(): number { | ||
| let result: number = (this.readBits(8)); | ||
| result |= this.readBits(8) << 8; | ||
| return result; | ||
| } | ||
| /// <summary> | ||
| /// Reades dynamic huffman codes from block header. | ||
| /// </summary> | ||
| /// <param name="lengthTree">Literals/Lengths tree.</param> | ||
| /// <param name="distanceTree">Distances tree.</param> | ||
| protected decodeDynamicHeader(lengthTree: DecompressorHuffmanTree, distanceTree: DecompressorHuffmanTree): any { | ||
| let bLastSymbol: number = 0; | ||
| let iLengthsCount: number = this.readBits(5); | ||
| let iDistancesCount: number = this.readBits(5); | ||
| let iCodeLengthsCount: number = this.readBits(4); | ||
| if (iLengthsCount < 0 || iDistancesCount < 0 || iCodeLengthsCount < 0) { | ||
| throw new DOMException('Wrong dynamic huffman codes.'); | ||
| } | ||
| iLengthsCount += 257; | ||
| iDistancesCount += 1; | ||
| const iResultingCodeLengthsCount: number = iLengthsCount + iDistancesCount; | ||
| const arrResultingCodeLengths: Uint8Array = new Uint8Array(iResultingCodeLengthsCount); | ||
| const arrDecoderCodeLengths: Uint8Array = new Uint8Array(19); | ||
| iCodeLengthsCount += 4; | ||
| let iCurrentCode: number = 0; | ||
| while (iCurrentCode < iCodeLengthsCount) { | ||
| const len: number = this.readBits(3); | ||
| if (len < 0) { | ||
| throw new DOMException('Wrong dynamic huffman codes.'); | ||
| } | ||
| arrDecoderCodeLengths[this.defaultHuffmanDynamicTree[iCurrentCode++]] = len; | ||
| } | ||
| const treeInternalDecoder: DecompressorHuffmanTree = new DecompressorHuffmanTree(arrDecoderCodeLengths); | ||
| iCurrentCode = 0; | ||
| for (; ;) { | ||
| let symbol: number; | ||
| let bNeedBreak: boolean = false; | ||
| symbol = treeInternalDecoder.unpackSymbol(this); | ||
| while ((symbol & ~15) === 0) { | ||
| arrResultingCodeLengths[iCurrentCode++] = bLastSymbol = symbol; | ||
| if (iCurrentCode === iResultingCodeLengthsCount) { | ||
| bNeedBreak = true; | ||
| break; | ||
| } | ||
| symbol = treeInternalDecoder.unpackSymbol(this); | ||
| } | ||
| if (bNeedBreak) { | ||
| break; | ||
| } | ||
| if (symbol < 0) { | ||
| throw new DOMException('Wrong dynamic huffman codes.'); | ||
| } | ||
| if (symbol >= 17) { | ||
| bLastSymbol = 0; | ||
| } | ||
| else if (iCurrentCode === 0) { | ||
| throw new DOMException('Wrong dynamic huffman codes.'); | ||
| } | ||
| const miRepSymbol: number = symbol - 16; | ||
| const bits: number = CompressedStreamReader.DEF_HUFFMAN_DYNTREE_REPEAT_BITS[miRepSymbol]; | ||
| let count: number = this.readBits(bits); | ||
| if (count < 0) { | ||
| throw new DOMException('Wrong dynamic huffman codes.'); | ||
| } | ||
| count += CompressedStreamReader.DEF_HUFFMAN_DYNTREE_REPEAT_MINIMUMS[miRepSymbol]; | ||
| if (iCurrentCode + count > iResultingCodeLengthsCount) { | ||
| throw new DOMException('Wrong dynamic huffman codes.'); | ||
| } | ||
| while (count-- > 0) { | ||
| arrResultingCodeLengths[iCurrentCode++] = bLastSymbol; | ||
| } | ||
| if (iCurrentCode === iResultingCodeLengthsCount) { | ||
| break; | ||
| } | ||
| } | ||
| let tempArray: Uint8Array = new Uint8Array(iLengthsCount); | ||
| tempArray.set(arrResultingCodeLengths.subarray(0, iLengthsCount), 0); | ||
| //sourceArray, sourceIndex, destinationArray, destinationIndex, length | ||
| //Array.copy( arrResultingCodeLengths, 0, tempArray, 0, iLengthsCount ); | ||
| lengthTree = new DecompressorHuffmanTree(tempArray); | ||
| tempArray = arrResultingCodeLengths.slice(iLengthsCount, iLengthsCount + iDistancesCount); | ||
| //Array.copy( arrResultingCodeLengths, iLengthsCount, tempArray, 0, iDistancesCount ); | ||
| distanceTree = new DecompressorHuffmanTree(tempArray); | ||
| return { 'lengthTree': lengthTree, 'distanceTree': distanceTree }; | ||
| } | ||
| /// <summary> | ||
| /// Decodes huffman codes. | ||
| /// </summary> | ||
| /// <returns>True if some data was read.</returns> | ||
| private readHuffman(): boolean { | ||
| let free: number = this.DEF_MAX_WINDOW_SIZE - (this.mDataLength - this.mCurrentPosition); | ||
| let dataRead: boolean = false; | ||
| //long maxdistance = DEF_MAX_WINDOW_SIZE >> 1; | ||
| const readdata: any = {}; | ||
| // DEF_HUFFMAN_REPEATE_MAX - longest repeatable block, we should always reserve space for it because | ||
| // if we should not, we will have buffer overrun. | ||
| while (free >= this.DEF_HUFFMAN_REPEATE_MAX) { | ||
| let symbol: number; | ||
| symbol = this.mCurrentLengthTree.unpackSymbol(this); | ||
| // Only codes 0..255 are valid independent symbols. | ||
| while (((symbol) & ~0xff) === 0) { | ||
| readdata[(this.mDataLength + 1) % this.DEF_MAX_WINDOW_SIZE] = symbol; | ||
| this.mBlockBuffer[this.mDataLength++ % this.DEF_MAX_WINDOW_SIZE] = symbol; | ||
| dataRead = true; | ||
| if (--free < this.DEF_HUFFMAN_REPEATE_MAX) { | ||
| return true; | ||
| } | ||
| //if( (mDataLength - mCurrentPosition ) < maxdistance ) return true; | ||
| symbol = this.mCurrentLengthTree.unpackSymbol(this); | ||
| } | ||
| if (symbol < this.DEF_HUFFMAN_LENGTH_MINIMUMCODE) { | ||
| if (symbol < this.DEF_HUFFMAN_END_BLOCK) { | ||
| throw new DOMException('Illegal code.'); | ||
| } | ||
| const numDataRead: number = dataRead ? 1 : 0; | ||
| this.mbCanReadMoreData = this.decodeBlockHeader(); | ||
| const numReadMore: number = (this.mbCanReadMoreData) ? 1 : 0; | ||
| return (numDataRead | numReadMore) ? true : false; | ||
| } | ||
| if (symbol > this.DEF_HUFFMAN_LENGTH_MAXIMUMCODE) { | ||
| throw new DOMException('Illegal repeat code length.'); | ||
| } | ||
| let iRepeatLength: number = CompressedStreamReader.DEF_HUFFMAN_REPEAT_LENGTH_BASE[symbol - | ||
| this.DEF_HUFFMAN_LENGTH_MINIMUMCODE]; | ||
| let iRepeatExtraBits: number = CompressedStreamReader.DEF_HUFFMAN_REPEAT_LENGTH_EXTENSION[symbol - | ||
| this.DEF_HUFFMAN_LENGTH_MINIMUMCODE]; | ||
| if (iRepeatExtraBits > 0) { | ||
| const extra: number = this.readBits(iRepeatExtraBits); | ||
| if (extra < 0) { | ||
| throw new DOMException('Wrong data.'); | ||
| } | ||
| iRepeatLength += extra; | ||
| } | ||
| // Unpack repeat distance. | ||
| symbol = this.mCurrentDistanceTree.unpackSymbol(this); | ||
| if (symbol < 0 || symbol > CompressedStreamReader.DEF_HUFFMAN_REPEAT_DISTANCE_BASE.length) { | ||
| throw new DOMException('Wrong distance code.'); | ||
| } | ||
| let iRepeatDistance: number = CompressedStreamReader.DEF_HUFFMAN_REPEAT_DISTANCE_BASE[symbol]; | ||
| iRepeatExtraBits = CompressedStreamReader.DEF_HUFFMAN_REPEAT_DISTANCE_EXTENSION[symbol]; | ||
| if (iRepeatExtraBits > 0) { | ||
| const extra: number = this.readBits(iRepeatExtraBits); | ||
| if (extra < 0) { | ||
| throw new DOMException('Wrong data.'); | ||
| } | ||
| iRepeatDistance += extra; | ||
| } | ||
| // Copy data in slow repeat mode | ||
| for (let i: number = 0; i < iRepeatLength; i++) { | ||
| this.mBlockBuffer[this.mDataLength % this.DEF_MAX_WINDOW_SIZE] = | ||
| this.mBlockBuffer[(this.mDataLength - iRepeatDistance) % this.DEF_MAX_WINDOW_SIZE]; | ||
| this.mDataLength++; | ||
| free--; | ||
| } | ||
| dataRead = true; | ||
| } | ||
| return dataRead; | ||
| } | ||
| /// <summary> | ||
| /// Reads data to buffer. | ||
| /// </summary> | ||
| /// <param name="buffer">Output buffer for data.</param> | ||
| /// <param name="offset">Offset in output data.</param> | ||
| /// <param name="length">Length of the data to be read.</param> | ||
| /// <returns>Count of bytes actually read.</returns> | ||
| public read(buffer: Uint8Array, offset: number, length: number): number { | ||
| if (buffer == null) { | ||
| throw new DOMException('buffer'); | ||
| } | ||
| if (offset < 0 || offset > buffer.length - 1) { | ||
| throw new DOMException('offset', 'Offset does not belong to specified buffer.'); | ||
| } | ||
| if (length < 0 || length > buffer.length - offset) { | ||
| throw new DOMException('length', 'Length is illegal.'); | ||
| } | ||
| const initialLength: number = length; | ||
| while (length > 0) { | ||
| // Read from internal buffer. | ||
| if (this.mCurrentPosition < this.mDataLength) { | ||
| // Position in buffer array. | ||
| const inBlockPosition: number = (this.mCurrentPosition % this.DEF_MAX_WINDOW_SIZE); | ||
| // We can not read more than we have in buffer at once, | ||
| // and we not read more than till the array end. | ||
| let dataToCopy: number = Math.min(this.DEF_MAX_WINDOW_SIZE - inBlockPosition, (this.mDataLength - this.mCurrentPosition)); | ||
| // Reading not more, than the rest of the buffer. | ||
| dataToCopy = Math.min(dataToCopy, length); | ||
| //sourceArray, sourceIndex, destinationArray, destinationIndex, length | ||
| // Copy data. | ||
| //Array.Copy( mBlockBuffer, inBlockPosition, buffer, offset, dataToCopy ); | ||
| //buffer.set(this.mBlockBuffer.slice(inBlockPosition, dataToCopy), offset); | ||
| Utils.arrayCopy(this.mBlockBuffer, inBlockPosition, buffer, offset, dataToCopy); | ||
| // Correct position, length, | ||
| this.mCurrentPosition += dataToCopy; | ||
| offset += dataToCopy; | ||
| length -= dataToCopy; | ||
| } | ||
| else { | ||
| if (!this.mbCanReadMoreData) { | ||
| break; | ||
| } | ||
| const oldDataLength: number = this.mDataLength; | ||
| if (!this.mbReadingUncompressed) { | ||
| if (!this.readHuffman()) { | ||
| break; | ||
| } | ||
| } | ||
| else { | ||
| if (this.mUncompressedDataLength === 0) { | ||
| // If there is no more data in stream, just exit. | ||
| this.mbCanReadMoreData = this.decodeBlockHeader(); | ||
| if (!(this.mbCanReadMoreData)) { | ||
| break; | ||
| } | ||
| } | ||
| else { | ||
| // Position of the data end in block buffer. | ||
| const inBlockPosition: number = (this.mDataLength % this.DEF_MAX_WINDOW_SIZE); | ||
| const dataToRead: number = Math.min(this.mUncompressedDataLength, this.DEF_MAX_WINDOW_SIZE - inBlockPosition); | ||
| const dataRead: number = this.readPackedBytes(this.mBlockBuffer, inBlockPosition, dataToRead); | ||
| if (dataToRead !== dataRead) { | ||
| throw new DOMException('Not enough data in stream.'); | ||
| } | ||
| this.mUncompressedDataLength -= dataRead; | ||
| this.mDataLength += dataRead; | ||
| } | ||
| } | ||
| if (oldDataLength < this.mDataLength) { | ||
| const start: number = (oldDataLength % this.DEF_MAX_WINDOW_SIZE); | ||
| const end: number = (this.mDataLength % this.DEF_MAX_WINDOW_SIZE); | ||
| if (start < end) { | ||
| this.checksumUpdate(this.mBlockBuffer, start, end - start); | ||
| } | ||
| else { | ||
| this.checksumUpdate(this.mBlockBuffer, start, this.DEF_MAX_WINDOW_SIZE - start); | ||
| if (end > 0) { | ||
| this.checksumUpdate(this.mBlockBuffer, 0, end); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| if (!this.mbCanReadMoreData && !this.mbCheckSumRead && !this.mbNoWrap) { | ||
| this.skipToBoundary(); | ||
| const checkSum: number = this.readInt32(); | ||
| //Debug.Assert( checkSum == mCheckSum, "" ); | ||
| if (checkSum !== this.mCheckSum) { | ||
| throw new DOMException('Checksum check failed.'); | ||
| } | ||
| this.mbCheckSumRead = true; | ||
| } | ||
| return initialLength - length; | ||
| } | ||
| /// <summary> | ||
| /// Reads array of bytes. | ||
| /// </summary> | ||
| /// <param name="buffer">Output buffer.</param> | ||
| /// <param name="offset">Offset in output buffer.</param> | ||
| /// <param name="length">Length of the data to be read.</param> | ||
| /// <returns>Count of bytes actually read to the buffer.</returns> | ||
| protected readPackedBytes(buffer: Uint8Array, offset: number, length: number): number { | ||
| if (buffer == null) { | ||
| throw new DOMException('buffer'); | ||
| } | ||
| if (offset < 0 || offset > buffer.length - 1) { | ||
| throw new DOMException('offset", "Offset can not be less than zero or greater than buffer length - 1.'); | ||
| } | ||
| if (length < 0) { | ||
| throw new DOMException('length", "Length can not be less than zero.'); | ||
| } | ||
| if (length > buffer.length - offset) { | ||
| throw new DOMException('length", "Length is too large.'); | ||
| } | ||
| if ((this.mBufferedBits & 7) !== 0) { | ||
| throw new DOMException('Reading of unalligned data is not supported.'); | ||
| } | ||
| if (length === 0) { | ||
| return 0; | ||
| } | ||
| let result: number = 0; | ||
| while (this.mBufferedBits > 0 && length > 0) { | ||
| buffer[offset++] = (this.mBuffer); | ||
| this.mBufferedBits -= 8; | ||
| this.mBuffer = Utils.bitConverterInt32ToUint(this.mBuffer >>> 8); | ||
| length--; | ||
| result++; | ||
| } | ||
| if (length > 0) { | ||
| //TODO: Fix this. | ||
| result += this.mInputStream.read(buffer, offset, length); | ||
| } | ||
| return result; | ||
| } | ||
| /// <summary> | ||
| /// TODO: place correct comment here | ||
| /// </summary> | ||
| /// <returns> | ||
| /// TODO: place correct comment here | ||
| /// </returns> | ||
| protected readInt32(): number { | ||
| let result: number = this.readBits(8) << 24; | ||
| result |= this.readBits(8) << 16; | ||
| result |= this.readBits(8) << 8; | ||
| result |= this.readBits(8); | ||
| return result; | ||
| } | ||
| /// <summary> | ||
| /// Updates checksum by calculating checksum of the | ||
| /// given buffer and adding it to current value. | ||
| /// </summary> | ||
| /// <param name="buffer">Data byte array.</param> | ||
| /// <param name="offset">Offset in the buffer.</param> | ||
| /// <param name="length">Length of data to be used from the stream.</param> | ||
| protected checksumUpdate(buffer: Uint8Array, offset: number, length: number): void { | ||
| ChecksumCalculator.ChecksumUpdate(this.mCheckSum, buffer, offset, length); | ||
| } | ||
| } | ||
| export class Stream { | ||
| public inputStream: Uint8Array; | ||
| public get length(): number { | ||
| return this.inputStream.buffer.byteLength; | ||
| } | ||
| public position: number = 0; | ||
| constructor(input: Uint8Array) { | ||
| this.inputStream = new Uint8Array(input.buffer); | ||
| } | ||
| public read(buffer: Uint8Array, start: number, length: number): number { | ||
| let temp: Uint8Array = new Uint8Array(this.inputStream.buffer, this.position + start); | ||
| let data: Uint8Array = temp.subarray(0, length); | ||
| buffer.set(data, 0); | ||
| this.position += data.byteLength; | ||
| return data.byteLength; | ||
| } | ||
| public readByte(): number { | ||
| return this.inputStream[this.position++]; | ||
| } | ||
| public write(inputBuffer: Uint8Array, offset: number, count: number): void { | ||
| Utils.arrayCopy(inputBuffer, 0, this.inputStream, this.position + offset, count) | ||
| // this.inputStream = new Uint8Array(this.inputStream.buffer, this.position + offset); | ||
| // this.inputStream.set(inputBuffer, offset); | ||
| this.position += count; | ||
| } | ||
| public toByteArray(): Uint8Array { | ||
| return new Uint8Array(this.inputStream.buffer); | ||
| } | ||
| } | ||
| /* eslint-enable */ |
| /** | ||
| * represent compression stream writer | ||
| * ```typescript | ||
| * let compressedWriter = new CompressedStreamWriter(); | ||
| * let text: string = 'Hello world!!!'; | ||
| * compressedWriter.write(text, 0, text.length); | ||
| * compressedWriter.close(); | ||
| * ``` | ||
| */ | ||
| export declare class CompressedStreamWriter { | ||
| private static isHuffmanTreeInitiated; | ||
| private stream; | ||
| private pendingBuffer; | ||
| private pendingBufLength; | ||
| private pendingBufCache; | ||
| private pendingBufBitsInCache; | ||
| private treeLiteral; | ||
| private treeDistances; | ||
| private treeCodeLengths; | ||
| private bufferPosition; | ||
| private arrLiterals; | ||
| private arrDistances; | ||
| private extraBits; | ||
| private currentHash; | ||
| private hashHead; | ||
| private hashPrevious; | ||
| private matchStart; | ||
| private matchLength; | ||
| private matchPrevAvail; | ||
| private blockStart; | ||
| private stringStart; | ||
| private lookAhead; | ||
| private dataWindow; | ||
| private inputBuffer; | ||
| private totalBytesIn; | ||
| private inputOffset; | ||
| private inputEnd; | ||
| private windowSize; | ||
| private windowMask; | ||
| private hashSize; | ||
| private hashMask; | ||
| private hashShift; | ||
| private maxDist; | ||
| private checkSum; | ||
| private noWrap; | ||
| /** | ||
| * get compressed data | ||
| */ | ||
| readonly compressedData: Uint8Array[]; | ||
| readonly getCompressedString: string; | ||
| /** | ||
| * Initializes compressor and writes ZLib header if needed. | ||
| * @param {boolean} noWrap - optional if true, ZLib header and checksum will not be written. | ||
| */ | ||
| constructor(noWrap?: boolean); | ||
| /** | ||
| * Compresses data and writes it to the stream. | ||
| * @param {Uint8Array} data - data to compress | ||
| * @param {number} offset - offset in data | ||
| * @param {number} length - length of the data | ||
| * @returns {void} | ||
| */ | ||
| write(data: Uint8Array | string, offset: number, length: number): void; | ||
| /** | ||
| * write ZLib header to the compressed data | ||
| * @return {void} | ||
| */ | ||
| writeZLibHeader(): void; | ||
| /** | ||
| * Write Most Significant Bytes in to stream | ||
| * @param {number} s - check sum value | ||
| */ | ||
| pendingBufferWriteShortBytes(s: number): void; | ||
| private compressData; | ||
| private compressSlow; | ||
| private discardMatch; | ||
| private matchPreviousAvailable; | ||
| private matchPreviousBest; | ||
| private lookAheadCompleted; | ||
| private huffmanIsFull; | ||
| private fillWindow; | ||
| private slideWindow; | ||
| private insertString; | ||
| private findLongestMatch; | ||
| private updateHash; | ||
| private huffmanTallyLit; | ||
| private huffmanTallyDist; | ||
| private huffmanFlushBlock; | ||
| private huffmanFlushStoredBlock; | ||
| private huffmanLengthCode; | ||
| private huffmanDistanceCode; | ||
| private huffmanSendAllTrees; | ||
| private huffmanReset; | ||
| private huffmanCompressBlock; | ||
| /** | ||
| * write bits in to internal buffer | ||
| * @param {number} b - source of bits | ||
| * @param {number} count - count of bits to write | ||
| */ | ||
| pendingBufferWriteBits(b: number, count: number): void; | ||
| private pendingBufferFlush; | ||
| private pendingBufferFlushBits; | ||
| private pendingBufferWriteByteBlock; | ||
| private pendingBufferWriteShort; | ||
| private pendingBufferAlignToByte; | ||
| /** | ||
| * Huffman Tree literal calculation | ||
| * @private | ||
| */ | ||
| static initHuffmanTree(): void; | ||
| /** | ||
| * close the stream and write all pending buffer in to stream | ||
| * @returns {void} | ||
| */ | ||
| close(): void; | ||
| /** | ||
| * release allocated un-managed resource | ||
| * @returns {void} | ||
| */ | ||
| destroy(): void; | ||
| } | ||
| /** | ||
| * represent the Huffman Tree | ||
| */ | ||
| export declare class CompressorHuffmanTree { | ||
| private codeFrequency; | ||
| private codes; | ||
| private codeLength; | ||
| private lengthCount; | ||
| private codeMinCount; | ||
| private codeCount; | ||
| private maxLength; | ||
| private writer; | ||
| private static reverseBits; | ||
| static huffCodeLengthOrders: number[]; | ||
| readonly treeLength: number; | ||
| readonly codeLengths: Uint8Array; | ||
| readonly codeFrequencies: Uint16Array; | ||
| /** | ||
| * Create new Huffman Tree | ||
| * @param {CompressedStreamWriter} writer instance | ||
| * @param {number} elementCount - element count | ||
| * @param {number} minCodes - minimum count | ||
| * @param {number} maxLength - maximum count | ||
| */ | ||
| constructor(writer: CompressedStreamWriter, elementCount: number, minCodes: number, maxLength: number); | ||
| setStaticCodes(codes: Int16Array, lengths: Uint8Array): void; | ||
| /** | ||
| * reset all code data in tree | ||
| * @returns {void} | ||
| */ | ||
| reset(): void; | ||
| /** | ||
| * write code to the compressor output stream | ||
| * @param {number} code - code to be written | ||
| * @returns {void} | ||
| */ | ||
| writeCodeToStream(code: number): void; | ||
| /** | ||
| * calculate code from their frequencies | ||
| * @returns {void} | ||
| */ | ||
| buildCodes(): void; | ||
| static bitReverse(value: number): number; | ||
| /** | ||
| * calculate length of compressed data | ||
| * @returns {number} | ||
| */ | ||
| getEncodedLength(): number; | ||
| /** | ||
| * calculate code frequencies | ||
| * @param {CompressorHuffmanTree} blTree | ||
| * @returns {void} | ||
| */ | ||
| calculateBLFreq(blTree: CompressorHuffmanTree): void; | ||
| /** | ||
| * @param {CompressorHuffmanTree} blTree - write tree to output stream | ||
| * @returns {void} | ||
| */ | ||
| writeTree(blTree: CompressorHuffmanTree): void; | ||
| /** | ||
| * Build huffman tree | ||
| * @returns {void} | ||
| */ | ||
| buildTree(): void; | ||
| private constructHuffmanTree; | ||
| private buildLength; | ||
| private recreateTree; | ||
| private calculateOptimalCodeLength; | ||
| } | ||
| /** | ||
| * Checksum calculator, based on Adler32 algorithm. | ||
| */ | ||
| export declare class ChecksumCalculator { | ||
| private static checkSumBitOffset; | ||
| private static checksumBase; | ||
| private static checksumIterationCount; | ||
| /** | ||
| * Updates checksum by calculating checksum of the | ||
| * given buffer and adding it to current value. | ||
| * @param {number} checksum - current checksum. | ||
| * @param {Uint8Array} buffer - data byte array. | ||
| * @param {number} offset - offset in the buffer. | ||
| * @param {number} length - length of data to be used from the stream. | ||
| * @returns {number} | ||
| */ | ||
| static checksumUpdate(checksum: number, buffer: Uint8Array, offset: number, length: number): number; | ||
| } |
| /* eslint-disable */ | ||
| import { Encoding } from '@syncfusion/ej2-file-utils'; | ||
| /** | ||
| * array literal codes | ||
| */ | ||
| const ARR_LITERAL_CODES: Int16Array = new Int16Array(286); | ||
| const ARR_LITERAL_LENGTHS: Uint8Array = new Uint8Array(286); | ||
| const ARR_DISTANCE_CODES: Int16Array = new Int16Array(30); | ||
| const ARR_DISTANCE_LENGTHS: Uint8Array = new Uint8Array(30); | ||
| /** | ||
| * represent compression stream writer | ||
| * ```typescript | ||
| * let compressedWriter = new CompressedStreamWriter(); | ||
| * let text: string = 'Hello world!!!'; | ||
| * compressedWriter.write(text, 0, text.length); | ||
| * compressedWriter.close(); | ||
| * ``` | ||
| */ | ||
| export class CompressedStreamWriter { | ||
| private static isHuffmanTreeInitiated: boolean = false; | ||
| private stream: Uint8Array[]; | ||
| private pendingBuffer: Uint8Array = new Uint8Array(1 << 16); | ||
| private pendingBufLength: number = 0; | ||
| private pendingBufCache: number = 0; | ||
| private pendingBufBitsInCache: number = 0; | ||
| private treeLiteral: CompressorHuffmanTree; | ||
| private treeDistances: CompressorHuffmanTree; | ||
| private treeCodeLengths: CompressorHuffmanTree; | ||
| private bufferPosition: number = 0; | ||
| private arrLiterals: Uint8Array; | ||
| private arrDistances: Uint16Array; | ||
| private extraBits: number = 0; | ||
| private currentHash: number = 0; | ||
| private hashHead: Int16Array; | ||
| private hashPrevious: Int16Array; | ||
| private matchStart: number = 0; | ||
| private matchLength: number = 0; | ||
| private matchPrevAvail: boolean = false; | ||
| private blockStart: number = 0; | ||
| private stringStart: number = 0; | ||
| private lookAhead: number = 0; | ||
| private dataWindow: Uint8Array; | ||
| private inputBuffer: Uint8Array; | ||
| private totalBytesIn: number = 0; | ||
| private inputOffset: number = 0; | ||
| private inputEnd: number = 0; | ||
| private windowSize: number = 1 << 15; | ||
| private windowMask: number = this.windowSize - 1; | ||
| private hashSize: number = 1 << 15; | ||
| private hashMask: number = this.hashSize - 1; | ||
| private hashShift: number = Math.floor((15 + 3 - 1) / 3); | ||
| private maxDist: number = this.windowSize - 262; | ||
| private checkSum: number = 1; | ||
| private noWrap: Boolean = false; | ||
| /** | ||
| * get compressed data | ||
| */ | ||
| get compressedData(): Uint8Array[] { | ||
| return this.stream; | ||
| } | ||
| get getCompressedString(): string { | ||
| let compressedString: string = ''; | ||
| if (this.stream !== undefined) { | ||
| for (let i: number = 0; i < this.stream.length; i++) { | ||
| compressedString += String.fromCharCode.apply(null, this.stream[i]); | ||
| } | ||
| } | ||
| return compressedString; | ||
| } | ||
| /** | ||
| * Initializes compressor and writes ZLib header if needed. | ||
| * @param {boolean} noWrap - optional if true, ZLib header and checksum will not be written. | ||
| */ | ||
| constructor(noWrap?: boolean) { | ||
| if (!CompressedStreamWriter.isHuffmanTreeInitiated) { | ||
| CompressedStreamWriter.initHuffmanTree(); | ||
| CompressedStreamWriter.isHuffmanTreeInitiated = true; | ||
| } | ||
| this.treeLiteral = new CompressorHuffmanTree(this, 286, 257, 15); | ||
| this.treeDistances = new CompressorHuffmanTree(this, 30, 1, 15); | ||
| this.treeCodeLengths = new CompressorHuffmanTree(this, 19, 4, 7); | ||
| this.arrDistances = new Uint16Array((1 << 14)); | ||
| this.arrLiterals = new Uint8Array((1 << 14)); | ||
| this.stream = []; | ||
| this.dataWindow = new Uint8Array(2 * this.windowSize); | ||
| this.hashHead = new Int16Array(this.hashSize); | ||
| this.hashPrevious = new Int16Array(this.windowSize); | ||
| this.blockStart = this.stringStart = 1; | ||
| this.noWrap = noWrap; | ||
| if (!noWrap) { | ||
| this.writeZLibHeader(); | ||
| } | ||
| } | ||
| /** | ||
| * Compresses data and writes it to the stream. | ||
| * @param {Uint8Array} data - data to compress | ||
| * @param {number} offset - offset in data | ||
| * @param {number} length - length of the data | ||
| * @returns {void} | ||
| */ | ||
| public write(data: Uint8Array | string, offset: number, length: number): void { | ||
| if (data === undefined || data === null) { | ||
| throw new Error('ArgumentException: data cannot null or undefined'); | ||
| } | ||
| let end: number = offset + length; | ||
| if (0 > offset || offset > end || end > data.length) { | ||
| throw new Error('ArgumentOutOfRangeException: Offset or length is incorrect'); | ||
| } | ||
| if (typeof data === 'string') { | ||
| let encode: Encoding = new Encoding(false); | ||
| encode.type = 'Utf8'; | ||
| data = new Uint8Array(encode.getBytes(data, 0, data.length)); | ||
| end = offset + data.length; | ||
| } | ||
| this.inputBuffer = data as Uint8Array; | ||
| this.inputOffset = offset; | ||
| this.inputEnd = end; | ||
| if (!this.noWrap) { | ||
| this.checkSum = ChecksumCalculator.checksumUpdate(this.checkSum, this.inputBuffer, this.inputOffset, end); | ||
| } | ||
| while (!(this.inputEnd === this.inputOffset) || !(this.pendingBufLength === 0)) { | ||
| this.pendingBufferFlush(); | ||
| this.compressData(false); | ||
| } | ||
| } | ||
| /** | ||
| * write ZLib header to the compressed data | ||
| * @return {void} | ||
| */ | ||
| public writeZLibHeader(): void { | ||
| /* Initialize header.*/ | ||
| let headerDate: number = (8 + (7 << 4)) << 8; | ||
| /* Save compression level.*/ | ||
| headerDate |= ((5 >> 2) & 3) << 6; | ||
| /* Align header.*/ | ||
| headerDate += 31 - (headerDate % 31); | ||
| /* Write header to stream.*/ | ||
| this.pendingBufferWriteShortBytes(headerDate); | ||
| } | ||
| /** | ||
| * Write Most Significant Bytes in to stream | ||
| * @param {number} s - check sum value | ||
| */ | ||
| public pendingBufferWriteShortBytes(s: number): void { | ||
| this.pendingBuffer[this.pendingBufLength++] = s >> 8; | ||
| this.pendingBuffer[this.pendingBufLength++] = s; | ||
| } | ||
| private compressData(finish: boolean): boolean { | ||
| let success: boolean; | ||
| do { | ||
| this.fillWindow(); | ||
| let canFlush: boolean = (finish && this.inputEnd === this.inputOffset); | ||
| success = this.compressSlow(canFlush, finish); | ||
| } | ||
| while (this.pendingBufLength === 0 && success); | ||
| return success; | ||
| } | ||
| private compressSlow(flush: boolean, finish: boolean): boolean { | ||
| if (this.lookAhead < 262 && !flush) { | ||
| return false; | ||
| } | ||
| while (this.lookAhead >= 262 || flush) { | ||
| if (this.lookAhead === 0) { | ||
| return this.lookAheadCompleted(finish); | ||
| } | ||
| if (this.stringStart >= 2 * this.windowSize - 262) { | ||
| this.slideWindow(); | ||
| } | ||
| let prevMatch: number = this.matchStart; | ||
| let prevLen: number = this.matchLength; | ||
| if (this.lookAhead >= 3) { | ||
| this.discardMatch(); | ||
| } | ||
| if (prevLen >= 3 && this.matchLength <= prevLen) { | ||
| prevLen = this.matchPreviousBest(prevMatch, prevLen); | ||
| } else { | ||
| this.matchPreviousAvailable(); | ||
| } | ||
| if (this.bufferPosition >= (1 << 14)) { | ||
| return this.huffmanIsFull(finish); | ||
| } | ||
| } | ||
| return true; | ||
| } | ||
| private discardMatch(): void { | ||
| let hashHead: number = this.insertString(); | ||
| if (hashHead !== 0 && this.stringStart - hashHead <= this.maxDist && this.findLongestMatch(hashHead)) { | ||
| if (this.matchLength <= 5 && (this.matchLength === 3 && this.stringStart - this.matchStart > 4096)) { | ||
| this.matchLength = 3 - 1; | ||
| } | ||
| } | ||
| } | ||
| private matchPreviousAvailable(): void { | ||
| if (this.matchPrevAvail) { | ||
| this.huffmanTallyLit(this.dataWindow[this.stringStart - 1] & 0xff); | ||
| } | ||
| this.matchPrevAvail = true; | ||
| this.stringStart++; | ||
| this.lookAhead--; | ||
| } | ||
| private matchPreviousBest(prevMatch: number, prevLen: number): number { | ||
| this.huffmanTallyDist(this.stringStart - 1 - prevMatch, prevLen); | ||
| prevLen -= 2; | ||
| do { | ||
| this.stringStart++; | ||
| this.lookAhead--; | ||
| if (this.lookAhead >= 3) { | ||
| this.insertString(); | ||
| } | ||
| } while (--prevLen > 0); | ||
| this.stringStart++; | ||
| this.lookAhead--; | ||
| this.matchPrevAvail = false; | ||
| this.matchLength = 3 - 1; | ||
| return prevLen; | ||
| } | ||
| private lookAheadCompleted(finish: boolean): boolean { | ||
| if (this.matchPrevAvail) { | ||
| this.huffmanTallyLit(this.dataWindow[this.stringStart - 1] & 0xff); | ||
| } | ||
| this.matchPrevAvail = false; | ||
| this.huffmanFlushBlock(this.dataWindow, this.blockStart, this.stringStart - this.blockStart, finish); | ||
| this.blockStart = this.stringStart; | ||
| return false; | ||
| } | ||
| private huffmanIsFull(finish: boolean): boolean { | ||
| let len: number = this.stringStart - this.blockStart; | ||
| if (this.matchPrevAvail) { | ||
| len--; | ||
| } | ||
| let lastBlock: boolean = (finish && this.lookAhead === 0 && !this.matchPrevAvail); | ||
| this.huffmanFlushBlock(this.dataWindow, this.blockStart, len, lastBlock); | ||
| this.blockStart += len; | ||
| return !lastBlock; | ||
| } | ||
| private fillWindow(): void { | ||
| if (this.stringStart >= this.windowSize + this.maxDist) { | ||
| this.slideWindow(); | ||
| } | ||
| while (this.lookAhead < 262 && this.inputOffset < this.inputEnd) { | ||
| let more: number = 2 * this.windowSize - this.lookAhead - this.stringStart; | ||
| if (more > this.inputEnd - this.inputOffset) { | ||
| more = this.inputEnd - this.inputOffset; | ||
| } | ||
| this.dataWindow.set(this.inputBuffer.subarray(this.inputOffset, this.inputOffset + more), this.stringStart + this.lookAhead); | ||
| this.inputOffset += more; | ||
| this.totalBytesIn += more; | ||
| this.lookAhead += more; | ||
| } | ||
| if (this.lookAhead >= 3) { | ||
| this.updateHash(); | ||
| } | ||
| } | ||
| private slideWindow(): void { | ||
| this.dataWindow.set(this.dataWindow.subarray(this.windowSize, this.windowSize + this.windowSize), 0); | ||
| this.matchStart -= this.windowSize; | ||
| this.stringStart -= this.windowSize; | ||
| this.blockStart -= this.windowSize; | ||
| for (let i: number = 0; i < this.hashSize; ++i) { | ||
| let m: number = this.hashHead[i] & 0xffff; | ||
| this.hashHead[i] = (((m >= this.windowSize) ? (m - this.windowSize) : 0)); | ||
| } | ||
| for (let i: number = 0; i < this.windowSize; i++) { | ||
| let m: number = this.hashPrevious[i] & 0xffff; | ||
| this.hashPrevious[i] = ((m >= this.windowSize) ? (m - this.windowSize) : 0); | ||
| } | ||
| } | ||
| private insertString(): number { | ||
| let match: number; | ||
| let hash: number = ((this.currentHash << this.hashShift) ^ this.dataWindow[this.stringStart + (3 - 1)]) & this.hashMask; | ||
| this.hashPrevious[this.stringStart & this.windowMask] = match = this.hashHead[hash]; | ||
| this.hashHead[hash] = this.stringStart; | ||
| this.currentHash = hash; | ||
| return match & 0xffff; | ||
| } | ||
| private findLongestMatch(curMatch: number): boolean { | ||
| let chainLen: number = 4096; | ||
| let niceLen: number = 258; | ||
| let scan: number = this.stringStart; | ||
| let match: number; | ||
| let bestEnd: number = this.stringStart + this.matchLength; | ||
| let bestLength: number = Math.max(this.matchLength, 3 - 1); | ||
| let limit: number = Math.max(this.stringStart - this.maxDist, 0); | ||
| let stringEnd: number = this.stringStart + 258 - 1; | ||
| let scanEnd1: number = this.dataWindow[bestEnd - 1]; | ||
| let scanEnd: number = this.dataWindow[bestEnd]; | ||
| let data: Uint8Array = this.dataWindow; | ||
| if (bestLength >= 32) { | ||
| chainLen >>= 2; | ||
| } | ||
| if (niceLen > this.lookAhead) { | ||
| niceLen = this.lookAhead; | ||
| } | ||
| do { | ||
| if (data[curMatch + bestLength] !== scanEnd || | ||
| data[curMatch + bestLength - 1] !== scanEnd1 || | ||
| data[curMatch] !== data[scan] || | ||
| data[curMatch + 1] !== data[scan + 1]) { | ||
| continue; | ||
| } | ||
| match = curMatch + 2; | ||
| scan += 2; | ||
| /* tslint:disable */ | ||
| while (data[++scan] === data[++match] && data[++scan] === data[++match] && | ||
| data[++scan] === data[++match] && data[++scan] === data[++match] && | ||
| data[++scan] === data[++match] && data[++scan] === data[++match] && | ||
| data[++scan] === data[++match] && data[++scan] === data[++match] && scan < stringEnd) { | ||
| /* tslint:disable */ | ||
| } | ||
| if (scan > bestEnd) { | ||
| this.matchStart = curMatch; | ||
| bestEnd = scan; | ||
| bestLength = scan - this.stringStart; | ||
| if (bestLength >= niceLen) { | ||
| break; | ||
| } | ||
| scanEnd1 = data[bestEnd - 1]; | ||
| scanEnd = data[bestEnd]; | ||
| } | ||
| scan = this.stringStart; | ||
| } | ||
| while ((curMatch = (this.hashPrevious[curMatch & this.windowMask] & 0xffff)) > limit && --chainLen !== 0); | ||
| this.matchLength = Math.min(bestLength, this.lookAhead); | ||
| return this.matchLength >= 3; | ||
| } | ||
| private updateHash(): void { | ||
| this.currentHash = (this.dataWindow[this.stringStart] << this.hashShift) ^ this.dataWindow[this.stringStart + 1]; | ||
| } | ||
| private huffmanTallyLit(literal: number): boolean { | ||
| this.arrDistances[this.bufferPosition] = 0; | ||
| this.arrLiterals[this.bufferPosition++] = literal; | ||
| this.treeLiteral.codeFrequencies[literal]++; | ||
| return this.bufferPosition >= (1 << 14); | ||
| } | ||
| private huffmanTallyDist(dist: number, len: number): boolean { | ||
| this.arrDistances[this.bufferPosition] = dist; | ||
| this.arrLiterals[this.bufferPosition++] = (len - 3); | ||
| let lc: number = this.huffmanLengthCode(len - 3); | ||
| this.treeLiteral.codeFrequencies[lc]++; | ||
| if (lc >= 265 && lc < 285) { | ||
| this.extraBits += Math.floor((lc - 261) / 4); | ||
| } | ||
| let dc: number = this.huffmanDistanceCode(dist - 1); | ||
| this.treeDistances.codeFrequencies[dc]++; | ||
| if (dc >= 4) { | ||
| this.extraBits += Math.floor((dc / 2 - 1)); | ||
| } | ||
| return this.bufferPosition >= (1 << 14); | ||
| } | ||
| private huffmanFlushBlock(stored: Uint8Array, storedOffset: number, storedLength: number, lastBlock: boolean): void { | ||
| this.treeLiteral.codeFrequencies[256]++; | ||
| this.treeLiteral.buildTree(); | ||
| this.treeDistances.buildTree(); | ||
| this.treeLiteral.calculateBLFreq(this.treeCodeLengths); | ||
| this.treeDistances.calculateBLFreq(this.treeCodeLengths); | ||
| this.treeCodeLengths.buildTree(); | ||
| let blTreeCodes: number = 4; | ||
| for (let i: number = 18; i > blTreeCodes; i--) { | ||
| if (this.treeCodeLengths.codeLengths[CompressorHuffmanTree.huffCodeLengthOrders[i]] > 0) { | ||
| blTreeCodes = i + 1; | ||
| } | ||
| } | ||
| let opt_len: number = 14 + blTreeCodes * 3 + this.treeCodeLengths.getEncodedLength() + | ||
| this.treeLiteral.getEncodedLength() + this.treeDistances.getEncodedLength() + this.extraBits; | ||
| let static_len: number = this.extraBits; | ||
| for (let i: number = 0; i < 286; i++) { | ||
| static_len += this.treeLiteral.codeFrequencies[i] * ARR_LITERAL_LENGTHS[i]; | ||
| } | ||
| for (let i = 0; i < 30; i++) { | ||
| static_len += this.treeDistances.codeFrequencies[i] * ARR_DISTANCE_LENGTHS[i]; | ||
| } | ||
| if (opt_len >= static_len) { | ||
| // Force static trees. | ||
| opt_len = static_len; | ||
| } | ||
| if (storedOffset >= 0 && storedLength + 4 < opt_len >> 3) { | ||
| this.huffmanFlushStoredBlock(stored, storedOffset, storedLength, lastBlock); | ||
| } else if (opt_len == static_len) { | ||
| // Encode with static tree. | ||
| this.pendingBufferWriteBits((1 << 1) + (lastBlock ? 1 : 0), 3); | ||
| this.treeLiteral.setStaticCodes(ARR_LITERAL_CODES, ARR_LITERAL_LENGTHS); | ||
| this.treeDistances.setStaticCodes(ARR_DISTANCE_CODES, ARR_DISTANCE_LENGTHS); | ||
| this.huffmanCompressBlock(); | ||
| this.huffmanReset(); | ||
| } else { | ||
| this.pendingBufferWriteBits((2 << 1) + (lastBlock ? 1 : 0), 3); | ||
| this.huffmanSendAllTrees(blTreeCodes); | ||
| this.huffmanCompressBlock(); | ||
| this.huffmanReset(); | ||
| } | ||
| } | ||
| private huffmanFlushStoredBlock(stored: Uint8Array, storedOffset: number, storedLength: number, lastBlock: boolean): void { | ||
| this.pendingBufferWriteBits((0 << 1) + (lastBlock ? 1 : 0), 3); | ||
| this.pendingBufferAlignToByte(); | ||
| this.pendingBufferWriteShort(storedLength); | ||
| this.pendingBufferWriteShort(~storedLength); | ||
| this.pendingBufferWriteByteBlock(stored, storedOffset, storedLength); | ||
| this.huffmanReset(); | ||
| } | ||
| private huffmanLengthCode(len: number): number { | ||
| if (len === 255) { | ||
| return 285; | ||
| } | ||
| let code: number = 257; | ||
| while (len >= 8) { | ||
| code += 4; | ||
| len >>= 1; | ||
| } | ||
| return code + len; | ||
| } | ||
| private huffmanDistanceCode(distance: number): number { | ||
| let code: number = 0; | ||
| while (distance >= 4) { | ||
| code += 2; | ||
| distance >>= 1; | ||
| } | ||
| return code + distance; | ||
| } | ||
| private huffmanSendAllTrees(blTreeCodes: number): void { | ||
| this.treeCodeLengths.buildCodes(); | ||
| this.treeLiteral.buildCodes(); | ||
| this.treeDistances.buildCodes(); | ||
| this.pendingBufferWriteBits(this.treeLiteral.treeLength - 257, 5); | ||
| this.pendingBufferWriteBits(this.treeDistances.treeLength - 1, 5); | ||
| this.pendingBufferWriteBits(blTreeCodes - 4, 4); | ||
| for (let rank: number = 0; rank < blTreeCodes; rank++) { | ||
| this.pendingBufferWriteBits( | ||
| this.treeCodeLengths.codeLengths[CompressorHuffmanTree.huffCodeLengthOrders[rank]] | ||
| , 3); | ||
| } | ||
| this.treeLiteral.writeTree(this.treeCodeLengths); | ||
| this.treeDistances.writeTree(this.treeCodeLengths); | ||
| } | ||
| private huffmanReset(): void { | ||
| this.bufferPosition = 0; | ||
| this.extraBits = 0; | ||
| this.treeLiteral.reset(); | ||
| this.treeDistances.reset(); | ||
| this.treeCodeLengths.reset(); | ||
| } | ||
| private huffmanCompressBlock(): void { | ||
| for (let i: number = 0; i < this.bufferPosition; i++) { | ||
| let literalLen: number = this.arrLiterals[i] & 255; | ||
| let dist: number = this.arrDistances[i]; | ||
| if (dist-- !== 0) { | ||
| let lc: number = this.huffmanLengthCode(literalLen); | ||
| this.treeLiteral.writeCodeToStream(lc); | ||
| let bits: number = Math.floor((lc - 261) / 4); | ||
| if (bits > 0 && bits <= 5) { | ||
| this.pendingBufferWriteBits(literalLen & ((1 << bits) - 1), bits); | ||
| } | ||
| let dc: number = this.huffmanDistanceCode(dist); | ||
| this.treeDistances.writeCodeToStream(dc); | ||
| bits = Math.floor(dc / 2 - 1); | ||
| if (bits > 0) { | ||
| this.pendingBufferWriteBits(dist & ((1 << bits) - 1), bits); | ||
| } | ||
| } else { | ||
| this.treeLiteral.writeCodeToStream(literalLen); | ||
| } | ||
| } | ||
| this.treeLiteral.writeCodeToStream(256); | ||
| } | ||
| /** | ||
| * write bits in to internal buffer | ||
| * @param {number} b - source of bits | ||
| * @param {number} count - count of bits to write | ||
| */ | ||
| public pendingBufferWriteBits(b: number, count: number): void { | ||
| let uint: Uint32Array = new Uint32Array(1); | ||
| uint[0] = this.pendingBufCache | (b << this.pendingBufBitsInCache); | ||
| this.pendingBufCache = uint[0]; | ||
| this.pendingBufBitsInCache += count; | ||
| this.pendingBufferFlushBits(); | ||
| } | ||
| private pendingBufferFlush(isClose?: boolean): void { | ||
| this.pendingBufferFlushBits(); | ||
| if (this.pendingBufLength > 0) { | ||
| let array: Uint8Array = new Uint8Array(this.pendingBufLength); | ||
| array.set(this.pendingBuffer.subarray(0, this.pendingBufLength), 0); | ||
| this.stream.push(array); | ||
| } | ||
| this.pendingBufLength = 0; | ||
| } | ||
| private pendingBufferFlushBits(): number { | ||
| let result: number = 0; | ||
| while (this.pendingBufBitsInCache >= 8 && this.pendingBufLength < (1 << 16)) { | ||
| this.pendingBuffer[this.pendingBufLength++] = this.pendingBufCache; | ||
| this.pendingBufCache >>= 8; | ||
| this.pendingBufBitsInCache -= 8; | ||
| result++; | ||
| } | ||
| return result; | ||
| } | ||
| private pendingBufferWriteByteBlock(data: Uint8Array, offset: number, length: number): void { | ||
| let array: Uint8Array = data.subarray(offset, offset + length); | ||
| this.pendingBuffer.set(array, this.pendingBufLength); | ||
| this.pendingBufLength += length; | ||
| } | ||
| private pendingBufferWriteShort(s: number): void { | ||
| this.pendingBuffer[this.pendingBufLength++] = s; | ||
| this.pendingBuffer[this.pendingBufLength++] = (s >> 8); | ||
| } | ||
| private pendingBufferAlignToByte(): void { | ||
| if (this.pendingBufBitsInCache > 0) { | ||
| this.pendingBuffer[this.pendingBufLength++] = this.pendingBufCache; | ||
| } | ||
| this.pendingBufCache = 0; | ||
| this.pendingBufBitsInCache = 0; | ||
| } | ||
| /** | ||
| * Huffman Tree literal calculation | ||
| * @private | ||
| */ | ||
| public static initHuffmanTree(): void { | ||
| let i: number = 0; | ||
| while (i < 144) { | ||
| ARR_LITERAL_CODES[i] = CompressorHuffmanTree.bitReverse((0x030 + i) << 8); | ||
| ARR_LITERAL_LENGTHS[i++] = 8; | ||
| } | ||
| while (i < 256) { | ||
| ARR_LITERAL_CODES[i] = CompressorHuffmanTree.bitReverse((0x190 - 144 + i) << 7); | ||
| ARR_LITERAL_LENGTHS[i++] = 9; | ||
| } | ||
| while (i < 280) { | ||
| ARR_LITERAL_CODES[i] = CompressorHuffmanTree.bitReverse((0x000 - 256 + i) << 9); | ||
| ARR_LITERAL_LENGTHS[i++] = 7; | ||
| } | ||
| while (i < 286) { | ||
| ARR_LITERAL_CODES[i] = CompressorHuffmanTree.bitReverse((0x0c0 - 280 + i) << 8); | ||
| ARR_LITERAL_LENGTHS[i++] = 8; | ||
| } | ||
| for (i = 0; i < 30; i++) { | ||
| ARR_DISTANCE_CODES[i] = CompressorHuffmanTree.bitReverse(i << 11); | ||
| ARR_DISTANCE_LENGTHS[i] = 5; | ||
| } | ||
| } | ||
| /** | ||
| * close the stream and write all pending buffer in to stream | ||
| * @returns {void} | ||
| */ | ||
| public close(): void { | ||
| do { | ||
| this.pendingBufferFlush(true); | ||
| if (!this.compressData(true)) { | ||
| this.pendingBufferFlush(true); | ||
| this.pendingBufferAlignToByte(); | ||
| if (!this.noWrap) { | ||
| this.pendingBufferWriteShortBytes(this.checkSum >> 16); | ||
| this.pendingBufferWriteShortBytes(this.checkSum & 0xffff); | ||
| } | ||
| this.pendingBufferFlush(true); | ||
| } | ||
| } | ||
| while (!(this.inputEnd === this.inputOffset) || | ||
| !(this.pendingBufLength === 0)); | ||
| } | ||
| /** | ||
| * release allocated un-managed resource | ||
| * @returns {void} | ||
| */ | ||
| public destroy(): void { | ||
| this.stream = []; | ||
| this.stream = undefined; | ||
| this.pendingBuffer = undefined; | ||
| this.treeLiteral = undefined; | ||
| this.treeDistances = undefined; | ||
| this.treeCodeLengths = undefined; | ||
| this.arrLiterals = undefined; | ||
| this.arrDistances = undefined; | ||
| this.hashHead = undefined; | ||
| this.hashPrevious = undefined; | ||
| this.dataWindow = undefined; | ||
| this.inputBuffer = undefined; | ||
| this.pendingBufLength = undefined; | ||
| this.pendingBufCache = undefined; | ||
| this.pendingBufBitsInCache = undefined; | ||
| this.bufferPosition = undefined; | ||
| this.extraBits = undefined; | ||
| this.currentHash = undefined; | ||
| this.matchStart = undefined; | ||
| this.matchLength = undefined; | ||
| this.matchPrevAvail = undefined; | ||
| this.blockStart = undefined; | ||
| this.stringStart = undefined; | ||
| this.lookAhead = undefined; | ||
| this.totalBytesIn = undefined; | ||
| this.inputOffset = undefined; | ||
| this.inputEnd = undefined; | ||
| this.windowSize = undefined; | ||
| this.windowMask = undefined; | ||
| this.hashSize = undefined; | ||
| this.hashMask = undefined; | ||
| this.hashShift = undefined; | ||
| this.maxDist = undefined; | ||
| this.checkSum = undefined; | ||
| this.noWrap = undefined; | ||
| } | ||
| } | ||
| /** | ||
| * represent the Huffman Tree | ||
| */ | ||
| export class CompressorHuffmanTree { | ||
| private codeFrequency: Uint16Array; | ||
| private codes: Int16Array; | ||
| private codeLength: Uint8Array; | ||
| private lengthCount: Int32Array; | ||
| private codeMinCount: number; | ||
| private codeCount: number; | ||
| private maxLength: number; | ||
| private writer: CompressedStreamWriter; | ||
| private static reverseBits: number[] = [0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15]; | ||
| public static huffCodeLengthOrders: number[] = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]; | ||
| public get treeLength(): number { | ||
| return this.codeCount; | ||
| } | ||
| public get codeLengths(): Uint8Array { | ||
| return this.codeLength; | ||
| } | ||
| public get codeFrequencies(): Uint16Array { | ||
| return this.codeFrequency; | ||
| } | ||
| /** | ||
| * Create new Huffman Tree | ||
| * @param {CompressedStreamWriter} writer instance | ||
| * @param {number} elementCount - element count | ||
| * @param {number} minCodes - minimum count | ||
| * @param {number} maxLength - maximum count | ||
| */ | ||
| constructor(writer: CompressedStreamWriter, elementCount: number, minCodes: number, maxLength: number) { | ||
| this.writer = writer; | ||
| this.codeMinCount = minCodes; | ||
| this.maxLength = maxLength; | ||
| this.codeFrequency = new Uint16Array(elementCount); | ||
| this.lengthCount = new Int32Array(maxLength); | ||
| } | ||
| public setStaticCodes(codes: Int16Array, lengths: Uint8Array): void { | ||
| let temp: Int16Array = new Int16Array(codes.length); | ||
| temp.set(codes, 0); | ||
| this.codes = temp; | ||
| let lengthTemp: Uint8Array = new Uint8Array(lengths.length); | ||
| lengthTemp.set(lengths, 0); | ||
| this.codeLength = lengthTemp; | ||
| } | ||
| /** | ||
| * reset all code data in tree | ||
| * @returns {void} | ||
| */ | ||
| public reset(): void { | ||
| for (let i: number = 0; i < this.codeFrequency.length; i++) { | ||
| this.codeFrequency[i] = 0; | ||
| } | ||
| this.codes = undefined; | ||
| this.codeLength = undefined; | ||
| } | ||
| /** | ||
| * write code to the compressor output stream | ||
| * @param {number} code - code to be written | ||
| * @returns {void} | ||
| */ | ||
| public writeCodeToStream(code: number): void { | ||
| this.writer.pendingBufferWriteBits(this.codes[code] & 0xffff, this.codeLength[code]); | ||
| } | ||
| /** | ||
| * calculate code from their frequencies | ||
| * @returns {void} | ||
| */ | ||
| public buildCodes(): void { | ||
| let nextCode: Int32Array = new Int32Array(this.maxLength); | ||
| this.codes = new Int16Array(this.codeCount); | ||
| let code: number = 0; | ||
| for (let bitsCount: number = 0; bitsCount < this.maxLength; bitsCount++) { | ||
| nextCode[bitsCount] = code; | ||
| code += this.lengthCount[bitsCount] << (15 - bitsCount); | ||
| } | ||
| for (let i: number = 0; i < this.codeCount; i++) { | ||
| let bits = this.codeLength[i]; | ||
| if (bits > 0) { | ||
| this.codes[i] = CompressorHuffmanTree.bitReverse(nextCode[bits - 1]); | ||
| nextCode[bits - 1] += 1 << (16 - bits); | ||
| } | ||
| } | ||
| } | ||
| public static bitReverse(value: number): number { | ||
| return (CompressorHuffmanTree.reverseBits[value & 15] << 12 | ||
| | CompressorHuffmanTree.reverseBits[(value >> 4) & 15] << 8 | ||
| | CompressorHuffmanTree.reverseBits[(value >> 8) & 15] << 4 | ||
| | CompressorHuffmanTree.reverseBits[value >> 12]); | ||
| } | ||
| /** | ||
| * calculate length of compressed data | ||
| * @returns {number} | ||
| */ | ||
| public getEncodedLength(): number { | ||
| let len: number = 0; | ||
| for (let i: number = 0; i < this.codeFrequency.length; i++) { | ||
| len += this.codeFrequency[i] * this.codeLength[i]; | ||
| } | ||
| return len; | ||
| } | ||
| /** | ||
| * calculate code frequencies | ||
| * @param {CompressorHuffmanTree} blTree | ||
| * @returns {void} | ||
| */ | ||
| public calculateBLFreq(blTree: CompressorHuffmanTree): void { | ||
| let maxCount: number; | ||
| let minCount: number; | ||
| let count: number; | ||
| let curLen: number = -1; | ||
| let i: number = 0; | ||
| while (i < this.codeCount) { | ||
| count = 1; | ||
| let nextLen: number = this.codeLength[i]; | ||
| if (nextLen === 0) { | ||
| maxCount = 138; | ||
| minCount = 3; | ||
| } else { | ||
| maxCount = 6; | ||
| minCount = 3; | ||
| if (curLen !== nextLen) { | ||
| blTree.codeFrequency[nextLen]++; | ||
| count = 0; | ||
| } | ||
| } | ||
| curLen = nextLen; | ||
| i++; | ||
| while (i < this.codeCount && curLen === this.codeLength[i]) { | ||
| i++; | ||
| if (++count >= maxCount) { | ||
| break; | ||
| } | ||
| } | ||
| if (count < minCount) { | ||
| blTree.codeFrequency[curLen] += count; | ||
| } else if (curLen !== 0) { | ||
| blTree.codeFrequency[16]++; | ||
| } else if (count <= 10) { | ||
| blTree.codeFrequency[17]++; | ||
| } else { | ||
| blTree.codeFrequency[18]++; | ||
| } | ||
| } | ||
| } | ||
| /** | ||
| * @param {CompressorHuffmanTree} blTree - write tree to output stream | ||
| * @returns {void} | ||
| */ | ||
| public writeTree(blTree: CompressorHuffmanTree): void { | ||
| let maxRepeatCount: number; | ||
| let minRepeatCount: number; | ||
| let currentRepeatCount: number; | ||
| let currentCodeLength: number = -1; | ||
| let i: number = 0; | ||
| while (i < this.codeCount) { | ||
| currentRepeatCount = 1; | ||
| let nextLen: number = this.codeLength[i]; | ||
| if (nextLen === 0) { | ||
| maxRepeatCount = 138; | ||
| minRepeatCount = 3; | ||
| } else { | ||
| maxRepeatCount = 6; | ||
| minRepeatCount = 3; | ||
| if (currentCodeLength !== nextLen) { | ||
| blTree.writeCodeToStream(nextLen); | ||
| currentRepeatCount = 0; | ||
| } | ||
| } | ||
| currentCodeLength = nextLen; | ||
| i++; | ||
| while (i < this.codeCount && currentCodeLength === this.codeLength[i]) { | ||
| i++; | ||
| if (++currentRepeatCount >= maxRepeatCount) { | ||
| break; | ||
| } | ||
| } | ||
| if (currentRepeatCount < minRepeatCount) { | ||
| while (currentRepeatCount-- > 0) { | ||
| blTree.writeCodeToStream(currentCodeLength); | ||
| } | ||
| } else if (currentCodeLength !== 0) { | ||
| blTree.writeCodeToStream(16); | ||
| this.writer.pendingBufferWriteBits(currentRepeatCount - 3, 2); | ||
| } else if (currentRepeatCount <= 10) { | ||
| blTree.writeCodeToStream(17); | ||
| this.writer.pendingBufferWriteBits(currentRepeatCount - 3, 3); | ||
| } else { | ||
| blTree.writeCodeToStream(18); | ||
| this.writer.pendingBufferWriteBits(currentRepeatCount - 11, 7); | ||
| } | ||
| } | ||
| } | ||
| /** | ||
| * Build huffman tree | ||
| * @returns {void} | ||
| */ | ||
| public buildTree(): void { | ||
| let codesCount: number = this.codeFrequency.length; | ||
| let arrTree: Int32Array = new Int32Array(codesCount); | ||
| let treeLength: number = 0; | ||
| let maxCount: number = 0; | ||
| for (let n = 0; n < codesCount; n++) { | ||
| let freq: number = this.codeFrequency[n]; | ||
| if (freq !== 0) { | ||
| let pos: number = treeLength++; | ||
| let pPos: number = 0; | ||
| while (pos > 0 && this.codeFrequency[arrTree[pPos = Math.floor((pos - 1) / 2)]] > freq) { | ||
| arrTree[pos] = arrTree[pPos]; | ||
| pos = pPos; | ||
| } | ||
| arrTree[pos] = n; | ||
| maxCount = n; | ||
| } | ||
| } | ||
| while (treeLength < 2) { | ||
| arrTree[treeLength++] = | ||
| (maxCount < 2) ? ++maxCount : 0; | ||
| } | ||
| this.codeCount = Math.max(maxCount + 1, this.codeMinCount); | ||
| let leafsCount: number = treeLength; | ||
| let nodesCount: number = leafsCount; | ||
| let child: Int32Array = new Int32Array(4 * treeLength - 2); | ||
| let values: Int32Array = new Int32Array(2 * treeLength - 1); | ||
| for (let i: number = 0; i < treeLength; i++) { | ||
| let node: number = arrTree[i]; | ||
| let iIndex: number = 2 * i; | ||
| child[iIndex] = node; | ||
| child[iIndex + 1] = -1; | ||
| values[i] = (this.codeFrequency[node] << 8); | ||
| arrTree[i] = i; | ||
| } | ||
| this.constructHuffmanTree(arrTree, treeLength, values, nodesCount, child); | ||
| this.buildLength(child); | ||
| } | ||
| private constructHuffmanTree(arrTree: Int32Array, treeLength: number, values: Int32Array, nodesCount: number, child: Int32Array): void { | ||
| do { | ||
| let first: number = arrTree[0]; | ||
| let last: number = arrTree[--treeLength]; | ||
| let lastVal: number = values[last]; | ||
| let pPos: number = 0; | ||
| let path: number = 1; | ||
| while (path < treeLength) { | ||
| if (path + 1 < treeLength && values[arrTree[path]] > values[arrTree[path + 1]]) { | ||
| path++; | ||
| } | ||
| arrTree[pPos] = arrTree[path]; | ||
| pPos = path; path = pPos * 2 + 1; | ||
| } | ||
| while ((path = pPos) > 0 && values[arrTree[pPos = Math.floor((path - 1) / 2)]] > lastVal) { | ||
| arrTree[path] = arrTree[pPos]; | ||
| } | ||
| arrTree[path] = last; | ||
| let second: number = arrTree[0]; | ||
| last = nodesCount++; | ||
| child[2 * last] = first; | ||
| child[2 * last + 1] = second; | ||
| let minDepth: number = Math.min(values[first] & 0xff, values[second] & 0xff); | ||
| values[last] = lastVal = values[first] + values[second] - minDepth + 1; | ||
| pPos = 0; | ||
| path = 1; | ||
| /* tslint:disable */ | ||
| while (path < treeLength) { | ||
| if (path + 1 < treeLength && values[arrTree[path]] > values[arrTree[path + 1]]) { | ||
| path++; | ||
| } | ||
| arrTree[pPos] = arrTree[path]; | ||
| pPos = path; | ||
| path = pPos * 2 + 1; | ||
| } /* tslint:disable */ | ||
| while ((path = pPos) > 0 && values[arrTree[pPos = Math.floor((path - 1) / 2)]] > lastVal) { | ||
| arrTree[path] = arrTree[pPos]; | ||
| } | ||
| arrTree[path] = last; | ||
| } | ||
| while (treeLength > 1); | ||
| } | ||
| private buildLength(child: Int32Array): void { | ||
| this.codeLength = new Uint8Array(this.codeFrequency.length); | ||
| let numNodes: number = Math.floor(child.length / 2); | ||
| let numLeafs: number = Math.floor((numNodes + 1) / 2); | ||
| let overflow: number = 0; | ||
| for (let i = 0; i < this.maxLength; i++) { | ||
| this.lengthCount[i] = 0; | ||
| } | ||
| overflow = this.calculateOptimalCodeLength(child, overflow, numNodes); | ||
| if (overflow === 0) { | ||
| return; | ||
| } | ||
| let iIncreasableLength: number = this.maxLength - 1; | ||
| do { | ||
| while (this.lengthCount[--iIncreasableLength] === 0) { | ||
| /* tslint:disable */ | ||
| } | ||
| do { | ||
| this.lengthCount[iIncreasableLength]--; | ||
| this.lengthCount[++iIncreasableLength]++; | ||
| overflow -= (1 << (this.maxLength - 1 - iIncreasableLength)); | ||
| } | ||
| while (overflow > 0 && iIncreasableLength < this.maxLength - 1); | ||
| } | ||
| while (overflow > 0); | ||
| this.recreateTree(child, overflow, numLeafs); | ||
| } | ||
| private recreateTree(child: Int32Array, overflow: number, numLeafs: number): void { | ||
| this.lengthCount[this.maxLength - 1] += overflow; | ||
| this.lengthCount[this.maxLength - 2] -= overflow; | ||
| let nodePtr: number = 2 * numLeafs; | ||
| for (let bits: number = this.maxLength; bits !== 0; bits--) { | ||
| let n = this.lengthCount[bits - 1]; | ||
| while (n > 0) { | ||
| let childPtr: number = 2 * child[nodePtr++]; | ||
| if (child[childPtr + 1] === -1) { | ||
| this.codeLength[child[childPtr]] = bits; | ||
| n--; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| private calculateOptimalCodeLength(child: Int32Array, overflow: number, numNodes: number): number { | ||
| let lengths: Int32Array = new Int32Array(numNodes); | ||
| lengths[numNodes - 1] = 0; | ||
| for (let i: number = numNodes - 1; i >= 0; i--) { | ||
| let childIndex: number = 2 * i + 1; | ||
| if (child[childIndex] !== -1) { | ||
| let bitLength: number = lengths[i] + 1; | ||
| if (bitLength > this.maxLength) { | ||
| bitLength = this.maxLength; | ||
| overflow++; | ||
| } | ||
| lengths[child[childIndex - 1]] = lengths[child[childIndex]] = bitLength; | ||
| } else { | ||
| let bitLength = lengths[i]; | ||
| this.lengthCount[bitLength - 1]++; | ||
| this.codeLength[child[childIndex - 1]] = lengths[i]; | ||
| } | ||
| } | ||
| return overflow | ||
| } | ||
| } | ||
| /** | ||
| * Checksum calculator, based on Adler32 algorithm. | ||
| */ | ||
| export class ChecksumCalculator { | ||
| private static checkSumBitOffset: number = 16; | ||
| private static checksumBase: number = 65521; | ||
| private static checksumIterationCount: number = 3800; | ||
| /** | ||
| * Updates checksum by calculating checksum of the | ||
| * given buffer and adding it to current value. | ||
| * @param {number} checksum - current checksum. | ||
| * @param {Uint8Array} buffer - data byte array. | ||
| * @param {number} offset - offset in the buffer. | ||
| * @param {number} length - length of data to be used from the stream. | ||
| * @returns {number} | ||
| */ | ||
| public static checksumUpdate(checksum: number, buffer: Uint8Array, offset: number, length: number): number { | ||
| let uint = new Uint32Array(1); | ||
| uint[0] = checksum; | ||
| let checksum_uint: number = uint[0]; | ||
| let s1 = uint[0] = checksum_uint & 65535; | ||
| let s2 = uint[0] = checksum_uint >> ChecksumCalculator.checkSumBitOffset; | ||
| while (length > 0) { | ||
| let steps = Math.min(length, ChecksumCalculator.checksumIterationCount); | ||
| length -= steps; | ||
| while (--steps >= 0) { | ||
| s1 = s1 + (uint[0] = (buffer[offset++] & 255)); | ||
| s2 = s2 + s1; | ||
| } | ||
| s1 %= ChecksumCalculator.checksumBase; | ||
| s2 %= ChecksumCalculator.checksumBase; | ||
| } | ||
| checksum_uint = (s2 << ChecksumCalculator.checkSumBitOffset) | s1; | ||
| return checksum_uint; | ||
| } | ||
| } | ||
| /* eslint-enable */ |
| import { CompressedStreamReader } from './index'; | ||
| export declare class DecompressorHuffmanTree { | ||
| private static MAX_BITLEN; | ||
| private m_Tree; | ||
| static m_LengthTree: DecompressorHuffmanTree; | ||
| static m_DistanceTree: DecompressorHuffmanTree; | ||
| constructor(lengths: Uint8Array); | ||
| static init(): void; | ||
| private prepareData; | ||
| private treeFromData; | ||
| private buildTree; | ||
| unpackSymbol(input: CompressedStreamReader): number; | ||
| static readonly lengthTree: DecompressorHuffmanTree; | ||
| static readonly distanceTree: DecompressorHuffmanTree; | ||
| } |
| /* eslint-disable */ | ||
| import { Utils, CompressedStreamReader } from './index'; | ||
| export class DecompressorHuffmanTree{ | ||
| /// <summary> | ||
| /// Maximum count of bits. | ||
| /// </summary> | ||
| private static MAX_BITLEN: number = 15; | ||
| /// <summary> | ||
| /// Build huffman tree. | ||
| /// </summary> | ||
| private m_Tree: Int16Array; | ||
| /// <summary> | ||
| /// Huffman tree for encoding and decoding lengths. | ||
| /// </summary> | ||
| public static m_LengthTree: DecompressorHuffmanTree; | ||
| /// <summary> | ||
| /// huffman tree for encoding and decoding distances. | ||
| /// </summary> | ||
| public static m_DistanceTree: DecompressorHuffmanTree; | ||
| public constructor(lengths: Uint8Array) { | ||
| this.buildTree( lengths ); | ||
| } | ||
| public static init(): void { | ||
| let lengths: Uint8Array; | ||
| let index: number ; | ||
| // Generate huffman tree for lengths. | ||
| lengths = new Uint8Array(288); | ||
| index = 0; | ||
| while( index < 144 ) | ||
| { | ||
| lengths[ index++ ] = 8; | ||
| } | ||
| while( index < 256 ) | ||
| { | ||
| lengths[ index++ ] = 9; | ||
| } | ||
| while( index < 280 ) | ||
| { | ||
| lengths[ index++ ] = 7; | ||
| } | ||
| while( index < 288 ) | ||
| { | ||
| lengths[ index++ ] = 8; | ||
| } | ||
| DecompressorHuffmanTree.m_LengthTree = new DecompressorHuffmanTree( lengths ); | ||
| // Generate huffman tree for distances. | ||
| lengths = new Uint8Array(32); | ||
| index = 0; | ||
| while( index < 32 ) | ||
| { | ||
| lengths[ index++ ] = 5; | ||
| } | ||
| DecompressorHuffmanTree.m_DistanceTree = new DecompressorHuffmanTree( lengths ); | ||
| } | ||
| /// <summary> | ||
| /// Prepares data for generating huffman tree. | ||
| /// </summary> | ||
| /// <param name="blCount">Array of counts of each code length.</param> | ||
| /// <param name="nextCode">Numerical values of the smallest code for each code length.</param> | ||
| /// <param name="lengths">Array of code lengths.</param> | ||
| /// <param name="treeSize">Calculated tree size.</param> | ||
| /// <returns>Code.</returns> | ||
| private prepareData(blCount: number[], nextCode: number[], lengths:Uint8Array) : any | ||
| { | ||
| let code: number = 0; | ||
| let treeSize: number = 512; | ||
| // Count number of codes for each code length. | ||
| for( let i = 0; i < lengths.length; i++ ) | ||
| { | ||
| let length = lengths[ i ]; | ||
| if( length > 0 ) | ||
| { | ||
| blCount[ length ]++; | ||
| } | ||
| } | ||
| for( let bits = 1; bits <= DecompressorHuffmanTree.MAX_BITLEN; bits++ ) | ||
| { | ||
| nextCode[ bits ] = code; | ||
| code += blCount[ bits ] << ( 16 - bits ); | ||
| if( bits >= 10 ) | ||
| { | ||
| let start = nextCode[ bits ] & 0x1ff80; | ||
| let end = code & 0x1ff80; | ||
| treeSize += ( end - start ) >> ( 16 - bits ); | ||
| } | ||
| } | ||
| /* if( code != 65536 ) | ||
| throw new ZipException( "Code lengths don't add up properly." );*/ | ||
| return { 'code': code, 'treeSize': treeSize }; | ||
| } | ||
| /// <summary> | ||
| /// Generates huffman tree. | ||
| /// </summary> | ||
| /// <param name="blCount">Array of counts of each code length.</param> | ||
| /// <param name="nextCode">Numerical values of the smallest code for each code length.</param> | ||
| /// <param name="code">Precalculated code.</param> | ||
| /// <param name="lengths">Array of code lengths.</param> | ||
| /// <param name="treeSize">Calculated size of the tree.</param> | ||
| /// <returns>Generated tree.</returns> | ||
| private treeFromData(blCount: number[], nextCode: number[], lengths:Uint8Array, code: number, treeSize: number): Int16Array | ||
| { | ||
| let tree: Int16Array = new Int16Array(treeSize); | ||
| let pointer: number = 512; | ||
| let increment: number = 1 << 7; | ||
| for( let bits = DecompressorHuffmanTree.MAX_BITLEN; bits >= 10; bits-- ) | ||
| { | ||
| let end = code & 0x1ff80; | ||
| code -= blCount[ bits ] << ( 16 - bits ); | ||
| let start = code & 0x1ff80; | ||
| for( let i = start; i < end; i += increment ) | ||
| { | ||
| tree[ Utils.bitReverse( i ) ] = Utils.bitConverterInt32ToInt16( ( -pointer << 4 ) | bits ); | ||
| pointer += 1 << ( bits - 9 ); | ||
| } | ||
| } | ||
| for( let i = 0; i < lengths.length; i++ ) | ||
| { | ||
| let bits = lengths[ i ]; | ||
| if( bits == 0 ) | ||
| { | ||
| continue; | ||
| } | ||
| code = nextCode[ bits ]; | ||
| let revcode = Utils.bitReverse( code ); | ||
| if( bits <= 9 ) | ||
| { | ||
| do | ||
| { | ||
| tree[ revcode ] = Utils.bitConverterInt32ToInt16( ( i << 4 ) | bits ); | ||
| revcode += 1 << bits; | ||
| } | ||
| while( revcode < 512 ); | ||
| } | ||
| else | ||
| { | ||
| let subTree = tree[ revcode & 511 ]; | ||
| let treeLen = 1 << ( subTree & 15 ); | ||
| subTree = -( subTree >> 4 ); | ||
| do | ||
| { | ||
| tree[ subTree | ( revcode >> 9 ) ] = Utils.bitConverterInt32ToInt16( ( i << 4 ) | bits ); | ||
| revcode += 1 << bits; | ||
| } | ||
| while( revcode < treeLen ); | ||
| } | ||
| nextCode[ bits ] = code + ( 1 << ( 16 - bits ) ); | ||
| } | ||
| return tree; | ||
| } | ||
| /// <summary> | ||
| /// Builds huffman tree from array of code lengths. | ||
| /// </summary> | ||
| /// <param name="lengths">Array of code lengths.</param> | ||
| private buildTree( lengths: Uint8Array ): void | ||
| { | ||
| // Count of codes for each code length. | ||
| let blCount: number[] = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]; | ||
| // Numerical value of the smallest code for each code length. | ||
| let nextCode: number[] = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]; | ||
| let prepareData: any = this.prepareData( blCount, nextCode, lengths); | ||
| this.m_Tree = this.treeFromData( blCount, nextCode, lengths, prepareData.code, prepareData.treeSize ); | ||
| } | ||
| /// <summary> | ||
| /// Reads and decompresses one symbol. | ||
| /// </summary> | ||
| /// <param name="input"></param> | ||
| /// <returns></returns> | ||
| public unpackSymbol( input: CompressedStreamReader ): number | ||
| { | ||
| let lookahead: number; | ||
| let symbol: number; | ||
| if( ( lookahead = input.peekBits( 9 ) ) >= 0 ) | ||
| { | ||
| if( ( symbol = this.m_Tree[ lookahead ] ) >= 0 ) | ||
| { | ||
| input.skipBits( (symbol & 15) ); | ||
| return symbol >> 4; | ||
| } | ||
| let subtree: number = -( symbol >> 4 ); | ||
| let bitlen: number = symbol & 15; | ||
| if( ( lookahead = input.peekBits( bitlen ) ) >= 0 ) | ||
| { | ||
| symbol = this.m_Tree[ subtree | ( lookahead >> 9 ) ]; | ||
| input.skipBits( (symbol & 15) ); | ||
| return symbol >> 4; | ||
| } | ||
| else | ||
| { | ||
| let bits = input.availableBits; | ||
| lookahead = input.peekBits( bits ); | ||
| symbol = this.m_Tree[ subtree | ( lookahead >> 9 ) ]; | ||
| if( ( symbol & 15 ) <= bits ) | ||
| { | ||
| input.skipBits( (symbol & 15) ); | ||
| return symbol >> 4; | ||
| } | ||
| else | ||
| { | ||
| return -1; | ||
| } | ||
| } | ||
| } | ||
| else | ||
| { | ||
| let bits = input.availableBits; | ||
| lookahead = input.peekBits( bits ); | ||
| symbol = this.m_Tree[ lookahead ]; | ||
| if( symbol >= 0 && ( symbol & 15 ) <= bits ) | ||
| { | ||
| input.skipBits( (symbol & 15) ); | ||
| return symbol >> 4; | ||
| } | ||
| else | ||
| { | ||
| return -1; | ||
| } | ||
| } | ||
| } | ||
| /// <summary> | ||
| /// GET huffman tree for encoding and decoding lengths. | ||
| /// </summary> | ||
| public static get lengthTree(): DecompressorHuffmanTree{ | ||
| return this.m_LengthTree; | ||
| } | ||
| /// <summary> | ||
| /// GET huffman tree for encoding and decoding distances. | ||
| /// </summary> | ||
| public static get distanceTree(): DecompressorHuffmanTree { | ||
| return this.m_DistanceTree; | ||
| } | ||
| } | ||
| /* eslint-enable */ |
| /** | ||
| * export ZipArchive class | ||
| */ | ||
| export * from './zip-archive'; | ||
| export * from './compression-writer'; | ||
| export * from './utils'; | ||
| export * from './decompressor-huffman-tree'; | ||
| export * from './compression-reader'; |
| /** | ||
| * export ZipArchive class | ||
| */ | ||
| export * from './zip-archive'; | ||
| export * from './compression-writer'; | ||
| export * from './utils'; | ||
| export * from './decompressor-huffman-tree'; | ||
| export * from './compression-reader'; |
| export declare class Utils { | ||
| private static reverseBits; | ||
| static huffCodeLengthOrders: number[]; | ||
| static bitReverse(value: number): number; | ||
| static bitConverterToInt32(value: Uint8Array, index: number): number; | ||
| static bitConverterToInt16(value: Uint8Array, index: number): number; | ||
| static bitConverterToUInt32(value: number): number; | ||
| static bitConverterToUInt16(value: Uint8Array, index: number): number; | ||
| static bitConverterUintToInt32(value: number): number; | ||
| static bitConverterInt32ToUint(value: number): number; | ||
| static bitConverterInt32ToInt16(value: number): number; | ||
| static byteToString(value: Uint8Array): string; | ||
| static byteIntToString(value: Int8Array): string; | ||
| static arrayCopy(source: Uint8Array, sourceIndex: number, destination: Uint8Array, destinationIndex: number, dataToCopy: number): void; | ||
| static mergeArray(arrayOne: Uint8Array, arrayTwo: Uint8Array): Uint8Array; | ||
| /** | ||
| * @private | ||
| */ | ||
| static encodedString(input: string): Uint8Array; | ||
| } |
-129
| /* eslint-disable */ | ||
| export class Utils { | ||
| private static reverseBits: number[] = [0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15]; | ||
| public static huffCodeLengthOrders: number[] = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]; | ||
| public static bitReverse(value: number): number { | ||
| return (Utils.reverseBits[value & 15] << 12 | ||
| | Utils.reverseBits[(value >> 4) & 15] << 8 | ||
| | Utils.reverseBits[(value >> 8) & 15] << 4 | ||
| | Utils.reverseBits[value >> 12]); | ||
| } | ||
| public static bitConverterToInt32(value: Uint8Array, index: number): number { | ||
| return value[index] | value[index+1] << 8 | value[index+2] << 16 | value[index+3] << 24; | ||
| } | ||
| public static bitConverterToInt16(value: Uint8Array, index: number): number { | ||
| return value[index] | value[index+1] << 8; | ||
| } | ||
| public static bitConverterToUInt32(value: number): number { | ||
| let uint: Uint32Array = new Uint32Array(1); | ||
| uint[0] = value; | ||
| return uint[0]; | ||
| } | ||
| public static bitConverterToUInt16(value: Uint8Array, index: number): number { | ||
| let uint: Uint16Array = new Uint16Array(1); | ||
| uint[0] = (value[index] | value[index+1] << 8); | ||
| return uint[0]; | ||
| } | ||
| public static bitConverterUintToInt32(value: number): number { | ||
| let uint: Int32Array = new Int32Array(1); | ||
| uint[0] = value; | ||
| return uint[0]; | ||
| } | ||
| public static bitConverterInt32ToUint(value: number): number { | ||
| let uint: Uint32Array = new Uint32Array(1); | ||
| uint[0] = value; | ||
| return uint[0]; | ||
| } | ||
| public static bitConverterInt32ToInt16(value: number): number { | ||
| let uint: Int16Array = new Int16Array(1); | ||
| uint[0] = value; | ||
| return uint[0]; | ||
| } | ||
| public static byteToString(value: Uint8Array): string { | ||
| let str: string = ''; | ||
| for (let i: number = 0; i < value.length; i++) { | ||
| str += String.fromCharCode(value[i]); | ||
| } | ||
| return str; | ||
| } | ||
| public static byteIntToString(value: Int8Array): string { | ||
| let str: string = ''; | ||
| for (let i: number = 0; i < value.length; i++) { | ||
| str += String.fromCharCode(value[i]); | ||
| } | ||
| return str; | ||
| } | ||
| public static arrayCopy(source: Uint8Array, sourceIndex: number, destination: Uint8Array, destinationIndex:number, dataToCopy: number): void { | ||
| let temp: Uint8Array = new Uint8Array(source.buffer, sourceIndex); | ||
| let data: Uint8Array = temp.subarray(0, dataToCopy); | ||
| destination.set(data, destinationIndex); | ||
| } | ||
| public static mergeArray(arrayOne: Uint8Array, arrayTwo: Uint8Array): Uint8Array { | ||
| let mergedArray: Uint8Array = new Uint8Array(arrayOne.length + arrayTwo.length); | ||
| mergedArray.set(arrayOne); | ||
| mergedArray.set(arrayTwo, arrayOne.length); | ||
| return mergedArray; | ||
| } | ||
| /** | ||
| * @private | ||
| */ | ||
| public static encodedString(input: string): Uint8Array { | ||
| let keyStr: string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; | ||
| let chr1: number; | ||
| let chr2: number; | ||
| let chr3: number; | ||
| let encode1: number; | ||
| let encode2: number; | ||
| let encode3: number; | ||
| let encode4: number; | ||
| let count: number = 0; | ||
| let resultIndex: number = 0; | ||
| /*let dataUrlPrefix: string = 'data:';*/ | ||
| input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ''); | ||
| let totalLength: number = input.length * 3 / 4; | ||
| if (input.charAt(input.length - 1) === keyStr.charAt(64)) { | ||
| totalLength--; | ||
| } | ||
| if (input.charAt(input.length - 2) === keyStr.charAt(64)) { | ||
| totalLength--; | ||
| } | ||
| if (totalLength % 1 !== 0) { | ||
| // totalLength is not an integer, the length does not match a valid | ||
| // base64 content. That can happen if: | ||
| // - the input is not a base64 content | ||
| // - the input is *almost* a base64 content, with a extra chars at the | ||
| // beginning or at the end | ||
| // - the input uses a base64 variant (base64url for example) | ||
| throw new Error('Invalid base64 input, bad content length.'); | ||
| } | ||
| let output: Uint8Array = new Uint8Array(totalLength | 0); | ||
| while (count < input.length) { | ||
| encode1 = keyStr.indexOf(input.charAt(count++)); | ||
| encode2 = keyStr.indexOf(input.charAt(count++)); | ||
| encode3 = keyStr.indexOf(input.charAt(count++)); | ||
| encode4 = keyStr.indexOf(input.charAt(count++)); | ||
| chr1 = (encode1 << 2) | (encode2 >> 4); | ||
| chr2 = ((encode2 & 15) << 4) | (encode3 >> 2); | ||
| chr3 = ((encode3 & 3) << 6) | encode4; | ||
| output[resultIndex++] = chr1; | ||
| if (encode3 !== 64) { | ||
| output[resultIndex++] = chr2; | ||
| } | ||
| if (encode4 !== 64) { | ||
| output[resultIndex++] = chr3; | ||
| } | ||
| } | ||
| return output; | ||
| } | ||
| } | ||
| /* eslint-enable */ |
| import { Stream } from './index'; | ||
| /** | ||
| * class provide compression library | ||
| * ```typescript | ||
| * let archive = new ZipArchive(); | ||
| * archive.compressionLevel = 'Normal'; | ||
| * let archiveItem = new ZipArchiveItem(archive, 'directoryName\fileName.txt'); | ||
| * archive.addItem(archiveItem); | ||
| * archive.save(fileName.zip); | ||
| * ``` | ||
| */ | ||
| export declare class ZipArchive { | ||
| private files; | ||
| private level; | ||
| readonly items: (ZipArchiveItem | string)[]; | ||
| /** | ||
| * gets compression level | ||
| */ | ||
| /** | ||
| * sets compression level | ||
| */ | ||
| compressionLevel: CompressionLevel; | ||
| /** | ||
| * gets items count | ||
| */ | ||
| readonly length: number; | ||
| /** | ||
| * constructor for creating ZipArchive instance | ||
| */ | ||
| constructor(); | ||
| /** | ||
| * add new item to archive | ||
| * @param {ZipArchiveItem} item - item to be added | ||
| * @returns {void} | ||
| */ | ||
| addItem(item: ZipArchiveItem): void; | ||
| /** | ||
| * add new directory to archive | ||
| * @param directoryName directoryName to be created | ||
| * @returns {void} | ||
| */ | ||
| addDirectory(directoryName: string): void; | ||
| /** | ||
| * gets item at specified index | ||
| * @param {number} index - item index | ||
| * @returns {ZipArchiveItem} | ||
| */ | ||
| getItem(index: number): ZipArchiveItem; | ||
| /** | ||
| * determines whether an element is in the collection | ||
| * @param {string | ZipArchiveItem} item - item to search | ||
| * @returns {boolean} | ||
| */ | ||
| contains(item: string | ZipArchiveItem): boolean; | ||
| open(base64String: string): void; | ||
| readCentralDirectoryDataAndExtractItems(stream: Stream): void; | ||
| /** | ||
| * save archive with specified file name | ||
| * @param {string} fileName save archive with specified file name | ||
| * @returns {Promise<ZipArchive>} | ||
| */ | ||
| save(fileName: string): Promise<ZipArchive>; | ||
| /** | ||
| * Save archive as blob | ||
| * @return {Promise<Blob>} | ||
| */ | ||
| saveAsBlob(): Promise<Blob>; | ||
| private saveInternal; | ||
| /** | ||
| * release allocated un-managed resource | ||
| * @returns {void} | ||
| */ | ||
| destroy(): void; | ||
| private getCompressedData; | ||
| private compressData; | ||
| private constructZippedObject; | ||
| private writeHeader; | ||
| private writeZippedContent; | ||
| private writeCentralDirectory; | ||
| private writeFooter; | ||
| private getArrayBuffer; | ||
| private getBytes; | ||
| private getModifiedTime; | ||
| private getModifiedDate; | ||
| private calculateCrc32Value; | ||
| /** | ||
| * construct cyclic redundancy code table | ||
| * @private | ||
| */ | ||
| static initCrc32Table(): void; | ||
| static findValueFromEnd(stream: Stream, value: number, maxCount: number): number; | ||
| static ReadInt32(stream: Stream): number; | ||
| static ReadInt16(stream: Stream): number; | ||
| static ReadUInt16(stream: Stream): number; | ||
| } | ||
| export declare class ZipArchiveItemHelper { | ||
| compressedStream: Uint8Array; | ||
| name: string; | ||
| unCompressedStream: Uint8Array; | ||
| headerSignature: number; | ||
| private options; | ||
| private compressionMethod; | ||
| checkCrc: boolean; | ||
| private crc32; | ||
| private compressedSize; | ||
| private originalSize; | ||
| private localHeaderOffset; | ||
| private externalAttributes; | ||
| readCentralDirectoryData(stream: Stream): void; | ||
| readData(stream: Stream, checkCrc: boolean): void; | ||
| decompressData(): void; | ||
| private decompressDataOld; | ||
| private readLocalHeader; | ||
| private readCompressedData; | ||
| } | ||
| /** | ||
| * Class represent unique ZipArchive item | ||
| * ```typescript | ||
| * let archiveItem = new ZipArchiveItem(archive, 'directoryName\fileName.txt'); | ||
| * ``` | ||
| */ | ||
| export declare class ZipArchiveItem { | ||
| data: Blob | ArrayBuffer; | ||
| private decompressedStream; | ||
| private fileName; | ||
| readonly dataStream: Blob | ArrayBuffer; | ||
| /** | ||
| * Get the name of archive item | ||
| * @returns string | ||
| */ | ||
| /** | ||
| * Set the name of archive item | ||
| * @param {string} value | ||
| */ | ||
| name: string; | ||
| /** | ||
| * constructor for creating {ZipArchiveItem} instance | ||
| * @param {Blob|ArrayBuffer} data file data | ||
| * @param {itemName} itemName absolute file path | ||
| */ | ||
| constructor(data: Blob | ArrayBuffer, itemName: string); | ||
| /** | ||
| * release allocated un-managed resource | ||
| * @returns {void} | ||
| */ | ||
| destroy(): void; | ||
| } | ||
| export interface CompressedData { | ||
| fileName: string; | ||
| compressedData: Uint8Array[] | string; | ||
| uncompressedDataSize: number; | ||
| compressedSize: number; | ||
| crc32Value: number; | ||
| compressionType: string; | ||
| isDirectory: boolean; | ||
| } | ||
| export interface ZippedObject { | ||
| localHeader: string; | ||
| centralDir: string; | ||
| compressedData: CompressedData; | ||
| } | ||
| /** | ||
| * Compression level. | ||
| */ | ||
| export declare type CompressionLevel = 'NoCompression' | 'Normal'; |
| /* eslint-disable */ | ||
| import { CompressedStreamWriter, Stream, CompressedStreamReader } from './index'; | ||
| import { Save } from '@syncfusion/ej2-file-utils'; | ||
| import { Utils } from './utils'; | ||
| const CRC32TABLE: number[] = []; | ||
| /// <summary> | ||
| /// Size of the int value in bytes. | ||
| /// </summary> | ||
| const INT_SIZE: number = 4; | ||
| /// <summary> | ||
| /// Size of the short value in bytes. | ||
| /// </summary> | ||
| const SHORT_SIZE = 2; | ||
| /// <summary> | ||
| /// End of central directory signature. | ||
| /// </summary> | ||
| const CentralDirectoryEndSignature: number = 0x06054b50; | ||
| /// <summary> | ||
| /// Offset to the size field in the End of central directory record. | ||
| /// </summary> | ||
| const CentralDirSizeOffset: number = 12; | ||
| /// <summary> | ||
| /// Central header signature. | ||
| /// </summary> | ||
| const CentralHeaderSignature: number = 0x02014b50; | ||
| /// <summary> | ||
| /// Buffer size. | ||
| /// </summary> | ||
| const BufferSize: number = 4096; | ||
| /** | ||
| * class provide compression library | ||
| * ```typescript | ||
| * let archive = new ZipArchive(); | ||
| * archive.compressionLevel = 'Normal'; | ||
| * let archiveItem = new ZipArchiveItem(archive, 'directoryName\fileName.txt'); | ||
| * archive.addItem(archiveItem); | ||
| * archive.save(fileName.zip); | ||
| * ``` | ||
| */ | ||
| export class ZipArchive { | ||
| private files: (ZipArchiveItem | string)[]; | ||
| private level: CompressionLevel; | ||
| public get items(): (ZipArchiveItem | string)[] { | ||
| return this.files; | ||
| } | ||
| /** | ||
| * gets compression level | ||
| */ | ||
| get compressionLevel(): CompressionLevel { | ||
| return this.level; | ||
| } | ||
| /** | ||
| * sets compression level | ||
| */ | ||
| set compressionLevel(level: CompressionLevel) { | ||
| this.level = level; | ||
| } | ||
| /** | ||
| * gets items count | ||
| */ | ||
| get length(): number { | ||
| if (this.files === undefined) { | ||
| return 0; | ||
| } | ||
| return this.files.length; | ||
| } | ||
| /** | ||
| * constructor for creating ZipArchive instance | ||
| */ | ||
| constructor() { | ||
| if (CRC32TABLE.length === 0) { | ||
| ZipArchive.initCrc32Table(); | ||
| } | ||
| this.files = []; | ||
| this.level = 'Normal'; | ||
| Save.isMicrosoftBrowser = !(!navigator.msSaveBlob); | ||
| } | ||
| /** | ||
| * add new item to archive | ||
| * @param {ZipArchiveItem} item - item to be added | ||
| * @returns {void} | ||
| */ | ||
| public addItem(item: ZipArchiveItem): void { | ||
| if (item === null || item === undefined) { | ||
| throw new Error('ArgumentException: item cannot be null or undefined'); | ||
| } | ||
| for (let i: number = 0; i < this.files.length; i++) { | ||
| let file: ZipArchiveItem = this.files[i] as ZipArchiveItem; | ||
| if (file instanceof ZipArchiveItem) { | ||
| if (file.name === item.name) { | ||
| throw new Error('item with same name already exist'); | ||
| } | ||
| } | ||
| } | ||
| this.files.push(item as ZipArchiveItem); | ||
| } | ||
| /** | ||
| * add new directory to archive | ||
| * @param directoryName directoryName to be created | ||
| * @returns {void} | ||
| */ | ||
| public addDirectory(directoryName: string): void { | ||
| if (directoryName === null || directoryName === undefined) { | ||
| throw new Error('ArgumentException: string cannot be null or undefined'); | ||
| } | ||
| if (directoryName.length === 0) { | ||
| throw new Error('ArgumentException: string cannot be empty'); | ||
| } | ||
| if (directoryName.slice(-1) !== '/') { | ||
| directoryName += '/'; | ||
| } | ||
| if (this.files.indexOf(directoryName) !== -1) { | ||
| throw new Error('item with same name already exist'); | ||
| } | ||
| this.files.push(directoryName as string); | ||
| } | ||
| /** | ||
| * gets item at specified index | ||
| * @param {number} index - item index | ||
| * @returns {ZipArchiveItem} | ||
| */ | ||
| public getItem(index: number): ZipArchiveItem { | ||
| if (index >= 0 && index < this.files.length) { | ||
| return this.files[index] as ZipArchiveItem; | ||
| } | ||
| return undefined; | ||
| } | ||
| /** | ||
| * determines whether an element is in the collection | ||
| * @param {string | ZipArchiveItem} item - item to search | ||
| * @returns {boolean} | ||
| */ | ||
| public contains(item: string | ZipArchiveItem): boolean { | ||
| return this.files.indexOf(item) !== -1 ? true : false; | ||
| } | ||
| public open(base64String: string): void { | ||
| //return promise = new Promise((resolve: Function, reject: Function) => { | ||
| let zipArchive: ZipArchive = this; | ||
| let zipByteArray: Uint8Array = Utils.encodedString(base64String); | ||
| if (zipByteArray.length == 0) | ||
| throw new DOMException("stream"); | ||
| let stream: Stream = new Stream(zipByteArray); | ||
| //let lCentralDirEndPosition = this.findValueFromEnd( arrBuffer, Constants.CentralDirectoryEndSignature, 65557 ); | ||
| let lCentralDirEndPosition: number = ZipArchive.findValueFromEnd(stream, CentralDirectoryEndSignature, 65557); | ||
| if (lCentralDirEndPosition < 0) | ||
| throw new DOMException("Can't locate end of central directory record. Possible wrong file format or archive is corrupt."); | ||
| // Step2. Locate central directory and iterate through all items | ||
| stream.position = lCentralDirEndPosition + CentralDirSizeOffset; | ||
| let iCentralDirSize: number = ZipArchive.ReadInt32(stream); | ||
| let lCentralDirPosition: number = lCentralDirEndPosition - iCentralDirSize; | ||
| // verify that this is really central directory | ||
| stream.position = lCentralDirPosition; | ||
| this.readCentralDirectoryDataAndExtractItems(stream); | ||
| //}); | ||
| // let zipArchive: ZipArchive = this; | ||
| //let promise: Promise<ZipArchive>; | ||
| // return promise = new Promise((resolve: Function, reject: Function) => { | ||
| // let reader: FileReader = new FileReader(); | ||
| // reader.onload = (e: Event) => { | ||
| // let data: Uint8Array = new Uint8Array((e.target as any).result); | ||
| // let zipReader: ZipReader = new ZipReader(data); | ||
| // zipReader.readEntries().then((entries: ZipEntry[]) => { | ||
| // for (let i: number = 0; i < entries.length; i++) { | ||
| // let entry: ZipEntry = entries[i]; | ||
| // let item: ZipArchiveItem = new ZipArchiveItem(zipArchive, entry.fileName); | ||
| // item.data = entry.data; | ||
| // item.compressionMethod = entry.compressionMethod; | ||
| // item.crc = entry.crc; | ||
| // item.lastModified = entry.lastModified; | ||
| // item.lastModifiedDate = entry.lastModifiedDate; | ||
| // item.size = entry.size; | ||
| // item.uncompressedSize = entry.uncompressedSize; | ||
| // zipArchive.addItem(item); | ||
| // } | ||
| // resolve(zipArchive); | ||
| // }); | ||
| // }; | ||
| // reader.readAsArrayBuffer(fileName); | ||
| // }); | ||
| } | ||
| /// <summary> | ||
| /// Read central directory record from the stream. | ||
| /// </summary> | ||
| /// <param name="stream">Stream to read from.</param> | ||
| public readCentralDirectoryDataAndExtractItems(stream: Stream): void { | ||
| if (stream == null) | ||
| throw new DOMException("stream"); | ||
| let itemHelper: ZipArchiveItemHelper ; | ||
| while (ZipArchive.ReadInt32(stream) == CentralHeaderSignature) { | ||
| itemHelper = new ZipArchiveItemHelper(); | ||
| itemHelper.readCentralDirectoryData(stream); | ||
| itemHelper | ||
| // let item: ZipArchiveItem = new ZipArchiveItem(this); | ||
| // item.ReadCentralDirectoryData(stream); | ||
| // m_arrItems.Add(item); | ||
| } | ||
| itemHelper.readData(stream, itemHelper.checkCrc); | ||
| itemHelper.decompressData(); | ||
| this.files.push(new ZipArchiveItem(itemHelper.unCompressedStream.buffer, itemHelper.name)); | ||
| } | ||
| /** | ||
| * save archive with specified file name | ||
| * @param {string} fileName save archive with specified file name | ||
| * @returns {Promise<ZipArchive>} | ||
| */ | ||
| public save(fileName: string): Promise<ZipArchive> { | ||
| if (fileName === null || fileName === undefined || fileName.length === 0) { | ||
| throw new Error('ArgumentException: fileName cannot be null or undefined'); | ||
| } | ||
| if (this.files.length === 0) { | ||
| throw new Error('InvalidOperation'); | ||
| } | ||
| let zipArchive: ZipArchive = this; | ||
| let promise: Promise<ZipArchive>; | ||
| return promise = new Promise((resolve: Function, reject: Function) => { | ||
| zipArchive.saveInternal(fileName, false).then(() => { | ||
| resolve(zipArchive); | ||
| }); | ||
| }); | ||
| } | ||
| /** | ||
| * Save archive as blob | ||
| * @return {Promise<Blob>} | ||
| */ | ||
| public saveAsBlob(): Promise<Blob> { | ||
| let zipArchive: ZipArchive = this; | ||
| let promise: Promise<Blob>; | ||
| return promise = new Promise((resolve: Function, reject: Function) => { | ||
| zipArchive.saveInternal('', true).then((blob: Blob) => { | ||
| resolve(blob); | ||
| }); | ||
| }); | ||
| } | ||
| private saveInternal(fileName: string, skipFileSave: boolean): Promise<Blob> { | ||
| let zipArchive: ZipArchive = this; | ||
| let promise: Promise<Blob>; | ||
| return promise = new Promise((resolve: Function, reject: Function) => { | ||
| let zipData: ZippedObject[] = []; | ||
| let dirLength: number = 0; | ||
| for (let i: number = 0; i < zipArchive.files.length; i++) { | ||
| let compressedObject: Promise<CompressedData> = this.getCompressedData(this.files[i]); | ||
| compressedObject.then((data: CompressedData) => { | ||
| dirLength = zipArchive.constructZippedObject(zipData, data, dirLength, data.isDirectory); | ||
| if (zipData.length === zipArchive.files.length) { | ||
| let blob: Blob = zipArchive.writeZippedContent(fileName, zipData, dirLength, skipFileSave); | ||
| resolve(blob); | ||
| } | ||
| }); | ||
| } | ||
| }); | ||
| } | ||
| /** | ||
| * release allocated un-managed resource | ||
| * @returns {void} | ||
| */ | ||
| public destroy(): void { | ||
| if (this.files !== undefined && this.files.length > 0) { | ||
| for (let i: number = 0; i < this.files.length; i++) { | ||
| let file: ZipArchiveItem | string = this.files[i]; | ||
| if (file instanceof ZipArchiveItem) { | ||
| (file as ZipArchiveItem).destroy(); | ||
| } | ||
| file = undefined; | ||
| } | ||
| this.files = []; | ||
| } | ||
| this.files = undefined; | ||
| this.level = undefined; | ||
| } | ||
| private getCompressedData(item: ZipArchiveItem | string): Promise<CompressedData> { | ||
| let zipArchive: ZipArchive = this; | ||
| let promise: Promise<CompressedData> = new Promise((resolve: Function, reject: Function) => { | ||
| if (item instanceof ZipArchiveItem) { | ||
| let reader: FileReader = new FileReader(); | ||
| reader.onload = () => { | ||
| let input: Uint8Array = new Uint8Array(reader.result as ArrayBuffer); | ||
| let data: CompressedData = { | ||
| fileName: item.name, crc32Value: 0, compressedData: [], | ||
| compressedSize: undefined, uncompressedDataSize: input.length, compressionType: undefined, | ||
| isDirectory: false | ||
| }; | ||
| if (zipArchive.level === 'Normal') { | ||
| zipArchive.compressData(input, data, CRC32TABLE); | ||
| let length: number = 0; | ||
| for (let i: number = 0; i < data.compressedData.length; i++) { | ||
| length += data.compressedData[i].length; | ||
| } | ||
| data.compressedSize = length; | ||
| data.compressionType = '\x08\x00'; //Deflated = 8 | ||
| } else { | ||
| data.compressedSize = input.length; | ||
| data.crc32Value = zipArchive.calculateCrc32Value(0, input, CRC32TABLE); | ||
| data.compressionType = '\x00\x00'; // Stored = 0 | ||
| (data.compressedData as Uint8Array[]).push(input); | ||
| } | ||
| resolve(data); | ||
| }; | ||
| reader.readAsArrayBuffer(item.data as Blob); | ||
| } else { | ||
| let data: CompressedData = { | ||
| fileName: item as string, crc32Value: 0, compressedData: '', compressedSize: 0, uncompressedDataSize: 0, | ||
| compressionType: '\x00\x00', isDirectory: true | ||
| }; | ||
| resolve(data); | ||
| } | ||
| }); | ||
| return promise; | ||
| } | ||
| private compressData(input: Uint8Array, data: CompressedData, crc32Table: number[]): void { | ||
| let compressor: CompressedStreamWriter = new CompressedStreamWriter(true); | ||
| let currentIndex: number = 0; | ||
| let nextIndex: number = 0; | ||
| do { | ||
| if (currentIndex >= input.length) { | ||
| compressor.close(); | ||
| break; | ||
| } | ||
| nextIndex = Math.min(input.length, currentIndex + 16384); | ||
| let subArray: Uint8Array = input.subarray(currentIndex, nextIndex); | ||
| data.crc32Value = this.calculateCrc32Value(data.crc32Value, subArray, crc32Table); | ||
| compressor.write(subArray, 0, nextIndex - currentIndex); | ||
| currentIndex = nextIndex; | ||
| } while (currentIndex <= input.length); | ||
| data.compressedData = compressor.compressedData; | ||
| compressor.destroy(); | ||
| } | ||
| private constructZippedObject(zipParts: ZippedObject[], data: CompressedData, dirLength: number, isDirectory: boolean): number { | ||
| let extFileAttr: number = 0; | ||
| let date: Date = new Date(); | ||
| if (isDirectory) { | ||
| extFileAttr = extFileAttr | 0x00010; // directory flag | ||
| } | ||
| extFileAttr = extFileAttr | (0 & 0x3F); | ||
| let header: string = this.writeHeader(data, date); | ||
| let localHeader: string = 'PK\x03\x04' + header + data.fileName; | ||
| let centralDir: string = this.writeCentralDirectory(data, header, dirLength, extFileAttr); | ||
| zipParts.push({ localHeader: localHeader, centralDir: centralDir, compressedData: data }); | ||
| return dirLength + localHeader.length + data.compressedSize; | ||
| } | ||
| private writeHeader(data: CompressedData, date: Date): string { | ||
| let zipHeader: string = ''; | ||
| zipHeader += '\x0A\x00' + '\x00\x00'; // version needed to extract & general purpose bit flag | ||
| zipHeader += data.compressionType; // compression method Deflate=8,Stored=0 | ||
| zipHeader += this.getBytes(this.getModifiedTime(date), 2); // last modified Time | ||
| zipHeader += this.getBytes(this.getModifiedDate(date), 2); // last modified date | ||
| zipHeader += this.getBytes(data.crc32Value, 4); // crc-32 value | ||
| zipHeader += this.getBytes(data.compressedSize, 4); // compressed file size | ||
| zipHeader += this.getBytes(data.uncompressedDataSize, 4); // uncompressed file size | ||
| zipHeader += this.getBytes(data.fileName.length, 2); // file name length | ||
| zipHeader += this.getBytes(0, 2); // extra field length | ||
| return zipHeader; | ||
| } | ||
| private writeZippedContent(fileName: string, zipData: ZippedObject[], localDirLen: number, skipFileSave: boolean): Blob { | ||
| let cenDirLen: number = 0; | ||
| let buffer: ArrayBuffer[] = []; | ||
| for (let i: number = 0; i < zipData.length; i++) { | ||
| let item: ZippedObject = zipData[i]; | ||
| cenDirLen += item.centralDir.length; | ||
| buffer.push(this.getArrayBuffer(item.localHeader)); | ||
| while (item.compressedData.compressedData.length) { | ||
| buffer.push((item.compressedData.compressedData as Uint8Array[]).shift().buffer); | ||
| } | ||
| } | ||
| for (let i: number = 0; i < zipData.length; i++) { | ||
| buffer.push(this.getArrayBuffer(zipData[i].centralDir)); | ||
| } | ||
| buffer.push(this.getArrayBuffer(this.writeFooter(zipData, cenDirLen, localDirLen))); | ||
| let blob: Blob = new Blob(buffer, { type: 'application/zip' }); | ||
| if (!skipFileSave) { | ||
| Save.save(fileName, blob); | ||
| } | ||
| return blob; | ||
| } | ||
| private writeCentralDirectory(data: CompressedData, localHeader: string, offset: number, externalFileAttribute: number): string { | ||
| let directoryHeader: string = 'PK\x01\x02' + | ||
| this.getBytes(0x0014, 2) + localHeader + // inherit from file header | ||
| this.getBytes(0, 2) + // comment length | ||
| '\x00\x00' + '\x00\x00' + // internal file attributes | ||
| this.getBytes(externalFileAttribute, 4) + // external file attributes | ||
| this.getBytes(offset, 4) + // local fileHeader relative offset | ||
| data.fileName; | ||
| return directoryHeader; | ||
| } | ||
| private writeFooter(zipData: ZippedObject[], centralLength: number, localLength: number): string { | ||
| let dirEnd: string = 'PK\x05\x06' + '\x00\x00' + '\x00\x00' + | ||
| this.getBytes(zipData.length, 2) + this.getBytes(zipData.length, 2) + | ||
| this.getBytes(centralLength, 4) + this.getBytes(localLength, 4) + | ||
| this.getBytes(0, 2); | ||
| return dirEnd; | ||
| } | ||
| private getArrayBuffer(input: string): ArrayBuffer { | ||
| let a: Uint8Array = new Uint8Array(input.length); | ||
| for (let j: number = 0; j < input.length; ++j) { | ||
| a[j] = input.charCodeAt(j) & 0xFF; | ||
| } | ||
| return a.buffer; | ||
| } | ||
| private getBytes(value: number, offset: number): string { | ||
| let bytes: string = ''; | ||
| for (let i: number = 0; i < offset; i++) { | ||
| bytes += String.fromCharCode(value & 0xff); | ||
| value = value >>> 8; | ||
| } | ||
| return bytes; | ||
| } | ||
| private getModifiedTime(date: Date): number { | ||
| let modTime: number = date.getHours(); | ||
| modTime = modTime << 6; | ||
| modTime = modTime | date.getMinutes(); | ||
| modTime = modTime << 5; | ||
| return modTime = modTime | date.getSeconds() / 2; | ||
| } | ||
| private getModifiedDate(date: Date): number { | ||
| let modiDate: number = date.getFullYear() - 1980; | ||
| modiDate = modiDate << 4; | ||
| modiDate = modiDate | (date.getMonth() + 1); | ||
| modiDate = modiDate << 5; | ||
| return modiDate = modiDate | date.getDate(); | ||
| } | ||
| private calculateCrc32Value(crc32Value: number, input: Uint8Array, crc32Table: number[]): number { | ||
| crc32Value ^= -1; | ||
| for (let i: number = 0; i < input.length; i++) { | ||
| crc32Value = (crc32Value >>> 8) ^ crc32Table[(crc32Value ^ input[i]) & 0xFF]; | ||
| } | ||
| return (crc32Value ^ (-1)); | ||
| } | ||
| /** | ||
| * construct cyclic redundancy code table | ||
| * @private | ||
| */ | ||
| public static initCrc32Table(): void { | ||
| let i: number; | ||
| for (let j: number = 0; j < 256; j++) { | ||
| i = j; | ||
| for (let k: number = 0; k < 8; k++) { | ||
| i = ((i & 1) ? (0xEDB88320 ^ (i >>> 1)) : (i >>> 1)); | ||
| } | ||
| CRC32TABLE[j] = i; | ||
| } | ||
| } | ||
| public static findValueFromEnd(stream: Stream, value: number, maxCount: number) { | ||
| if (stream == null) | ||
| throw new DOMException("stream"); | ||
| // if( !stream.CanSeek || !stream.CanRead ) | ||
| // throw new ArgumentOutOfRangeException( "We need to have seekable and readable stream." ); | ||
| // read last 4 bytes and compare with required value | ||
| let lStreamSize: number = stream.inputStream.buffer.byteLength; | ||
| if (lStreamSize < 4) | ||
| return -1; | ||
| let arrBuffer: Uint8Array = new Uint8Array(4); | ||
| let lLastPos: number = Math.max(0, lStreamSize - maxCount); | ||
| let lCurrentPosition: number = lStreamSize - 1 - INT_SIZE; | ||
| stream.position = lCurrentPosition; | ||
| stream.read(arrBuffer, 0, INT_SIZE); | ||
| let uiCurValue: number = arrBuffer[0]; | ||
| let bFound: boolean = (uiCurValue == value); | ||
| if (!bFound) { | ||
| while (lCurrentPosition > lLastPos) { | ||
| // remove unnecessary byte and replace it with new value. | ||
| uiCurValue <<= 8; | ||
| lCurrentPosition--; | ||
| stream.position = lCurrentPosition; | ||
| uiCurValue += stream.readByte(); | ||
| if (uiCurValue == value) { | ||
| bFound = true; | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| return bFound ? lCurrentPosition : -1; | ||
| } | ||
| /// <summary> | ||
| /// Extracts Int32 value from the stream. | ||
| /// </summary> | ||
| /// <param name="stream">Stream to read data from.</param> | ||
| /// <returns>Extracted value.</returns> | ||
| public static ReadInt32(stream: Stream): number { | ||
| let buffer: Uint8Array = new Uint8Array(INT_SIZE); | ||
| if (stream.read(buffer, 0, INT_SIZE) != INT_SIZE) { | ||
| throw new DOMException("Unable to read value at the specified position - end of stream was reached."); | ||
| } | ||
| return Utils.bitConverterToInt32(buffer, 0); | ||
| } | ||
| /// <summary> | ||
| /// Extracts Int16 value from the stream. | ||
| /// </summary> | ||
| /// <param name="stream">Stream to read data from.</param> | ||
| /// <returns>Extracted value.</returns> | ||
| public static ReadInt16(stream: Stream): number { | ||
| let buffer: Uint8Array = new Uint8Array(SHORT_SIZE) | ||
| if (stream.read(buffer, 0, SHORT_SIZE) != SHORT_SIZE) { | ||
| throw new DOMException("Unable to read value at the specified position - end of stream was reached."); | ||
| } | ||
| return Utils.bitConverterToInt16(buffer, 0); | ||
| } | ||
| /// <summary> | ||
| /// Extracts unsigned Int16 value from the stream. | ||
| /// </summary> | ||
| /// <param name="stream">Stream to read data from.</param> | ||
| /// <returns>Extracted value.</returns> | ||
| public static ReadUInt16(stream: Stream): number { | ||
| { | ||
| let buffer: Uint8Array = new Uint8Array(SHORT_SIZE) | ||
| if (stream.read(buffer, 0, SHORT_SIZE) != SHORT_SIZE) { | ||
| throw new DOMException("Unable to read value at the specified position - end of stream was reached."); | ||
| } | ||
| return Utils.bitConverterToInt16(buffer, 0); | ||
| } | ||
| } | ||
| } | ||
| export class ZipArchiveItemHelper { | ||
| public compressedStream : Uint8Array; | ||
| public name: string; | ||
| public unCompressedStream : Uint8Array; | ||
| /// <summary> | ||
| /// Zip header signature. | ||
| /// </summary> | ||
| public headerSignature: number = 0x04034b50; | ||
| /// <summary> | ||
| /// General purpose bit flag. | ||
| /// </summary> | ||
| private options: number; | ||
| /// <summary> | ||
| /// Compression method. | ||
| /// </summary> | ||
| private compressionMethod: number; | ||
| /// <summary> | ||
| /// Indicates whether we should check Crc value when reading item's data. Check | ||
| /// is performed when user gets access to decompressed data for the first time. | ||
| /// </summary> | ||
| public checkCrc: boolean = true; | ||
| /// <summary> | ||
| /// Crc. | ||
| /// </summary> | ||
| private crc32: number = 0; | ||
| /// <summary> | ||
| /// Compressed data size. | ||
| /// </summary> | ||
| private compressedSize: number; | ||
| /// <summary> | ||
| /// Original (not compressed) data size. | ||
| /// </summary> | ||
| private originalSize: number; | ||
| /// <summary> | ||
| /// Offset to the local header. | ||
| /// </summary> | ||
| private localHeaderOffset: number; | ||
| /// <summary> | ||
| /// Item's external attributes. | ||
| /// </summary> | ||
| private externalAttributes: number; | ||
| /// <summary> | ||
| /// Read data from the stream based on the central directory. | ||
| /// </summary> | ||
| /// <param name="stream">Stream to read data from, stream.Position must point at just after correct file header.</param> | ||
| public readCentralDirectoryData(stream: Stream): void { | ||
| // on the current moment we ignore "version made by" and "version needed to extract" fields. | ||
| stream.position += 4; | ||
| this.options = ZipArchive.ReadInt16(stream); | ||
| this.compressionMethod = ZipArchive.ReadInt16(stream); | ||
| this.checkCrc = (this.compressionMethod != 99); //COmpression.Defalte != SecurityConstants.AES | ||
| //m_bCompressed = true; | ||
| // on the current moment we ignore "last mod file time" and "last mod file date" fields. | ||
| let lastModified: number = ZipArchive.ReadInt32(stream); | ||
| //LastModified = ConvertToDateTime(lastModified); | ||
| this.crc32 = Utils.bitConverterToUInt32(ZipArchive.ReadInt32(stream)); | ||
| this.compressedSize = ZipArchive.ReadInt32(stream); | ||
| this.originalSize = ZipArchive.ReadInt32(stream); | ||
| let iFileNameLength = ZipArchive.ReadInt16(stream); | ||
| let iExtraFieldLenth = ZipArchive.ReadInt16(stream); | ||
| let iCommentLength = ZipArchive.ReadInt16(stream); | ||
| // on the current moment we ignore and "disk number start" (2 bytes), | ||
| // "internal file attributes" (2 bytes). | ||
| stream.position += 4; | ||
| this.externalAttributes = ZipArchive.ReadInt32(stream); | ||
| this.localHeaderOffset = ZipArchive.ReadInt32(stream); | ||
| let arrBuffer: Uint8Array = new Uint8Array(iFileNameLength); | ||
| stream.read(arrBuffer, 0, iFileNameLength); | ||
| let m_strItemName = Utils.byteToString(arrBuffer); | ||
| m_strItemName = m_strItemName.replace("\\", "/"); | ||
| this.name = m_strItemName; | ||
| stream.position += iExtraFieldLenth + iCommentLength; | ||
| if (this.options != 0) this.options = 0; | ||
| } | ||
| /// <summary> | ||
| /// Reads zipped data from the stream. | ||
| /// </summary> | ||
| /// <param name="stream">Stream to read data from.</param> | ||
| /// <param name="checkCrc">Indicates whether we should check crc value after data decompression.</param> | ||
| public readData(stream: Stream, checkCrc: boolean): void { | ||
| if (stream.length == 0) | ||
| throw new DOMException("stream"); | ||
| stream.position = this.localHeaderOffset; | ||
| this.checkCrc = checkCrc; | ||
| this.readLocalHeader(stream); | ||
| this.readCompressedData( stream ); | ||
| } | ||
| public decompressData(): void { | ||
| if(this.compressionMethod == 8){ | ||
| if( this.originalSize > 0 ) | ||
| { | ||
| this.decompressDataOld(); | ||
| } | ||
| } | ||
| } | ||
| private decompressDataOld(): void | ||
| { | ||
| let reader: CompressedStreamReader = new CompressedStreamReader( this.compressedStream, true ); | ||
| let decompressedData: Stream; | ||
| if(this.originalSize>0) | ||
| decompressedData = new Stream(new Uint8Array(this.originalSize)); | ||
| let arrBuffer:Uint8Array = new Uint8Array(BufferSize ); | ||
| let iReadBytes: number; | ||
| let past:Uint8Array = new Uint8Array(0); | ||
| while ((iReadBytes = reader.read(arrBuffer, 0, BufferSize)) > 0) { | ||
| // past = new Uint8Array(decompressedData.length); | ||
| // let currentBlock: Uint8Array = arrBuffer.subarray(0, iReadBytes); | ||
| decompressedData.write(arrBuffer.subarray(0, iReadBytes), 0, iReadBytes); | ||
| } | ||
| this.unCompressedStream = decompressedData.toByteArray(); | ||
| // this.originalSize = decompressedData.Length; | ||
| // m_bControlStream = true; | ||
| // m_streamData = decompressedData; | ||
| // decompressedData.SetLength( m_lOriginalSize ); | ||
| // decompressedData.Capacity = ( int )m_lOriginalSize; | ||
| if (this.checkCrc) { | ||
| //TODO: fix this | ||
| //CheckCrc(decompressedData.ToArray()); | ||
| } | ||
| //m_streamData.Position = 0; | ||
| } | ||
| /// <summary> | ||
| /// Extracts local header from the stream. | ||
| /// </summary> | ||
| /// <param name="stream">Stream to read data from.</param> | ||
| private readLocalHeader(stream: Stream) { | ||
| if (stream.length == 0) | ||
| throw new DOMException("stream"); | ||
| if (ZipArchive.ReadInt32(stream) != this.headerSignature) | ||
| throw new DOMException("Can't find local header signature - wrong file format or file is corrupt."); | ||
| // TODO: it is good to verify data read from the central directory record, | ||
| // but on the current moment we simply skip it. | ||
| stream.position += 22; | ||
| let iNameLength = ZipArchive.ReadInt16(stream); | ||
| let iExtraLength = ZipArchive.ReadUInt16(stream); | ||
| if (this.compressionMethod == 99) //SecurityConstants.AES | ||
| { | ||
| // stream.Position += iNameLength + 8; | ||
| // m_archive.EncryptionAlgorithm = (EncryptionAlgorithm)stream.ReadByte(); | ||
| // m_actualCompression = new byte[2]; | ||
| // stream.Read(m_actualCompression, 0, 2); | ||
| } | ||
| else if (iExtraLength > 2) { | ||
| stream.position += iNameLength; | ||
| let headerVal = ZipArchive.ReadInt16(stream); | ||
| if (headerVal == 0x0017) //PKZipEncryptionHeader | ||
| throw new DOMException("UnSupported"); | ||
| else | ||
| stream.position += iExtraLength - 2; | ||
| } | ||
| else | ||
| stream.position += iNameLength + iExtraLength; | ||
| } | ||
| /// <summary> | ||
| /// Extracts compressed data from the stream. | ||
| /// </summary> | ||
| /// <param name="stream">Stream to read data from.</param> | ||
| private readCompressedData(stream: Stream ): void | ||
| { | ||
| let dataStream: Stream; | ||
| if( this.compressedSize > 0 ) | ||
| { | ||
| let iBytesLeft: number = this.compressedSize; | ||
| dataStream = new Stream(new Uint8Array(iBytesLeft)); | ||
| let arrBuffer: Uint8Array = new Uint8Array(BufferSize); | ||
| while( iBytesLeft > 0 ) | ||
| { | ||
| let iBytesToRead: number = Math.min( iBytesLeft, BufferSize ); | ||
| if( stream.read( arrBuffer, 0, iBytesToRead ) != iBytesToRead ) | ||
| throw new DOMException( "End of file reached - wrong file format or file is corrupt." ); | ||
| dataStream.write(arrBuffer.subarray(0, iBytesToRead), 0, iBytesToRead); | ||
| iBytesLeft -= iBytesToRead; | ||
| } | ||
| // if(m_archive.Password != null) | ||
| // { | ||
| // byte[] dataBuffer = new byte[dataStream.Length]; | ||
| // dataBuffer = dataStream.ToArray(); | ||
| // dataStream=new MemoryStream( Decrypt(dataBuffer)); | ||
| // } | ||
| this.compressedStream = new Uint8Array(dataStream.inputStream); | ||
| // m_bControlStream = true; | ||
| } | ||
| else if(this.compressedSize<0) //If compression size is negative, then read until the next header signature reached. | ||
| { | ||
| // MemoryStream dataStream = new MemoryStream(); | ||
| // int bt = 0; | ||
| // bool proceed=true; | ||
| // while (proceed) | ||
| // { | ||
| // if ((bt = stream.ReadByte()) == Constants.HeaderSignatureStartByteValue) | ||
| // { | ||
| // stream.Position -= 1; | ||
| // int headerSignature = ZipArchive.ReadInt32(stream); | ||
| // if (headerSignature==Constants.CentralHeaderSignature || headerSignature==Constants.CentralHeaderSignature) | ||
| // { | ||
| // proceed = false; | ||
| // } | ||
| // stream.Position -= 3; | ||
| // } | ||
| // if (proceed) | ||
| // dataStream.WriteByte((byte)bt); | ||
| // } | ||
| // m_streamData = dataStream; | ||
| // m_lCompressedSize = m_streamData.Length; | ||
| // m_bControlStream = true; | ||
| } | ||
| else if(this.compressedSize == 0) | ||
| { | ||
| // m_streamData = new MemoryStream(); | ||
| } | ||
| } | ||
| } | ||
| /** | ||
| * Class represent unique ZipArchive item | ||
| * ```typescript | ||
| * let archiveItem = new ZipArchiveItem(archive, 'directoryName\fileName.txt'); | ||
| * ``` | ||
| */ | ||
| export class ZipArchiveItem { | ||
| public data: Blob | ArrayBuffer; | ||
| private decompressedStream: Blob | ArrayBuffer; | ||
| private fileName: string; | ||
| public get dataStream(): Blob | ArrayBuffer { | ||
| return this.decompressedStream; | ||
| } | ||
| /** | ||
| * Get the name of archive item | ||
| * @returns string | ||
| */ | ||
| get name(): string { | ||
| return this.fileName; | ||
| } | ||
| /** | ||
| * Set the name of archive item | ||
| * @param {string} value | ||
| */ | ||
| set name(value: string) { | ||
| this.fileName = value; | ||
| } | ||
| /** | ||
| * constructor for creating {ZipArchiveItem} instance | ||
| * @param {Blob|ArrayBuffer} data file data | ||
| * @param {itemName} itemName absolute file path | ||
| */ | ||
| constructor(data: Blob | ArrayBuffer, itemName: string) { | ||
| if (data === null || data === undefined) { | ||
| throw new Error('ArgumentException: data cannot be null or undefined'); | ||
| } | ||
| if (itemName === null || itemName === undefined) { | ||
| throw new Error('ArgumentException: string cannot be null or undefined'); | ||
| } | ||
| if (itemName.length === 0) { | ||
| throw new Error('string cannot be empty'); | ||
| } | ||
| this.data = data; | ||
| this.name = itemName; | ||
| } | ||
| /** | ||
| * release allocated un-managed resource | ||
| * @returns {void} | ||
| */ | ||
| public destroy(): void { | ||
| this.fileName = undefined; | ||
| this.data = undefined; | ||
| } | ||
| } | ||
| export interface CompressedData { | ||
| fileName: string; | ||
| compressedData: Uint8Array[] | string; | ||
| uncompressedDataSize: number; | ||
| compressedSize: number; | ||
| crc32Value: number; | ||
| compressionType: string; | ||
| isDirectory: boolean; | ||
| } | ||
| export interface ZippedObject { | ||
| localHeader: string; | ||
| centralDir: string; | ||
| compressedData: CompressedData; | ||
| } | ||
| /** | ||
| * Compression level. | ||
| */ | ||
| export type CompressionLevel = | ||
| /* Pack without compression */ | ||
| 'NoCompression' | | ||
| /* Use normal compression, middle between speed and size*/ | ||
| 'Normal'; | ||
| /* eslint-enable */ |
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
27
-18.18%1262506
-9.73%30
-31.82%9318
-26.83%