var LZMA = LZMA || {}; // browserify support if ( typeof module === 'object' ) { module.exports = LZMA; } LZMA.OutWindow = function() { this._windowSize = 0; }; LZMA.OutWindow.prototype.create = function(windowSize) { if ( (!this._buffer) || (this._windowSize !== windowSize) ) { this._buffer = []; } this._windowSize = windowSize; this._pos = 0; this._streamPos = 0; }; LZMA.OutWindow.prototype.flush = function() { var size = this._pos - this._streamPos; if (size !== 0) { while (size --) { this._stream.writeByte(this._buffer[this._streamPos ++]); } if (this._pos >= this._windowSize) { this._pos = 0; } this._streamPos = this._pos; } }; LZMA.OutWindow.prototype.releaseStream = function() { this.flush(); this._stream = null; }; LZMA.OutWindow.prototype.setStream = function(stream) { this.releaseStream(); this._stream = stream; }; LZMA.OutWindow.prototype.init = function(solid) { if (!solid) { this._streamPos = 0; this._pos = 0; } }; LZMA.OutWindow.prototype.copyBlock = function(distance, len) { var pos = this._pos - distance - 1; if (pos < 0) { pos += this._windowSize; } while (len --) { if (pos >= this._windowSize) { pos = 0; } this._buffer[this._pos ++] = this._buffer[pos ++]; if (this._pos >= this._windowSize) { this.flush(); } } }; LZMA.OutWindow.prototype.putByte = function(b) { this._buffer[this._pos ++] = b; if (this._pos >= this._windowSize) { this.flush(); } }; LZMA.OutWindow.prototype.getByte = function(distance) { var pos = this._pos - distance - 1; if (pos < 0) { pos += this._windowSize; } return this._buffer[pos]; }; LZMA.RangeDecoder = function() { }; LZMA.RangeDecoder.prototype.setStream = function(stream) { this._stream = stream; }; LZMA.RangeDecoder.prototype.releaseStream = function() { this._stream = null; }; LZMA.RangeDecoder.prototype.init = function() { var i = 5; this._code = 0; this._range = -1; while (i --) { this._code = (this._code << 8) | this._stream.readByte(); } }; LZMA.RangeDecoder.prototype.decodeDirectBits = function(numTotalBits) { var result = 0, i = numTotalBits, t; while (i --) { this._range >>>= 1; t = (this._code - this._range) >>> 31; this._code -= this._range & (t - 1); result = (result << 1) | (1 - t); if ( (this._range & 0xff000000) === 0) { this._code = (this._code << 8) | this._stream.readByte(); this._range <<= 8; } } return result; }; LZMA.RangeDecoder.prototype.decodeBit = function(probs, index) { var prob = probs[index], newBound = (this._range >>> 11) * prob; if ( (this._code ^ 0x80000000) < (newBound ^ 0x80000000) ) { this._range = newBound; probs[index] += (2048 - prob) >>> 5; if ( (this._range & 0xff000000) === 0) { this._code = (this._code << 8) | this._stream.readByte(); this._range <<= 8; } return 0; } this._range -= newBound; this._code -= newBound; probs[index] -= prob >>> 5; if ( (this._range & 0xff000000) === 0) { this._code = (this._code << 8) | this._stream.readByte(); this._range <<= 8; } return 1; }; LZMA.initBitModels = function(probs, len) { while (len --) { probs[len] = 1024; } }; LZMA.BitTreeDecoder = function(numBitLevels) { this._models = []; this._numBitLevels = numBitLevels; }; LZMA.BitTreeDecoder.prototype.init = function() { LZMA.initBitModels(this._models, 1 << this._numBitLevels); }; LZMA.BitTreeDecoder.prototype.decode = function(rangeDecoder) { var m = 1, i = this._numBitLevels; while (i --) { m = (m << 1) | rangeDecoder.decodeBit(this._models, m); } return m - (1 << this._numBitLevels); }; LZMA.BitTreeDecoder.prototype.reverseDecode = function(rangeDecoder) { var m = 1, symbol = 0, i = 0, bit; for (; i < this._numBitLevels; ++ i) { bit = rangeDecoder.decodeBit(this._models, m); m = (m << 1) | bit; symbol |= bit << i; } return symbol; }; LZMA.reverseDecode2 = function(models, startIndex, rangeDecoder, numBitLevels) { var m = 1, symbol = 0, i = 0, bit; for (; i < numBitLevels; ++ i) { bit = rangeDecoder.decodeBit(models, startIndex + m); m = (m << 1) | bit; symbol |= bit << i; } return symbol; }; LZMA.LenDecoder = function() { this._choice = []; this._lowCoder = []; this._midCoder = []; this._highCoder = new LZMA.BitTreeDecoder(8); this._numPosStates = 0; }; LZMA.LenDecoder.prototype.create = function(numPosStates) { for (; this._numPosStates < numPosStates; ++ this._numPosStates) { this._lowCoder[this._numPosStates] = new LZMA.BitTreeDecoder(3); this._midCoder[this._numPosStates] = new LZMA.BitTreeDecoder(3); } }; LZMA.LenDecoder.prototype.init = function() { var i = this._numPosStates; LZMA.initBitModels(this._choice, 2); while (i --) { this._lowCoder[i].init(); this._midCoder[i].init(); } this._highCoder.init(); }; LZMA.LenDecoder.prototype.decode = function(rangeDecoder, posState) { if (rangeDecoder.decodeBit(this._choice, 0) === 0) { return this._lowCoder[posState].decode(rangeDecoder); } if (rangeDecoder.decodeBit(this._choice, 1) === 0) { return 8 + this._midCoder[posState].decode(rangeDecoder); } return 16 + this._highCoder.decode(rangeDecoder); }; LZMA.Decoder2 = function() { this._decoders = []; }; LZMA.Decoder2.prototype.init = function() { LZMA.initBitModels(this._decoders, 0x300); }; LZMA.Decoder2.prototype.decodeNormal = function(rangeDecoder) { var symbol = 1; do { symbol = (symbol << 1) | rangeDecoder.decodeBit(this._decoders, symbol); }while (symbol < 0x100); return symbol & 0xff; }; LZMA.Decoder2.prototype.decodeWithMatchByte = function(rangeDecoder, matchByte) { var symbol = 1, matchBit, bit; do { matchBit = (matchByte >> 7) & 1; matchByte <<= 1; bit = rangeDecoder.decodeBit(this._decoders, ( (1 + matchBit) << 8) + symbol); symbol = (symbol << 1) | bit; if (matchBit !== bit) { while (symbol < 0x100) { symbol = (symbol << 1) | rangeDecoder.decodeBit(this._decoders, symbol); } break; } }while (symbol < 0x100); return symbol & 0xff; }; LZMA.LiteralDecoder = function() { }; LZMA.LiteralDecoder.prototype.create = function(numPosBits, numPrevBits) { var i; if (this._coders && (this._numPrevBits === numPrevBits) && (this._numPosBits === numPosBits) ) { return; } this._numPosBits = numPosBits; this._posMask = (1 << numPosBits) - 1; this._numPrevBits = numPrevBits; this._coders = []; i = 1 << (this._numPrevBits + this._numPosBits); while (i --) { this._coders[i] = new LZMA.Decoder2(); } }; LZMA.LiteralDecoder.prototype.init = function() { var i = 1 << (this._numPrevBits + this._numPosBits); while (i --) { this._coders[i].init(); } }; LZMA.LiteralDecoder.prototype.getDecoder = function(pos, prevByte) { return this._coders[( (pos & this._posMask) << this._numPrevBits) + ( (prevByte & 0xff) >>> (8 - this._numPrevBits) )]; }; LZMA.Decoder = function() { this._outWindow = new LZMA.OutWindow(); this._rangeDecoder = new LZMA.RangeDecoder(); this._isMatchDecoders = []; this._isRepDecoders = []; this._isRepG0Decoders = []; this._isRepG1Decoders = []; this._isRepG2Decoders = []; this._isRep0LongDecoders = []; this._posSlotDecoder = []; this._posDecoders = []; this._posAlignDecoder = new LZMA.BitTreeDecoder(4); this._lenDecoder = new LZMA.LenDecoder(); this._repLenDecoder = new LZMA.LenDecoder(); this._literalDecoder = new LZMA.LiteralDecoder(); this._dictionarySize = -1; this._dictionarySizeCheck = -1; this._posSlotDecoder[0] = new LZMA.BitTreeDecoder(6); this._posSlotDecoder[1] = new LZMA.BitTreeDecoder(6); this._posSlotDecoder[2] = new LZMA.BitTreeDecoder(6); this._posSlotDecoder[3] = new LZMA.BitTreeDecoder(6); }; LZMA.Decoder.prototype.setDictionarySize = function(dictionarySize) { if (dictionarySize < 0) { return false; } if (this._dictionarySize !== dictionarySize) { this._dictionarySize = dictionarySize; this._dictionarySizeCheck = Math.max(this._dictionarySize, 1); this._outWindow.create( Math.max(this._dictionarySizeCheck, 4096) ); } return true; }; LZMA.Decoder.prototype.setLcLpPb = function(lc, lp, pb) { var numPosStates = 1 << pb; if (lc > 8 || lp > 4 || pb > 4) { return false; } this._literalDecoder.create(lp, lc); this._lenDecoder.create(numPosStates); this._repLenDecoder.create(numPosStates); this._posStateMask = numPosStates - 1; return true; }; LZMA.Decoder.prototype.init = function() { var i = 4; this._outWindow.init(false); LZMA.initBitModels(this._isMatchDecoders, 192); LZMA.initBitModels(this._isRep0LongDecoders, 192); LZMA.initBitModels(this._isRepDecoders, 12); LZMA.initBitModels(this._isRepG0Decoders, 12); LZMA.initBitModels(this._isRepG1Decoders, 12); LZMA.initBitModels(this._isRepG2Decoders, 12); LZMA.initBitModels(this._posDecoders, 114); this._literalDecoder.init(); while (i --) { this._posSlotDecoder[i].init(); } this._lenDecoder.init(); this._repLenDecoder.init(); this._posAlignDecoder.init(); this._rangeDecoder.init(); }; LZMA.Decoder.prototype.decode = function(inStream, outStream, outSize) { var state = 0, rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0, nowPos64 = 0, prevByte = 0, posState, decoder2, len, distance, posSlot, numDirectBits; this._rangeDecoder.setStream(inStream); this._outWindow.setStream(outStream); this.init(); while (outSize < 0 || nowPos64 < outSize) { posState = nowPos64 & this._posStateMask; if (this._rangeDecoder.decodeBit(this._isMatchDecoders, (state << 4) + posState) === 0) { decoder2 = this._literalDecoder.getDecoder(nowPos64 ++, prevByte); if (state >= 7) { prevByte = decoder2.decodeWithMatchByte(this._rangeDecoder, this._outWindow.getByte(rep0) ); }else { prevByte = decoder2.decodeNormal(this._rangeDecoder); } this._outWindow.putByte(prevByte); state = state < 4 ? 0 : state - (state < 10 ? 3 : 6); }else { if (this._rangeDecoder.decodeBit(this._isRepDecoders, state) === 1) { len = 0; if (this._rangeDecoder.decodeBit(this._isRepG0Decoders, state) === 0) { if (this._rangeDecoder.decodeBit(this._isRep0LongDecoders, (state << 4) + posState) === 0) { state = state < 7 ? 9 : 11; len = 1; } }else { if (this._rangeDecoder.decodeBit(this._isRepG1Decoders, state) === 0) { distance = rep1; }else { if (this._rangeDecoder.decodeBit(this._isRepG2Decoders, state) === 0) { distance = rep2; }else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } if (len === 0) { len = 2 + this._repLenDecoder.decode(this._rangeDecoder, posState); state = state < 7 ? 8 : 11; } }else { rep3 = rep2; rep2 = rep1; rep1 = rep0; len = 2 + this._lenDecoder.decode(this._rangeDecoder, posState); state = state < 7 ? 7 : 10; posSlot = this._posSlotDecoder[len <= 5 ? len - 2 : 3].decode(this._rangeDecoder); if (posSlot >= 4) { numDirectBits = (posSlot >> 1) - 1; rep0 = (2 | (posSlot & 1) ) << numDirectBits; if (posSlot < 14) { rep0 += LZMA.reverseDecode2(this._posDecoders, rep0 - posSlot - 1, this._rangeDecoder, numDirectBits); }else { rep0 += this._rangeDecoder.decodeDirectBits(numDirectBits - 4) << 4; rep0 += this._posAlignDecoder.reverseDecode(this._rangeDecoder); if (rep0 < 0) { if (rep0 === -1) { break; } return false; } } }else { rep0 = posSlot; } } if (rep0 >= nowPos64 || rep0 >= this._dictionarySizeCheck) { return false; } this._outWindow.copyBlock(rep0, len); nowPos64 += len; prevByte = this._outWindow.getByte(0); } } this._outWindow.flush(); this._outWindow.releaseStream(); this._rangeDecoder.releaseStream(); return true; }; LZMA.Decoder.prototype.setDecoderProperties = function(properties) { var value, lc, lp, pb, dictionarySize; if (properties.size < 5) { return false; } value = properties.readByte(); lc = value % 9; value = ~~(value / 9); lp = value % 5; pb = ~~(value / 5); if ( !this.setLcLpPb(lc, lp, pb) ) { return false; } dictionarySize = properties.readByte(); dictionarySize |= properties.readByte() << 8; dictionarySize |= properties.readByte() << 16; dictionarySize += properties.readByte() * 16777216; return this.setDictionarySize(dictionarySize); }; LZMA.decompress = function(properties, inStream, outStream, outSize) { var decoder = new LZMA.Decoder(); if ( !decoder.setDecoderProperties(properties) ) { throw "Incorrect stream properties"; } if ( !decoder.decode(inStream, outStream, outSize) ) { throw "Error in data stream"; } return true; };