0001: package SevenZip.Compression.lzma;
0002:
0003: import java.io.IOException;
0004:
0005: import SevenZip.ICodeProgress;
0006: import SevenZip.Compression.RangeCoder.BitTreeEncoder;
0007:
0008: public class Encoder {
0009: public static final int EMatchFinderTypeBT2 = 0;
0010: public static final int EMatchFinderTypeBT4 = 1;
0011:
0012: static final int kIfinityPrice = 0xFFFFFFF;
0013:
0014: static byte[] g_FastPos = new byte[1 << 11];
0015:
0016: static {
0017: int kFastSlots = 22;
0018: int c = 2;
0019: g_FastPos[0] = 0;
0020: g_FastPos[1] = 1;
0021: for (int slotFast = 2; slotFast < kFastSlots; slotFast++) {
0022: int k = (1 << ((slotFast >> 1) - 1));
0023: for (int j = 0; j < k; j++, c++)
0024: g_FastPos[c] = (byte) slotFast;
0025: }
0026: }
0027:
0028: static int GetPosSlot(int pos) {
0029: if (pos < (1 << 11))
0030: return g_FastPos[pos];
0031: if (pos < (1 << 21))
0032: return (g_FastPos[pos >> 10] + 20);
0033: return (g_FastPos[pos >> 20] + 40);
0034: }
0035:
0036: static int GetPosSlot2(int pos) {
0037: if (pos < (1 << 17))
0038: return (g_FastPos[pos >> 6] + 12);
0039: if (pos < (1 << 27))
0040: return (g_FastPos[pos >> 16] + 32);
0041: return (g_FastPos[pos >> 26] + 52);
0042: }
0043:
0044: int _state = Base.StateInit();
0045: byte _previousByte;
0046: int[] _repDistances = new int[Base.kNumRepDistances];
0047:
0048: void BaseInit() {
0049: _state = Base.StateInit();
0050: _previousByte = 0;
0051: for (int i = 0; i < Base.kNumRepDistances; i++)
0052: _repDistances[i] = 0;
0053: }
0054:
0055: static final int kDefaultDictionaryLogSize = 22;
0056: static final int kNumFastBytesDefault = 0x20;
0057:
0058: class LiteralEncoder {
0059: class Encoder2 {
0060: short[] m_Encoders = new short[0x300];
0061:
0062: public void Init() {
0063: SevenZip.Compression.RangeCoder.Encoder
0064: .InitBitModels(m_Encoders);
0065: }
0066:
0067: public void Encode(
0068: SevenZip.Compression.RangeCoder.Encoder rangeEncoder,
0069: byte symbol) throws IOException {
0070: int context = 1;
0071: for (int i = 7; i >= 0; i--) {
0072: int bit = ((symbol >> i) & 1);
0073: rangeEncoder.Encode(m_Encoders, context, bit);
0074: context = (context << 1) | bit;
0075: }
0076: }
0077:
0078: public void EncodeMatched(
0079: SevenZip.Compression.RangeCoder.Encoder rangeEncoder,
0080: byte matchByte, byte symbol) throws IOException {
0081: int context = 1;
0082: boolean same = true;
0083: for (int i = 7; i >= 0; i--) {
0084: int bit = ((symbol >> i) & 1);
0085: int state = context;
0086: if (same) {
0087: int matchBit = ((matchByte >> i) & 1);
0088: state += ((1 + matchBit) << 8);
0089: same = (matchBit == bit);
0090: }
0091: rangeEncoder.Encode(m_Encoders, state, bit);
0092: context = (context << 1) | bit;
0093: }
0094: }
0095:
0096: public int GetPrice(boolean matchMode, byte matchByte,
0097: byte symbol) {
0098: int price = 0;
0099: int context = 1;
0100: int i = 7;
0101: if (matchMode) {
0102: for (; i >= 0; i--) {
0103: int matchBit = (matchByte >> i) & 1;
0104: int bit = (symbol >> i) & 1;
0105: price += SevenZip.Compression.RangeCoder.Encoder
0106: .GetPrice(
0107: m_Encoders[((1 + matchBit) << 8)
0108: + context], bit);
0109: context = (context << 1) | bit;
0110: if (matchBit != bit) {
0111: i--;
0112: break;
0113: }
0114: }
0115: }
0116: for (; i >= 0; i--) {
0117: int bit = (symbol >> i) & 1;
0118: price += SevenZip.Compression.RangeCoder.Encoder
0119: .GetPrice(m_Encoders[context], bit);
0120: context = (context << 1) | bit;
0121: }
0122: return price;
0123: }
0124: }
0125:
0126: Encoder2[] m_Coders;
0127: int m_NumPrevBits;
0128: int m_NumPosBits;
0129: int m_PosMask;
0130:
0131: public void Create(int numPosBits, int numPrevBits) {
0132: if (m_Coders != null && m_NumPrevBits == numPrevBits
0133: && m_NumPosBits == numPosBits)
0134: return;
0135: m_NumPosBits = numPosBits;
0136: m_PosMask = (1 << numPosBits) - 1;
0137: m_NumPrevBits = numPrevBits;
0138: int numStates = 1 << (m_NumPrevBits + m_NumPosBits);
0139: m_Coders = new Encoder2[numStates];
0140: for (int i = 0; i < numStates; i++)
0141: m_Coders[i] = new Encoder2();
0142: }
0143:
0144: public void Init() {
0145: int numStates = 1 << (m_NumPrevBits + m_NumPosBits);
0146: for (int i = 0; i < numStates; i++)
0147: m_Coders[i].Init();
0148: }
0149:
0150: public Encoder2 GetSubCoder(int pos, byte prevByte) {
0151: return m_Coders[((pos & m_PosMask) << m_NumPrevBits)
0152: + ((prevByte & 0xFF) >>> (8 - m_NumPrevBits))];
0153: }
0154: }
0155:
0156: class LenEncoder {
0157: short[] _choice = new short[2];
0158: BitTreeEncoder[] _lowCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax];
0159: BitTreeEncoder[] _midCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax];
0160: BitTreeEncoder _highCoder = new BitTreeEncoder(
0161: Base.kNumHighLenBits);
0162:
0163: public LenEncoder() {
0164: for (int posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++) {
0165: _lowCoder[posState] = new BitTreeEncoder(
0166: Base.kNumLowLenBits);
0167: _midCoder[posState] = new BitTreeEncoder(
0168: Base.kNumMidLenBits);
0169: }
0170: }
0171:
0172: public void Init(int numPosStates) {
0173: SevenZip.Compression.RangeCoder.Encoder
0174: .InitBitModels(_choice);
0175:
0176: for (int posState = 0; posState < numPosStates; posState++) {
0177: _lowCoder[posState].Init();
0178: _midCoder[posState].Init();
0179: }
0180: _highCoder.Init();
0181: }
0182:
0183: public void Encode(
0184: SevenZip.Compression.RangeCoder.Encoder rangeEncoder,
0185: int symbol, int posState) throws IOException {
0186: if (symbol < Base.kNumLowLenSymbols) {
0187: rangeEncoder.Encode(_choice, 0, 0);
0188: _lowCoder[posState].Encode(rangeEncoder, symbol);
0189: } else {
0190: symbol -= Base.kNumLowLenSymbols;
0191: rangeEncoder.Encode(_choice, 0, 1);
0192: if (symbol < Base.kNumMidLenSymbols) {
0193: rangeEncoder.Encode(_choice, 1, 0);
0194: _midCoder[posState].Encode(rangeEncoder, symbol);
0195: } else {
0196: rangeEncoder.Encode(_choice, 1, 1);
0197: _highCoder.Encode(rangeEncoder, symbol
0198: - Base.kNumMidLenSymbols);
0199: }
0200: }
0201: }
0202:
0203: public void SetPrices(int posState, int numSymbols,
0204: int[] prices, int st) {
0205: int a0 = SevenZip.Compression.RangeCoder.Encoder
0206: .GetPrice0(_choice[0]);
0207: int a1 = SevenZip.Compression.RangeCoder.Encoder
0208: .GetPrice1(_choice[0]);
0209: int b0 = a1
0210: + SevenZip.Compression.RangeCoder.Encoder
0211: .GetPrice0(_choice[1]);
0212: int b1 = a1
0213: + SevenZip.Compression.RangeCoder.Encoder
0214: .GetPrice1(_choice[1]);
0215: int i = 0;
0216: for (i = 0; i < Base.kNumLowLenSymbols; i++) {
0217: if (i >= numSymbols)
0218: return;
0219: prices[st + i] = a0 + _lowCoder[posState].GetPrice(i);
0220: }
0221: for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++) {
0222: if (i >= numSymbols)
0223: return;
0224: prices[st + i] = b0
0225: + _midCoder[posState].GetPrice(i
0226: - Base.kNumLowLenSymbols);
0227: }
0228: for (; i < numSymbols; i++)
0229: prices[st + i] = b1
0230: + _highCoder.GetPrice(i
0231: - Base.kNumLowLenSymbols
0232: - Base.kNumMidLenSymbols);
0233: }
0234: };
0235:
0236: public static final int kNumLenSpecSymbols = Base.kNumLowLenSymbols
0237: + Base.kNumMidLenSymbols;
0238:
0239: class LenPriceTableEncoder extends LenEncoder {
0240: int[] _prices = new int[Base.kNumLenSymbols << Base.kNumPosStatesBitsEncodingMax];
0241: int _tableSize;
0242: int[] _counters = new int[Base.kNumPosStatesEncodingMax];
0243:
0244: public void SetTableSize(int tableSize) {
0245: _tableSize = tableSize;
0246: }
0247:
0248: public int GetPrice(int symbol, int posState) {
0249: return _prices[posState * Base.kNumLenSymbols + symbol];
0250: }
0251:
0252: void UpdateTable(int posState) {
0253: SetPrices(posState, _tableSize, _prices, posState
0254: * Base.kNumLenSymbols);
0255: _counters[posState] = _tableSize;
0256: }
0257:
0258: public void UpdateTables(int numPosStates) {
0259: for (int posState = 0; posState < numPosStates; posState++)
0260: UpdateTable(posState);
0261: }
0262:
0263: public void Encode(
0264: SevenZip.Compression.RangeCoder.Encoder rangeEncoder,
0265: int symbol, int posState) throws IOException {
0266: super .Encode(rangeEncoder, symbol, posState);
0267: if (--_counters[posState] == 0)
0268: UpdateTable(posState);
0269: }
0270: }
0271:
0272: static final int kNumOpts = 1 << 12;
0273:
0274: class Optimal {
0275: public int State;
0276:
0277: public boolean Prev1IsChar;
0278: public boolean Prev2;
0279:
0280: public int PosPrev2;
0281: public int BackPrev2;
0282:
0283: public int Price;
0284: public int PosPrev;
0285: public int BackPrev;
0286:
0287: public int Backs0;
0288: public int Backs1;
0289: public int Backs2;
0290: public int Backs3;
0291:
0292: public void MakeAsChar() {
0293: BackPrev = -1;
0294: Prev1IsChar = false;
0295: }
0296:
0297: public void MakeAsShortRep() {
0298: BackPrev = 0;
0299: ;
0300: Prev1IsChar = false;
0301: }
0302:
0303: public boolean IsShortRep() {
0304: return (BackPrev == 0);
0305: }
0306: };
0307:
0308: Optimal[] _optimum = new Optimal[kNumOpts];
0309: SevenZip.Compression.lz.BinTree _matchFinder = null;
0310: SevenZip.Compression.RangeCoder.Encoder _rangeEncoder = new SevenZip.Compression.RangeCoder.Encoder();
0311:
0312: short[] _isMatch = new short[Base.kNumStates << Base.kNumPosStatesBitsMax];
0313: short[] _isRep = new short[Base.kNumStates];
0314: short[] _isRepG0 = new short[Base.kNumStates];
0315: short[] _isRepG1 = new short[Base.kNumStates];
0316: short[] _isRepG2 = new short[Base.kNumStates];
0317: short[] _isRep0Long = new short[Base.kNumStates << Base.kNumPosStatesBitsMax];
0318:
0319: BitTreeEncoder[] _posSlotEncoder = new BitTreeEncoder[Base.kNumLenToPosStates]; // kNumPosSlotBits
0320:
0321: short[] _posEncoders = new short[Base.kNumFullDistances
0322: - Base.kEndPosModelIndex];
0323: BitTreeEncoder _posAlignEncoder = new BitTreeEncoder(
0324: Base.kNumAlignBits);
0325:
0326: LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder();
0327: LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder();
0328:
0329: LiteralEncoder _literalEncoder = new LiteralEncoder();
0330:
0331: int[] _matchDistances = new int[Base.kMatchMaxLen * 2 + 2];
0332:
0333: int _numFastBytes = kNumFastBytesDefault;
0334: int _longestMatchLength;
0335: int _numDistancePairs;
0336:
0337: int _additionalOffset;
0338:
0339: int _optimumEndIndex;
0340: int _optimumCurrentIndex;
0341:
0342: boolean _longestMatchWasFound;
0343:
0344: int[] _posSlotPrices = new int[1 << (Base.kNumPosSlotBits + Base.kNumLenToPosStatesBits)];
0345: int[] _distancesPrices = new int[Base.kNumFullDistances << Base.kNumLenToPosStatesBits];
0346: int[] _alignPrices = new int[Base.kAlignTableSize];
0347: int _alignPriceCount;
0348:
0349: int _distTableSize = (kDefaultDictionaryLogSize * 2);
0350:
0351: int _posStateBits = 2;
0352: int _posStateMask = (4 - 1);
0353: int _numLiteralPosStateBits = 0;
0354: int _numLiteralContextBits = 3;
0355:
0356: int _dictionarySize = (1 << kDefaultDictionaryLogSize);
0357: int _dictionarySizePrev = -1;
0358: int _numFastBytesPrev = -1;
0359:
0360: long nowPos64;
0361: boolean _finished;
0362: java.io.InputStream _inStream;
0363:
0364: int _matchFinderType = EMatchFinderTypeBT4;
0365: boolean _writeEndMark = false;
0366:
0367: boolean _needReleaseMFStream = false;
0368:
0369: void Create() {
0370: if (_matchFinder == null) {
0371: SevenZip.Compression.lz.BinTree bt = new SevenZip.Compression.lz.BinTree();
0372: int numHashBytes = 4;
0373: if (_matchFinderType == EMatchFinderTypeBT2)
0374: numHashBytes = 2;
0375: bt.SetType(numHashBytes);
0376: _matchFinder = bt;
0377: }
0378: _literalEncoder.Create(_numLiteralPosStateBits,
0379: _numLiteralContextBits);
0380:
0381: if (_dictionarySize == _dictionarySizePrev
0382: && _numFastBytesPrev == _numFastBytes)
0383: return;
0384: _matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes,
0385: Base.kMatchMaxLen + 1);
0386: _dictionarySizePrev = _dictionarySize;
0387: _numFastBytesPrev = _numFastBytes;
0388: }
0389:
0390: public Encoder() {
0391: for (int i = 0; i < kNumOpts; i++)
0392: _optimum[i] = new Optimal();
0393: for (int i = 0; i < Base.kNumLenToPosStates; i++)
0394: _posSlotEncoder[i] = new BitTreeEncoder(
0395: Base.kNumPosSlotBits);
0396: }
0397:
0398: void SetWriteEndMarkerMode(boolean writeEndMarker) {
0399: _writeEndMark = writeEndMarker;
0400: }
0401:
0402: void Init() {
0403: BaseInit();
0404: _rangeEncoder.Init();
0405:
0406: SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isMatch);
0407: SevenZip.Compression.RangeCoder.Encoder
0408: .InitBitModels(_isRep0Long);
0409: SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRep);
0410: SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG0);
0411: SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG1);
0412: SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG2);
0413: SevenZip.Compression.RangeCoder.Encoder
0414: .InitBitModels(_posEncoders);
0415:
0416: _literalEncoder.Init();
0417: for (int i = 0; i < Base.kNumLenToPosStates; i++)
0418: _posSlotEncoder[i].Init();
0419:
0420: _lenEncoder.Init(1 << _posStateBits);
0421: _repMatchLenEncoder.Init(1 << _posStateBits);
0422:
0423: _posAlignEncoder.Init();
0424:
0425: _longestMatchWasFound = false;
0426: _optimumEndIndex = 0;
0427: _optimumCurrentIndex = 0;
0428: _additionalOffset = 0;
0429: }
0430:
0431: int ReadMatchDistances() throws java.io.IOException {
0432: int lenRes = 0;
0433: _numDistancePairs = _matchFinder.GetMatches(_matchDistances);
0434: if (_numDistancePairs > 0) {
0435: lenRes = _matchDistances[_numDistancePairs - 2];
0436: if (lenRes == _numFastBytes)
0437: lenRes += _matchFinder.GetMatchLen(lenRes - 1,
0438: _matchDistances[_numDistancePairs - 1],
0439: Base.kMatchMaxLen - lenRes);
0440: }
0441: _additionalOffset++;
0442: return lenRes;
0443: }
0444:
0445: void MovePos(int num) throws java.io.IOException {
0446: if (num > 0) {
0447: _matchFinder.Skip(num);
0448: _additionalOffset += num;
0449: }
0450: }
0451:
0452: int GetRepLen1Price(int state, int posState) {
0453: return SevenZip.Compression.RangeCoder.Encoder
0454: .GetPrice0(_isRepG0[state])
0455: + SevenZip.Compression.RangeCoder.Encoder
0456: .GetPrice0(_isRep0Long[(state << Base.kNumPosStatesBitsMax)
0457: + posState]);
0458: }
0459:
0460: int GetPureRepPrice(int repIndex, int state, int posState) {
0461: int price;
0462: if (repIndex == 0) {
0463: price = SevenZip.Compression.RangeCoder.Encoder
0464: .GetPrice0(_isRepG0[state]);
0465: price += SevenZip.Compression.RangeCoder.Encoder
0466: .GetPrice1(_isRep0Long[(state << Base.kNumPosStatesBitsMax)
0467: + posState]);
0468: } else {
0469: price = SevenZip.Compression.RangeCoder.Encoder
0470: .GetPrice1(_isRepG0[state]);
0471: if (repIndex == 1)
0472: price += SevenZip.Compression.RangeCoder.Encoder
0473: .GetPrice0(_isRepG1[state]);
0474: else {
0475: price += SevenZip.Compression.RangeCoder.Encoder
0476: .GetPrice1(_isRepG1[state]);
0477: price += SevenZip.Compression.RangeCoder.Encoder
0478: .GetPrice(_isRepG2[state], repIndex - 2);
0479: }
0480: }
0481: return price;
0482: }
0483:
0484: int GetRepPrice(int repIndex, int len, int state, int posState) {
0485: int price = _repMatchLenEncoder.GetPrice(len
0486: - Base.kMatchMinLen, posState);
0487: return price + GetPureRepPrice(repIndex, state, posState);
0488: }
0489:
0490: int GetPosLenPrice(int pos, int len, int posState) {
0491: int price;
0492: int lenToPosState = Base.GetLenToPosState(len);
0493: if (pos < Base.kNumFullDistances)
0494: price = _distancesPrices[(lenToPosState * Base.kNumFullDistances)
0495: + pos];
0496: else
0497: price = _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits)
0498: + GetPosSlot2(pos)]
0499: + _alignPrices[pos & Base.kAlignMask];
0500: return price
0501: + _lenEncoder.GetPrice(len - Base.kMatchMinLen,
0502: posState);
0503: }
0504:
0505: int Backward(int cur) {
0506: _optimumEndIndex = cur;
0507: int posMem = _optimum[cur].PosPrev;
0508: int backMem = _optimum[cur].BackPrev;
0509: do {
0510: if (_optimum[cur].Prev1IsChar) {
0511: _optimum[posMem].MakeAsChar();
0512: _optimum[posMem].PosPrev = posMem - 1;
0513: if (_optimum[cur].Prev2) {
0514: _optimum[posMem - 1].Prev1IsChar = false;
0515: _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2;
0516: _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2;
0517: }
0518: }
0519: int posPrev = posMem;
0520: int backCur = backMem;
0521:
0522: backMem = _optimum[posPrev].BackPrev;
0523: posMem = _optimum[posPrev].PosPrev;
0524:
0525: _optimum[posPrev].BackPrev = backCur;
0526: _optimum[posPrev].PosPrev = cur;
0527: cur = posPrev;
0528: } while (cur > 0);
0529: backRes = _optimum[0].BackPrev;
0530: _optimumCurrentIndex = _optimum[0].PosPrev;
0531: return _optimumCurrentIndex;
0532: }
0533:
0534: int[] reps = new int[Base.kNumRepDistances];
0535: int[] repLens = new int[Base.kNumRepDistances];
0536: int backRes;
0537:
0538: int GetOptimum(int position) throws IOException {
0539: if (_optimumEndIndex != _optimumCurrentIndex) {
0540: int lenRes = _optimum[_optimumCurrentIndex].PosPrev
0541: - _optimumCurrentIndex;
0542: backRes = _optimum[_optimumCurrentIndex].BackPrev;
0543: _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev;
0544: return lenRes;
0545: }
0546: _optimumCurrentIndex = _optimumEndIndex = 0;
0547:
0548: int lenMain, numDistancePairs;
0549: if (!_longestMatchWasFound) {
0550: lenMain = ReadMatchDistances();
0551: } else {
0552: lenMain = _longestMatchLength;
0553: _longestMatchWasFound = false;
0554: }
0555: numDistancePairs = _numDistancePairs;
0556:
0557: int numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1;
0558: if (numAvailableBytes < 2) {
0559: backRes = -1;
0560: return 1;
0561: }
0562: if (numAvailableBytes > Base.kMatchMaxLen)
0563: numAvailableBytes = Base.kMatchMaxLen;
0564:
0565: int repMaxIndex = 0;
0566: int i;
0567: for (i = 0; i < Base.kNumRepDistances; i++) {
0568: reps[i] = _repDistances[i];
0569: repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i],
0570: Base.kMatchMaxLen);
0571: if (repLens[i] > repLens[repMaxIndex])
0572: repMaxIndex = i;
0573: }
0574: if (repLens[repMaxIndex] >= _numFastBytes) {
0575: backRes = repMaxIndex;
0576: int lenRes = repLens[repMaxIndex];
0577: MovePos(lenRes - 1);
0578: return lenRes;
0579: }
0580:
0581: if (lenMain >= _numFastBytes) {
0582: backRes = _matchDistances[numDistancePairs - 1]
0583: + Base.kNumRepDistances;
0584: MovePos(lenMain - 1);
0585: return lenMain;
0586: }
0587:
0588: byte currentByte = _matchFinder.GetIndexByte(0 - 1);
0589: byte matchByte = _matchFinder
0590: .GetIndexByte(0 - _repDistances[0] - 1 - 1);
0591:
0592: if (lenMain < 2 && currentByte != matchByte
0593: && repLens[repMaxIndex] < 2) {
0594: backRes = -1;
0595: return 1;
0596: }
0597:
0598: _optimum[0].State = _state;
0599:
0600: int posState = (position & _posStateMask);
0601:
0602: _optimum[1].Price = SevenZip.Compression.RangeCoder.Encoder
0603: .GetPrice0(_isMatch[(_state << Base.kNumPosStatesBitsMax)
0604: + posState])
0605: + _literalEncoder.GetSubCoder(position, _previousByte)
0606: .GetPrice(!Base.StateIsCharState(_state),
0607: matchByte, currentByte);
0608: _optimum[1].MakeAsChar();
0609:
0610: int matchPrice = SevenZip.Compression.RangeCoder.Encoder
0611: .GetPrice1(_isMatch[(_state << Base.kNumPosStatesBitsMax)
0612: + posState]);
0613: int repMatchPrice = matchPrice
0614: + SevenZip.Compression.RangeCoder.Encoder
0615: .GetPrice1(_isRep[_state]);
0616:
0617: if (matchByte == currentByte) {
0618: int shortRepPrice = repMatchPrice
0619: + GetRepLen1Price(_state, posState);
0620: if (shortRepPrice < _optimum[1].Price) {
0621: _optimum[1].Price = shortRepPrice;
0622: _optimum[1].MakeAsShortRep();
0623: }
0624: }
0625:
0626: int lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain
0627: : repLens[repMaxIndex]);
0628:
0629: if (lenEnd < 2) {
0630: backRes = _optimum[1].BackPrev;
0631: return 1;
0632: }
0633:
0634: _optimum[1].PosPrev = 0;
0635:
0636: _optimum[0].Backs0 = reps[0];
0637: _optimum[0].Backs1 = reps[1];
0638: _optimum[0].Backs2 = reps[2];
0639: _optimum[0].Backs3 = reps[3];
0640:
0641: int len = lenEnd;
0642: do
0643: _optimum[len--].Price = kIfinityPrice;
0644: while (len >= 2);
0645:
0646: for (i = 0; i < Base.kNumRepDistances; i++) {
0647: int repLen = repLens[i];
0648: if (repLen < 2)
0649: continue;
0650: int price = repMatchPrice
0651: + GetPureRepPrice(i, _state, posState);
0652: do {
0653: int curAndLenPrice = price
0654: + _repMatchLenEncoder.GetPrice(repLen - 2,
0655: posState);
0656: Optimal optimum = _optimum[repLen];
0657: if (curAndLenPrice < optimum.Price) {
0658: optimum.Price = curAndLenPrice;
0659: optimum.PosPrev = 0;
0660: optimum.BackPrev = i;
0661: optimum.Prev1IsChar = false;
0662: }
0663: } while (--repLen >= 2);
0664: }
0665:
0666: int normalMatchPrice = matchPrice
0667: + SevenZip.Compression.RangeCoder.Encoder
0668: .GetPrice0(_isRep[_state]);
0669:
0670: len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2);
0671: if (len <= lenMain) {
0672: int offs = 0;
0673: while (len > _matchDistances[offs])
0674: offs += 2;
0675: for (;; len++) {
0676: int distance = _matchDistances[offs + 1];
0677: int curAndLenPrice = normalMatchPrice
0678: + GetPosLenPrice(distance, len, posState);
0679: Optimal optimum = _optimum[len];
0680: if (curAndLenPrice < optimum.Price) {
0681: optimum.Price = curAndLenPrice;
0682: optimum.PosPrev = 0;
0683: optimum.BackPrev = distance + Base.kNumRepDistances;
0684: optimum.Prev1IsChar = false;
0685: }
0686: if (len == _matchDistances[offs]) {
0687: offs += 2;
0688: if (offs == numDistancePairs)
0689: break;
0690: }
0691: }
0692: }
0693:
0694: int cur = 0;
0695:
0696: while (true) {
0697: cur++;
0698: if (cur == lenEnd)
0699: return Backward(cur);
0700: int newLen = ReadMatchDistances();
0701: numDistancePairs = _numDistancePairs;
0702: if (newLen >= _numFastBytes) {
0703:
0704: _longestMatchLength = newLen;
0705: _longestMatchWasFound = true;
0706: return Backward(cur);
0707: }
0708: position++;
0709: int posPrev = _optimum[cur].PosPrev;
0710: int state;
0711: if (_optimum[cur].Prev1IsChar) {
0712: posPrev--;
0713: if (_optimum[cur].Prev2) {
0714: state = _optimum[_optimum[cur].PosPrev2].State;
0715: if (_optimum[cur].BackPrev2 < Base.kNumRepDistances)
0716: state = Base.StateUpdateRep(state);
0717: else
0718: state = Base.StateUpdateMatch(state);
0719: } else
0720: state = _optimum[posPrev].State;
0721: state = Base.StateUpdateChar(state);
0722: } else
0723: state = _optimum[posPrev].State;
0724: if (posPrev == cur - 1) {
0725: if (_optimum[cur].IsShortRep())
0726: state = Base.StateUpdateShortRep(state);
0727: else
0728: state = Base.StateUpdateChar(state);
0729: } else {
0730: int pos;
0731: if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2) {
0732: posPrev = _optimum[cur].PosPrev2;
0733: pos = _optimum[cur].BackPrev2;
0734: state = Base.StateUpdateRep(state);
0735: } else {
0736: pos = _optimum[cur].BackPrev;
0737: if (pos < Base.kNumRepDistances)
0738: state = Base.StateUpdateRep(state);
0739: else
0740: state = Base.StateUpdateMatch(state);
0741: }
0742: Optimal opt = _optimum[posPrev];
0743: if (pos < Base.kNumRepDistances) {
0744: if (pos == 0) {
0745: reps[0] = opt.Backs0;
0746: reps[1] = opt.Backs1;
0747: reps[2] = opt.Backs2;
0748: reps[3] = opt.Backs3;
0749: } else if (pos == 1) {
0750: reps[0] = opt.Backs1;
0751: reps[1] = opt.Backs0;
0752: reps[2] = opt.Backs2;
0753: reps[3] = opt.Backs3;
0754: } else if (pos == 2) {
0755: reps[0] = opt.Backs2;
0756: reps[1] = opt.Backs0;
0757: reps[2] = opt.Backs1;
0758: reps[3] = opt.Backs3;
0759: } else {
0760: reps[0] = opt.Backs3;
0761: reps[1] = opt.Backs0;
0762: reps[2] = opt.Backs1;
0763: reps[3] = opt.Backs2;
0764: }
0765: } else {
0766: reps[0] = (pos - Base.kNumRepDistances);
0767: reps[1] = opt.Backs0;
0768: reps[2] = opt.Backs1;
0769: reps[3] = opt.Backs2;
0770: }
0771: }
0772: _optimum[cur].State = state;
0773: _optimum[cur].Backs0 = reps[0];
0774: _optimum[cur].Backs1 = reps[1];
0775: _optimum[cur].Backs2 = reps[2];
0776: _optimum[cur].Backs3 = reps[3];
0777: int curPrice = _optimum[cur].Price;
0778:
0779: currentByte = _matchFinder.GetIndexByte(0 - 1);
0780: matchByte = _matchFinder.GetIndexByte(0 - reps[0] - 1 - 1);
0781:
0782: posState = (position & _posStateMask);
0783:
0784: int curAnd1Price = curPrice
0785: + SevenZip.Compression.RangeCoder.Encoder
0786: .GetPrice0(_isMatch[(state << Base.kNumPosStatesBitsMax)
0787: + posState])
0788: + _literalEncoder.GetSubCoder(position,
0789: _matchFinder.GetIndexByte(0 - 2)).GetPrice(
0790: !Base.StateIsCharState(state), matchByte,
0791: currentByte);
0792:
0793: Optimal nextOptimum = _optimum[cur + 1];
0794:
0795: boolean nextIsChar = false;
0796: if (curAnd1Price < nextOptimum.Price) {
0797: nextOptimum.Price = curAnd1Price;
0798: nextOptimum.PosPrev = cur;
0799: nextOptimum.MakeAsChar();
0800: nextIsChar = true;
0801: }
0802:
0803: matchPrice = curPrice
0804: + SevenZip.Compression.RangeCoder.Encoder
0805: .GetPrice1(_isMatch[(state << Base.kNumPosStatesBitsMax)
0806: + posState]);
0807: repMatchPrice = matchPrice
0808: + SevenZip.Compression.RangeCoder.Encoder
0809: .GetPrice1(_isRep[state]);
0810:
0811: if (matchByte == currentByte
0812: && !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) {
0813: int shortRepPrice = repMatchPrice
0814: + GetRepLen1Price(state, posState);
0815: if (shortRepPrice <= nextOptimum.Price) {
0816: nextOptimum.Price = shortRepPrice;
0817: nextOptimum.PosPrev = cur;
0818: nextOptimum.MakeAsShortRep();
0819: nextIsChar = true;
0820: }
0821: }
0822:
0823: int numAvailableBytesFull = _matchFinder
0824: .GetNumAvailableBytes() + 1;
0825: numAvailableBytesFull = Math.min(kNumOpts - 1 - cur,
0826: numAvailableBytesFull);
0827: numAvailableBytes = numAvailableBytesFull;
0828:
0829: if (numAvailableBytes < 2)
0830: continue;
0831: if (numAvailableBytes > _numFastBytes)
0832: numAvailableBytes = _numFastBytes;
0833: if (!nextIsChar && matchByte != currentByte) {
0834: // try Literal + rep0
0835: int t = Math.min(numAvailableBytesFull - 1,
0836: _numFastBytes);
0837: int lenTest2 = _matchFinder.GetMatchLen(0, reps[0], t);
0838: if (lenTest2 >= 2) {
0839: int state2 = Base.StateUpdateChar(state);
0840:
0841: int posStateNext = (position + 1) & _posStateMask;
0842: int nextRepMatchPrice = curAnd1Price
0843: + SevenZip.Compression.RangeCoder.Encoder
0844: .GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax)
0845: + posStateNext])
0846: + SevenZip.Compression.RangeCoder.Encoder
0847: .GetPrice1(_isRep[state2]);
0848: {
0849: int offset = cur + 1 + lenTest2;
0850: while (lenEnd < offset)
0851: _optimum[++lenEnd].Price = kIfinityPrice;
0852: int curAndLenPrice = nextRepMatchPrice
0853: + GetRepPrice(0, lenTest2, state2,
0854: posStateNext);
0855: Optimal optimum = _optimum[offset];
0856: if (curAndLenPrice < optimum.Price) {
0857: optimum.Price = curAndLenPrice;
0858: optimum.PosPrev = cur + 1;
0859: optimum.BackPrev = 0;
0860: optimum.Prev1IsChar = true;
0861: optimum.Prev2 = false;
0862: }
0863: }
0864: }
0865: }
0866:
0867: int startLen = 2; // speed optimization
0868:
0869: for (int repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++) {
0870: int lenTest = _matchFinder.GetMatchLen(0 - 1,
0871: reps[repIndex], numAvailableBytes);
0872: if (lenTest < 2)
0873: continue;
0874: int lenTestTemp = lenTest;
0875: do {
0876: while (lenEnd < cur + lenTest)
0877: _optimum[++lenEnd].Price = kIfinityPrice;
0878: int curAndLenPrice = repMatchPrice
0879: + GetRepPrice(repIndex, lenTest, state,
0880: posState);
0881: Optimal optimum = _optimum[cur + lenTest];
0882: if (curAndLenPrice < optimum.Price) {
0883: optimum.Price = curAndLenPrice;
0884: optimum.PosPrev = cur;
0885: optimum.BackPrev = repIndex;
0886: optimum.Prev1IsChar = false;
0887: }
0888: } while (--lenTest >= 2);
0889: lenTest = lenTestTemp;
0890:
0891: if (repIndex == 0)
0892: startLen = lenTest + 1;
0893:
0894: // if (_maxMode)
0895: if (lenTest < numAvailableBytesFull) {
0896: int t = Math.min(numAvailableBytesFull - 1
0897: - lenTest, _numFastBytes);
0898: int lenTest2 = _matchFinder.GetMatchLen(lenTest,
0899: reps[repIndex], t);
0900: if (lenTest2 >= 2) {
0901: int state2 = Base.StateUpdateRep(state);
0902:
0903: int posStateNext = (position + lenTest)
0904: & _posStateMask;
0905: int curAndLenCharPrice = repMatchPrice
0906: + GetRepPrice(repIndex, lenTest, state,
0907: posState)
0908: + SevenZip.Compression.RangeCoder.Encoder
0909: .GetPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax)
0910: + posStateNext])
0911: + _literalEncoder
0912: .GetSubCoder(
0913: position + lenTest,
0914: _matchFinder
0915: .GetIndexByte(lenTest - 1 - 1))
0916: .GetPrice(
0917: true,
0918: _matchFinder
0919: .GetIndexByte(lenTest
0920: - 1
0921: - (reps[repIndex] + 1)),
0922: _matchFinder
0923: .GetIndexByte(lenTest - 1));
0924: state2 = Base.StateUpdateChar(state2);
0925: posStateNext = (position + lenTest + 1)
0926: & _posStateMask;
0927: int nextMatchPrice = curAndLenCharPrice
0928: + SevenZip.Compression.RangeCoder.Encoder
0929: .GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax)
0930: + posStateNext]);
0931: int nextRepMatchPrice = nextMatchPrice
0932: + SevenZip.Compression.RangeCoder.Encoder
0933: .GetPrice1(_isRep[state2]);
0934:
0935: // for(; lenTest2 >= 2; lenTest2--)
0936: {
0937: int offset = lenTest + 1 + lenTest2;
0938: while (lenEnd < cur + offset)
0939: _optimum[++lenEnd].Price = kIfinityPrice;
0940: int curAndLenPrice = nextRepMatchPrice
0941: + GetRepPrice(0, lenTest2, state2,
0942: posStateNext);
0943: Optimal optimum = _optimum[cur + offset];
0944: if (curAndLenPrice < optimum.Price) {
0945: optimum.Price = curAndLenPrice;
0946: optimum.PosPrev = cur + lenTest + 1;
0947: optimum.BackPrev = 0;
0948: optimum.Prev1IsChar = true;
0949: optimum.Prev2 = true;
0950: optimum.PosPrev2 = cur;
0951: optimum.BackPrev2 = repIndex;
0952: }
0953: }
0954: }
0955: }
0956: }
0957:
0958: if (newLen > numAvailableBytes) {
0959: newLen = numAvailableBytes;
0960: for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2)
0961: ;
0962: _matchDistances[numDistancePairs] = newLen;
0963: numDistancePairs += 2;
0964: }
0965: if (newLen >= startLen) {
0966: normalMatchPrice = matchPrice
0967: + SevenZip.Compression.RangeCoder.Encoder
0968: .GetPrice0(_isRep[state]);
0969: while (lenEnd < cur + newLen)
0970: _optimum[++lenEnd].Price = kIfinityPrice;
0971:
0972: int offs = 0;
0973: while (startLen > _matchDistances[offs])
0974: offs += 2;
0975:
0976: for (int lenTest = startLen;; lenTest++) {
0977: int curBack = _matchDistances[offs + 1];
0978: int curAndLenPrice = normalMatchPrice
0979: + GetPosLenPrice(curBack, lenTest, posState);
0980: Optimal optimum = _optimum[cur + lenTest];
0981: if (curAndLenPrice < optimum.Price) {
0982: optimum.Price = curAndLenPrice;
0983: optimum.PosPrev = cur;
0984: optimum.BackPrev = curBack
0985: + Base.kNumRepDistances;
0986: optimum.Prev1IsChar = false;
0987: }
0988:
0989: if (lenTest == _matchDistances[offs]) {
0990: if (lenTest < numAvailableBytesFull) {
0991: int t = Math.min(numAvailableBytesFull - 1
0992: - lenTest, _numFastBytes);
0993: int lenTest2 = _matchFinder.GetMatchLen(
0994: lenTest, curBack, t);
0995: if (lenTest2 >= 2) {
0996: int state2 = Base
0997: .StateUpdateMatch(state);
0998:
0999: int posStateNext = (position + lenTest)
1000: & _posStateMask;
1001: int curAndLenCharPrice = curAndLenPrice
1002: + SevenZip.Compression.RangeCoder.Encoder
1003: .GetPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax)
1004: + posStateNext])
1005: + _literalEncoder
1006: .GetSubCoder(
1007: position
1008: + lenTest,
1009: _matchFinder
1010: .GetIndexByte(lenTest - 1 - 1))
1011: .GetPrice(
1012: true,
1013: _matchFinder
1014: .GetIndexByte(lenTest
1015: - (curBack + 1)
1016: - 1),
1017: _matchFinder
1018: .GetIndexByte(lenTest - 1));
1019: state2 = Base.StateUpdateChar(state2);
1020: posStateNext = (position + lenTest + 1)
1021: & _posStateMask;
1022: int nextMatchPrice = curAndLenCharPrice
1023: + SevenZip.Compression.RangeCoder.Encoder
1024: .GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax)
1025: + posStateNext]);
1026: int nextRepMatchPrice = nextMatchPrice
1027: + SevenZip.Compression.RangeCoder.Encoder
1028: .GetPrice1(_isRep[state2]);
1029:
1030: int offset = lenTest + 1 + lenTest2;
1031: while (lenEnd < cur + offset)
1032: _optimum[++lenEnd].Price = kIfinityPrice;
1033: curAndLenPrice = nextRepMatchPrice
1034: + GetRepPrice(0, lenTest2,
1035: state2, posStateNext);
1036: optimum = _optimum[cur + offset];
1037: if (curAndLenPrice < optimum.Price) {
1038: optimum.Price = curAndLenPrice;
1039: optimum.PosPrev = cur + lenTest + 1;
1040: optimum.BackPrev = 0;
1041: optimum.Prev1IsChar = true;
1042: optimum.Prev2 = true;
1043: optimum.PosPrev2 = cur;
1044: optimum.BackPrev2 = curBack
1045: + Base.kNumRepDistances;
1046: }
1047: }
1048: }
1049: offs += 2;
1050: if (offs == numDistancePairs)
1051: break;
1052: }
1053: }
1054: }
1055: }
1056: }
1057:
1058: boolean ChangePair(int smallDist, int bigDist) {
1059: int kDif = 7;
1060: return (smallDist < (1 << (32 - kDif)) && bigDist >= (smallDist << kDif));
1061: }
1062:
1063: void WriteEndMarker(int posState) throws IOException {
1064: if (!_writeEndMark)
1065: return;
1066:
1067: _rangeEncoder.Encode(_isMatch,
1068: (_state << Base.kNumPosStatesBitsMax) + posState, 1);
1069: _rangeEncoder.Encode(_isRep, _state, 0);
1070: _state = Base.StateUpdateMatch(_state);
1071: int len = Base.kMatchMinLen;
1072: _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen,
1073: posState);
1074: int posSlot = (1 << Base.kNumPosSlotBits) - 1;
1075: int lenToPosState = Base.GetLenToPosState(len);
1076: _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot);
1077: int footerBits = 30;
1078: int posReduced = (1 << footerBits) - 1;
1079: _rangeEncoder.EncodeDirectBits(
1080: posReduced >> Base.kNumAlignBits, footerBits
1081: - Base.kNumAlignBits);
1082: _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced
1083: & Base.kAlignMask);
1084: }
1085:
1086: void Flush(int nowPos) throws IOException {
1087: ReleaseMFStream();
1088: WriteEndMarker(nowPos & _posStateMask);
1089: _rangeEncoder.FlushData();
1090: _rangeEncoder.FlushStream();
1091: }
1092:
1093: public void CodeOneBlock(long[] inSize, long[] outSize,
1094: boolean[] finished) throws IOException {
1095: inSize[0] = 0;
1096: outSize[0] = 0;
1097: finished[0] = true;
1098:
1099: if (_inStream != null) {
1100: _matchFinder.SetStream(_inStream);
1101: _matchFinder.Init();
1102: _needReleaseMFStream = true;
1103: _inStream = null;
1104: }
1105:
1106: if (_finished)
1107: return;
1108: _finished = true;
1109:
1110: long progressPosValuePrev = nowPos64;
1111: if (nowPos64 == 0) {
1112: if (_matchFinder.GetNumAvailableBytes() == 0) {
1113: Flush((int) nowPos64);
1114: return;
1115: }
1116:
1117: ReadMatchDistances();
1118: int posState = (int) (nowPos64) & _posStateMask;
1119: _rangeEncoder
1120: .Encode(_isMatch,
1121: (_state << Base.kNumPosStatesBitsMax)
1122: + posState, 0);
1123: _state = Base.StateUpdateChar(_state);
1124: byte curByte = _matchFinder
1125: .GetIndexByte(0 - _additionalOffset);
1126: _literalEncoder
1127: .GetSubCoder((int) (nowPos64), _previousByte)
1128: .Encode(_rangeEncoder, curByte);
1129: _previousByte = curByte;
1130: _additionalOffset--;
1131: nowPos64++;
1132: }
1133: if (_matchFinder.GetNumAvailableBytes() == 0) {
1134: Flush((int) nowPos64);
1135: return;
1136: }
1137: while (true) {
1138:
1139: int len = GetOptimum((int) nowPos64);
1140: int pos = backRes;
1141: int posState = ((int) nowPos64) & _posStateMask;
1142: int complexState = (_state << Base.kNumPosStatesBitsMax)
1143: + posState;
1144: if (len == 1 && pos == -1) {
1145: _rangeEncoder.Encode(_isMatch, complexState, 0);
1146: byte curByte = _matchFinder
1147: .GetIndexByte((0 - _additionalOffset));
1148: LiteralEncoder.Encoder2 subCoder = _literalEncoder
1149: .GetSubCoder((int) nowPos64, _previousByte);
1150: if (!Base.StateIsCharState(_state)) {
1151: byte matchByte = _matchFinder
1152: .GetIndexByte((0 - _repDistances[0] - 1 - _additionalOffset));
1153: subCoder.EncodeMatched(_rangeEncoder, matchByte,
1154: curByte);
1155: } else
1156: subCoder.Encode(_rangeEncoder, curByte);
1157: _previousByte = curByte;
1158: _state = Base.StateUpdateChar(_state);
1159: } else {
1160: _rangeEncoder.Encode(_isMatch, complexState, 1);
1161: if (pos < Base.kNumRepDistances) {
1162: _rangeEncoder.Encode(_isRep, _state, 1);
1163: if (pos == 0) {
1164: _rangeEncoder.Encode(_isRepG0, _state, 0);
1165: if (len == 1)
1166: _rangeEncoder.Encode(_isRep0Long,
1167: complexState, 0);
1168: else
1169: _rangeEncoder.Encode(_isRep0Long,
1170: complexState, 1);
1171: } else {
1172: _rangeEncoder.Encode(_isRepG0, _state, 1);
1173: if (pos == 1)
1174: _rangeEncoder.Encode(_isRepG1, _state, 0);
1175: else {
1176: _rangeEncoder.Encode(_isRepG1, _state, 1);
1177: _rangeEncoder.Encode(_isRepG2, _state,
1178: pos - 2);
1179: }
1180: }
1181: if (len == 1)
1182: _state = Base.StateUpdateShortRep(_state);
1183: else {
1184: _repMatchLenEncoder.Encode(_rangeEncoder, len
1185: - Base.kMatchMinLen, posState);
1186: _state = Base.StateUpdateRep(_state);
1187: }
1188: int distance = _repDistances[pos];
1189: if (pos != 0) {
1190: for (int i = pos; i >= 1; i--)
1191: _repDistances[i] = _repDistances[i - 1];
1192: _repDistances[0] = distance;
1193: }
1194: } else {
1195: _rangeEncoder.Encode(_isRep, _state, 0);
1196: _state = Base.StateUpdateMatch(_state);
1197: _lenEncoder.Encode(_rangeEncoder, len
1198: - Base.kMatchMinLen, posState);
1199: pos -= Base.kNumRepDistances;
1200: int posSlot = GetPosSlot(pos);
1201: int lenToPosState = Base.GetLenToPosState(len);
1202: _posSlotEncoder[lenToPosState].Encode(
1203: _rangeEncoder, posSlot);
1204:
1205: if (posSlot >= Base.kStartPosModelIndex) {
1206: int footerBits = ((posSlot >> 1) - 1);
1207: int baseVal = ((2 | (posSlot & 1)) << footerBits);
1208: int posReduced = pos - baseVal;
1209:
1210: if (posSlot < Base.kEndPosModelIndex)
1211: BitTreeEncoder.ReverseEncode(_posEncoders,
1212: baseVal - posSlot - 1,
1213: _rangeEncoder, footerBits,
1214: posReduced);
1215: else {
1216: _rangeEncoder.EncodeDirectBits(
1217: posReduced >> Base.kNumAlignBits,
1218: footerBits - Base.kNumAlignBits);
1219: _posAlignEncoder.ReverseEncode(
1220: _rangeEncoder, posReduced
1221: & Base.kAlignMask);
1222: _alignPriceCount++;
1223: }
1224: }
1225: int distance = pos;
1226: for (int i = Base.kNumRepDistances - 1; i >= 1; i--)
1227: _repDistances[i] = _repDistances[i - 1];
1228: _repDistances[0] = distance;
1229: _matchPriceCount++;
1230: }
1231: _previousByte = _matchFinder.GetIndexByte(len - 1
1232: - _additionalOffset);
1233: }
1234: _additionalOffset -= len;
1235: nowPos64 += len;
1236: if (_additionalOffset == 0) {
1237: // if (!_fastMode)
1238: if (_matchPriceCount >= (1 << 7))
1239: FillDistancesPrices();
1240: if (_alignPriceCount >= Base.kAlignTableSize)
1241: FillAlignPrices();
1242: inSize[0] = nowPos64;
1243: outSize[0] = _rangeEncoder.GetProcessedSizeAdd();
1244: if (_matchFinder.GetNumAvailableBytes() == 0) {
1245: Flush((int) nowPos64);
1246: return;
1247: }
1248:
1249: if (nowPos64 - progressPosValuePrev >= (1 << 12)) {
1250: _finished = false;
1251: finished[0] = false;
1252: return;
1253: }
1254: }
1255: }
1256: }
1257:
1258: void ReleaseMFStream() {
1259: if (_matchFinder != null && _needReleaseMFStream) {
1260: _matchFinder.ReleaseStream();
1261: _needReleaseMFStream = false;
1262: }
1263: }
1264:
1265: void SetOutStream(java.io.OutputStream outStream) {
1266: _rangeEncoder.SetStream(outStream);
1267: }
1268:
1269: void ReleaseOutStream() {
1270: _rangeEncoder.ReleaseStream();
1271: }
1272:
1273: void ReleaseStreams() {
1274: ReleaseMFStream();
1275: ReleaseOutStream();
1276: }
1277:
1278: void SetStreams(java.io.InputStream inStream,
1279: java.io.OutputStream outStream, long inSize, long outSize) {
1280: _inStream = inStream;
1281: _finished = false;
1282: Create();
1283: SetOutStream(outStream);
1284: Init();
1285:
1286: // if (!_fastMode)
1287: {
1288: FillDistancesPrices();
1289: FillAlignPrices();
1290: }
1291:
1292: _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen);
1293: _lenEncoder.UpdateTables(1 << _posStateBits);
1294: _repMatchLenEncoder.SetTableSize(_numFastBytes + 1
1295: - Base.kMatchMinLen);
1296: _repMatchLenEncoder.UpdateTables(1 << _posStateBits);
1297:
1298: nowPos64 = 0;
1299: }
1300:
1301: long[] processedInSize = new long[1];
1302: long[] processedOutSize = new long[1];
1303: boolean[] finished = new boolean[1];
1304:
1305: public void Code(java.io.InputStream inStream,
1306: java.io.OutputStream outStream, long inSize, long outSize,
1307: ICodeProgress progress) throws IOException {
1308: _needReleaseMFStream = false;
1309: try {
1310: SetStreams(inStream, outStream, inSize, outSize);
1311: while (true) {
1312:
1313: CodeOneBlock(processedInSize, processedOutSize,
1314: finished);
1315: if (finished[0])
1316: return;
1317: if (progress != null) {
1318: progress.SetProgress(processedInSize[0],
1319: processedOutSize[0]);
1320: }
1321: }
1322: } finally {
1323: ReleaseStreams();
1324: }
1325: }
1326:
1327: public static final int kPropSize = 5;
1328: byte[] properties = new byte[kPropSize];
1329:
1330: public void WriteCoderProperties(java.io.OutputStream outStream)
1331: throws IOException {
1332: properties[0] = (byte) ((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits);
1333: for (int i = 0; i < 4; i++)
1334: properties[1 + i] = (byte) (_dictionarySize >> (8 * i));
1335: outStream.write(properties, 0, kPropSize);
1336: }
1337:
1338: int[] tempPrices = new int[Base.kNumFullDistances];
1339: int _matchPriceCount;
1340:
1341: void FillDistancesPrices() {
1342: for (int i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++) {
1343: int posSlot = GetPosSlot(i);
1344: int footerBits = ((posSlot >> 1) - 1);
1345: int baseVal = ((2 | (posSlot & 1)) << footerBits);
1346: tempPrices[i] = BitTreeEncoder.ReverseGetPrice(
1347: _posEncoders, baseVal - posSlot - 1, footerBits, i
1348: - baseVal);
1349: }
1350:
1351: for (int lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) {
1352: int posSlot;
1353: BitTreeEncoder encoder = _posSlotEncoder[lenToPosState];
1354:
1355: int st = (lenToPosState << Base.kNumPosSlotBits);
1356: for (posSlot = 0; posSlot < _distTableSize; posSlot++)
1357: _posSlotPrices[st + posSlot] = encoder
1358: .GetPrice(posSlot);
1359: for (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++)
1360: _posSlotPrices[st + posSlot] += ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << SevenZip.Compression.RangeCoder.Encoder.kNumBitPriceShiftBits);
1361:
1362: int st2 = lenToPosState * Base.kNumFullDistances;
1363: int i;
1364: for (i = 0; i < Base.kStartPosModelIndex; i++)
1365: _distancesPrices[st2 + i] = _posSlotPrices[st + i];
1366: for (; i < Base.kNumFullDistances; i++)
1367: _distancesPrices[st2 + i] = _posSlotPrices[st
1368: + GetPosSlot(i)]
1369: + tempPrices[i];
1370: }
1371: _matchPriceCount = 0;
1372: }
1373:
1374: void FillAlignPrices() {
1375: for (int i = 0; i < Base.kAlignTableSize; i++)
1376: _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i);
1377: _alignPriceCount = 0;
1378: }
1379:
1380: public boolean SetAlgorithm(int algorithm) {
1381: /*
1382: _fastMode = (algorithm == 0);
1383: _maxMode = (algorithm >= 2);
1384: */
1385: return true;
1386: }
1387:
1388: public boolean SetDictionarySize(int dictionarySize) {
1389: int kDicLogSizeMaxCompress = 29;
1390: if (dictionarySize < (1 << Base.kDicLogSizeMin)
1391: || dictionarySize > (1 << kDicLogSizeMaxCompress))
1392: return false;
1393: _dictionarySize = dictionarySize;
1394: int dicLogSize;
1395: for (dicLogSize = 0; dictionarySize > (1 << dicLogSize); dicLogSize++)
1396: ;
1397: _distTableSize = dicLogSize * 2;
1398: return true;
1399: }
1400:
1401: public boolean SeNumFastBytes(int numFastBytes) {
1402: if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen)
1403: return false;
1404: _numFastBytes = numFastBytes;
1405: return true;
1406: }
1407:
1408: public boolean SetMatchFinder(int matchFinderIndex) {
1409: if (matchFinderIndex < 0 || matchFinderIndex > 2)
1410: return false;
1411: int matchFinderIndexPrev = _matchFinderType;
1412: _matchFinderType = matchFinderIndex;
1413: if (_matchFinder != null
1414: && matchFinderIndexPrev != _matchFinderType) {
1415: _dictionarySizePrev = -1;
1416: _matchFinder = null;
1417: }
1418: return true;
1419: }
1420:
1421: public boolean SetLcLpPb(int lc, int lp, int pb) {
1422: if (lp < 0 || lp > Base.kNumLitPosStatesBitsEncodingMax
1423: || lc < 0 || lc > Base.kNumLitContextBitsMax || pb < 0
1424: || pb > Base.kNumPosStatesBitsEncodingMax)
1425: return false;
1426: _numLiteralPosStateBits = lp;
1427: _numLiteralContextBits = lc;
1428: _posStateBits = pb;
1429: _posStateMask = ((1) << _posStateBits) - 1;
1430: return true;
1431: }
1432:
1433: public void SetEndMarkerMode(boolean endMarkerMode) {
1434: _writeEndMark = endMarkerMode;
1435: }
1436: }
|