Latest Threat Research:SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains.Details
Socket
Book a DemoInstallSign in
Socket

@syncfusion/ej2-compression

Package Overview
Dependencies
Maintainers
3
Versions
116
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@syncfusion/ej2-compression - npm Package Compare versions

Comparing version
31.2.2
to
31.2.12
+2
-2
dist/ej2-compression.min.js
/*!
* 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.

{
"_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;
}
/* 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 */