Skip to content

Package: Encoder

Encoder

nameinstructionbranchcomplexitylinemethod
Encoder()
M: 180 C: 0
0%
M: 4 C: 0
0%
M: 3 C: 0
0%
M: 45 C: 0
0%
M: 1 C: 0
0%
backward(int)
M: 121 C: 0
0%
M: 6 C: 0
0%
M: 4 C: 0
0%
M: 21 C: 0
0%
M: 1 C: 0
0%
baseInit()
M: 19 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 5 C: 0
0%
M: 1 C: 0
0%
changePair(int, int)
M: 18 C: 0
0%
M: 4 C: 0
0%
M: 3 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
code(LZMAEncoder.LZMAOutputState, long, long)
M: 30 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 6 C: 0
0%
M: 1 C: 0
0%
codeOneBlock(long[], long[], boolean[])
M: 542 C: 0
0%
M: 42 C: 0
0%
M: 22 C: 0
0%
M: 104 C: 0
0%
M: 1 C: 0
0%
create()
M: 57 C: 0
0%
M: 8 C: 0
0%
M: 5 C: 0
0%
M: 14 C: 0
0%
M: 1 C: 0
0%
fillAlignPrices()
M: 19 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%
fillDistancesPrices()
M: 149 C: 0
0%
M: 12 C: 0
0%
M: 7 C: 0
0%
M: 19 C: 0
0%
M: 1 C: 0
0%
flush(int)
M: 12 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%
getOptimum(int)
M: 1674 C: 0
0%
M: 152 C: 0
0%
M: 77 C: 0
0%
M: 304 C: 0
0%
M: 1 C: 0
0%
getPosLenPrice(int, int, int)
M: 43 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 5 C: 0
0%
M: 1 C: 0
0%
getPosSlot(int)
M: 26 C: 0
0%
M: 4 C: 0
0%
M: 3 C: 0
0%
M: 5 C: 0
0%
M: 1 C: 0
0%
getPosSlot2(int)
M: 30 C: 0
0%
M: 4 C: 0
0%
M: 3 C: 0
0%
M: 5 C: 0
0%
M: 1 C: 0
0%
getPureRepPrice(int, int, int)
M: 60 C: 0
0%
M: 4 C: 0
0%
M: 3 C: 0
0%
M: 9 C: 0
0%
M: 1 C: 0
0%
getRepLen1Price(int, int)
M: 16 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
getRepPrice(int, int, int, int)
M: 16 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
init()
M: 71 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 20 C: 0
0%
M: 1 C: 0
0%
movePos(int)
M: 13 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%
readMatchDistances()
M: 51 C: 0
0%
M: 4 C: 0
0%
M: 3 C: 0
0%
M: 8 C: 0
0%
M: 1 C: 0
0%
releaseBuffers(LZMAEncoder.LZMAOutputState)
M: 7 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 3 C: 0
0%
M: 1 C: 0
0%
releaseDstBuffer()
M: 4 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
releaseMFBuffer()
M: 13 C: 0
0%
M: 4 C: 0
0%
M: 3 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%
setAlgorithm(int)
M: 2 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
setDictionarySize(int)
M: 31 C: 0
0%
M: 6 C: 0
0%
M: 4 C: 0
0%
M: 7 C: 0
0%
M: 1 C: 0
0%
setDstBuffer(Buffer, MemoryManager)
M: 6 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
setEndMarkerMode(boolean)
M: 4 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
setLcLpPb(int, int, int)
M: 36 C: 0
0%
M: 12 C: 0
0%
M: 7 C: 0
0%
M: 7 C: 0
0%
M: 1 C: 0
0%
setMatchFinder(int)
M: 28 C: 0
0%
M: 8 C: 0
0%
M: 5 C: 0
0%
M: 8 C: 0
0%
M: 1 C: 0
0%
setNumFastBytes(int)
M: 13 C: 0
0%
M: 4 C: 0
0%
M: 3 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%
setStreams(Buffer, Buffer, MemoryManager, long, long)
M: 54 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 13 C: 0
0%
M: 1 C: 0
0%
setWriteEndMarkerMode(boolean)
M: 4 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
static {...}
M: 44 C: 0
0%
M: 4 C: 0
0%
M: 3 C: 0
0%
M: 10 C: 0
0%
M: 1 C: 0
0%
writeCoderProperties(Buffer)
M: 34 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%
writeEndMarker(int)
M: 79 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 15 C: 0
0%
M: 1 C: 0
0%

Coverage

1: /*
2: * Copyright (c) 2011, 2020 Oracle and/or its affiliates. All rights reserved.
3: *
4: * This program and the accompanying materials are made available under the
5: * terms of the Eclipse Public License v. 2.0, which is available at
6: * http://www.eclipse.org/legal/epl-2.0.
7: *
8: * This Source Code may also be made available under the following Secondary
9: * Licenses when the conditions for such availability set forth in the
10: * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
11: * version 2 with the GNU Classpath Exception, which is available at
12: * https://www.gnu.org/software/classpath/license.html.
13: *
14: * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15: */
16:
17: package org.glassfish.grizzly.compression.lzma.impl;
18:
19: import java.io.IOException;
20:
21: import org.glassfish.grizzly.Buffer;
22: import org.glassfish.grizzly.compression.lzma.LZMAEncoder;
23: import org.glassfish.grizzly.compression.lzma.impl.lz.BinTree;
24: import org.glassfish.grizzly.compression.lzma.impl.rangecoder.BitTreeEncoder;
25: import org.glassfish.grizzly.compression.lzma.impl.rangecoder.RangeEncoder;
26: import org.glassfish.grizzly.memory.MemoryManager;
27:
28: /**
29: * RangeEncoder
30: *
31: * @author Igor Pavlov
32: */
33: public class Encoder {
34:
35: public static final int EMatchFinderTypeBT2 = 0;
36: public static final int EMatchFinderTypeBT4 = 1;
37: static final int kIfinityPrice = 0xFFFFFFF;
38: static final byte[] g_FastPos = new byte[1 << 11];
39:
40: static {
41: int kFastSlots = 22;
42: int c = 2;
43: g_FastPos[0] = 0;
44: g_FastPos[1] = 1;
45:• for (int slotFast = 2; slotFast < kFastSlots; slotFast++) {
46: int k = 1 << (slotFast >> 1) - 1;
47:• for (int j = 0; j < k; j++, c++) {
48: g_FastPos[c] = (byte) slotFast;
49: }
50: }
51: }
52:
53: static int getPosSlot(int pos) {
54:• if (pos < 1 << 11) {
55: return g_FastPos[pos];
56: }
57:• if (pos < 1 << 21) {
58: return g_FastPos[pos >> 10] + 20;
59: }
60: return g_FastPos[pos >> 20] + 40;
61: }
62:
63: static int getPosSlot2(int pos) {
64:• if (pos < 1 << 17) {
65: return g_FastPos[pos >> 6] + 12;
66: }
67:• if (pos < 1 << 27) {
68: return g_FastPos[pos >> 16] + 32;
69: }
70: return g_FastPos[pos >> 26] + 52;
71: }
72:
73: int _state = Base.stateInit();
74: byte _previousByte;
75: final int[] _repDistances = new int[Base.kNumRepDistances];
76:
77: void baseInit() {
78: _state = Base.stateInit();
79: _previousByte = 0;
80:• for (int i = 0; i < Base.kNumRepDistances; i++) {
81: _repDistances[i] = 0;
82: }
83: }
84:
85: static final int kDefaultDictionaryLogSize = 22;
86: static final int kNumFastBytesDefault = 0x20;
87:
88: static class LiteralEncoder {
89:
90: static class Encoder2 {
91:
92: final short[] m_Encoders = new short[0x300];
93:
94: public void init() {
95: RangeEncoder.initBitModels(m_Encoders);
96: }
97:
98: public void encode(RangeEncoder rangeEncoder, byte symbol) throws IOException {
99: int context = 1;
100: for (int i = 7; i >= 0; i--) {
101: int bit = symbol >> i & 1;
102: rangeEncoder.encode(m_Encoders, context, bit);
103: context = context << 1 | bit;
104: }
105: }
106:
107: public void encodeMatched(RangeEncoder rangeEncoder, byte matchByte, byte symbol) throws IOException {
108: int context = 1;
109: boolean same = true;
110: for (int i = 7; i >= 0; i--) {
111: int bit = symbol >> i & 1;
112: int state = context;
113: if (same) {
114: int matchBit = matchByte >> i & 1;
115: state += 1 + matchBit << 8;
116: same = matchBit == bit;
117: }
118: rangeEncoder.encode(m_Encoders, state, bit);
119: context = context << 1 | bit;
120: }
121: }
122:
123: public int getPrice(boolean matchMode, byte matchByte, byte symbol) {
124: int price = 0;
125: int context = 1;
126: int i = 7;
127: if (matchMode) {
128: for (; i >= 0; i--) {
129: int matchBit = matchByte >> i & 1;
130: int bit = symbol >> i & 1;
131: price += RangeEncoder.getPrice(m_Encoders[(1 + matchBit << 8) + context], bit);
132: context = context << 1 | bit;
133: if (matchBit != bit) {
134: i--;
135: break;
136: }
137: }
138: }
139: for (; i >= 0; i--) {
140: int bit = symbol >> i & 1;
141: price += RangeEncoder.getPrice(m_Encoders[context], bit);
142: context = context << 1 | bit;
143: }
144: return price;
145: }
146: }
147:
148: Encoder2[] m_Coders;
149: int m_NumPrevBits;
150: int m_NumPosBits;
151: int m_PosMask;
152:
153: public void create(int numPosBits, int numPrevBits) {
154: if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) {
155: return;
156: }
157: m_NumPosBits = numPosBits;
158: m_PosMask = (1 << numPosBits) - 1;
159: m_NumPrevBits = numPrevBits;
160: int numStates = 1 << m_NumPrevBits + m_NumPosBits;
161: m_Coders = new Encoder2[numStates];
162: for (int i = 0; i < numStates; i++) {
163: m_Coders[i] = new Encoder2();
164: }
165: }
166:
167: public void init() {
168: int numStates = 1 << m_NumPrevBits + m_NumPosBits;
169: for (int i = 0; i < numStates; i++) {
170: m_Coders[i].init();
171: }
172: }
173:
174: public Encoder2 getSubCoder(int pos, byte prevByte) {
175: return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + ((prevByte & 0xFF) >>> 8 - m_NumPrevBits)];
176: }
177: }
178:
179: static class LenEncoder {
180:
181: final short[] _choice = new short[2];
182: final BitTreeEncoder[] _lowCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax];
183: final BitTreeEncoder[] _midCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax];
184: final BitTreeEncoder _highCoder = new BitTreeEncoder(Base.kNumHighLenBits);
185:
186: public LenEncoder() {
187: for (int posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++) {
188: _lowCoder[posState] = new BitTreeEncoder(Base.kNumLowLenBits);
189: _midCoder[posState] = new BitTreeEncoder(Base.kNumMidLenBits);
190: }
191: }
192:
193: public void init(int numPosStates) {
194: RangeEncoder.initBitModels(_choice);
195:
196: for (int posState = 0; posState < numPosStates; posState++) {
197: _lowCoder[posState].init();
198: _midCoder[posState].init();
199: }
200: _highCoder.init();
201: }
202:
203: public void encode(RangeEncoder rangeEncoder, int symbol, int posState) throws IOException {
204: if (symbol < Base.kNumLowLenSymbols) {
205: rangeEncoder.encode(_choice, 0, 0);
206: _lowCoder[posState].encode(rangeEncoder, symbol);
207: } else {
208: symbol -= Base.kNumLowLenSymbols;
209: rangeEncoder.encode(_choice, 0, 1);
210: if (symbol < Base.kNumMidLenSymbols) {
211: rangeEncoder.encode(_choice, 1, 0);
212: _midCoder[posState].encode(rangeEncoder, symbol);
213: } else {
214: rangeEncoder.encode(_choice, 1, 1);
215: _highCoder.encode(rangeEncoder, symbol - Base.kNumMidLenSymbols);
216: }
217: }
218: }
219:
220: public void setPrices(int posState, int numSymbols, int[] prices, int st) {
221: int a0 = RangeEncoder.getPrice0(_choice[0]);
222: int a1 = RangeEncoder.getPrice1(_choice[0]);
223: int b0 = a1 + RangeEncoder.getPrice0(_choice[1]);
224: int b1 = a1 + RangeEncoder.getPrice1(_choice[1]);
225: int i;
226: for (i = 0; i < Base.kNumLowLenSymbols; i++) {
227: if (i >= numSymbols) {
228: return;
229: }
230: prices[st + i] = a0 + _lowCoder[posState].getPrice(i);
231: }
232: for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++) {
233: if (i >= numSymbols) {
234: return;
235: }
236: prices[st + i] = b0 + _midCoder[posState].getPrice(i - Base.kNumLowLenSymbols);
237: }
238: for (; i < numSymbols; i++) {
239: prices[st + i] = b1 + _highCoder.getPrice(i - Base.kNumLowLenSymbols - Base.kNumMidLenSymbols);
240: }
241: }
242: }
243:
244: public static final int kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols;
245:
246: static class LenPriceTableEncoder extends LenEncoder {
247:
248: final int[] _prices = new int[Base.kNumLenSymbols << Base.kNumPosStatesBitsEncodingMax];
249: int _tableSize;
250: final int[] _counters = new int[Base.kNumPosStatesEncodingMax];
251:
252: public void setTableSize(int tableSize) {
253: _tableSize = tableSize;
254: }
255:
256: public int getPrice(int symbol, int posState) {
257: return _prices[posState * Base.kNumLenSymbols + symbol];
258: }
259:
260: void updateTable(int posState) {
261: setPrices(posState, _tableSize, _prices, posState * Base.kNumLenSymbols);
262: _counters[posState] = _tableSize;
263: }
264:
265: public void updateTables(int numPosStates) {
266: for (int posState = 0; posState < numPosStates; posState++) {
267: updateTable(posState);
268: }
269: }
270:
271: @Override
272: public void encode(RangeEncoder rangeEncoder, int symbol, int posState) throws IOException {
273: super.encode(rangeEncoder, symbol, posState);
274: if (--_counters[posState] == 0) {
275: updateTable(posState);
276: }
277: }
278: }
279:
280: static final int kNumOpts = 1 << 12;
281:
282: static class Optimal {
283:
284: public int State;
285: public boolean Prev1IsChar;
286: public boolean Prev2;
287: public int PosPrev2;
288: public int BackPrev2;
289: public int Price;
290: public int PosPrev;
291: public int BackPrev;
292: public int Backs0;
293: public int Backs1;
294: public int Backs2;
295: public int Backs3;
296:
297: public void makeAsChar() {
298: BackPrev = -1;
299: Prev1IsChar = false;
300: }
301:
302: public void makeAsShortRep() {
303: BackPrev = 0;
304: Prev1IsChar = false;
305: }
306:
307: public boolean isShortRep() {
308: return BackPrev == 0;
309: }
310: }
311:
312: final Optimal[] _optimum = new Optimal[kNumOpts];
313: BinTree _matchFinder = null;
314: final RangeEncoder _rangeEncoder = new RangeEncoder();
315: final short[] _isMatch = new short[Base.kNumStates << Base.kNumPosStatesBitsMax];
316: final short[] _isRep = new short[Base.kNumStates];
317: final short[] _isRepG0 = new short[Base.kNumStates];
318: final short[] _isRepG1 = new short[Base.kNumStates];
319: final short[] _isRepG2 = new short[Base.kNumStates];
320: final short[] _isRep0Long = new short[Base.kNumStates << Base.kNumPosStatesBitsMax];
321: final BitTreeEncoder[] _posSlotEncoder = new BitTreeEncoder[Base.kNumLenToPosStates]; // kNumPosSlotBits
322: final short[] _posEncoders = new short[Base.kNumFullDistances - Base.kEndPosModelIndex];
323: final BitTreeEncoder _posAlignEncoder = new BitTreeEncoder(Base.kNumAlignBits);
324: final LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder();
325: final LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder();
326: final LiteralEncoder _literalEncoder = new LiteralEncoder();
327: final int[] _matchDistances = new int[Base.kMatchMaxLen * 2 + 2];
328: int _numFastBytes = kNumFastBytesDefault;
329: int _longestMatchLength;
330: int _numDistancePairs;
331: int _additionalOffset;
332: int _optimumEndIndex;
333: int _optimumCurrentIndex;
334: boolean _longestMatchWasFound;
335: final int[] _posSlotPrices = new int[1 << Base.kNumPosSlotBits + Base.kNumLenToPosStatesBits];
336: final int[] _distancesPrices = new int[Base.kNumFullDistances << Base.kNumLenToPosStatesBits];
337: final int[] _alignPrices = new int[Base.kAlignTableSize];
338: int _alignPriceCount;
339: int _distTableSize = kDefaultDictionaryLogSize * 2;
340: int _posStateBits = 2;
341: int _posStateMask = 4 - 1;
342: int _numLiteralPosStateBits = 0;
343: int _numLiteralContextBits = 3;
344: int _dictionarySize = 1 << kDefaultDictionaryLogSize;
345: int _dictionarySizePrev = -1;
346: int _numFastBytesPrev = -1;
347: long nowPos64;
348: boolean _finished;
349: Buffer _src;
350: int _matchFinderType = EMatchFinderTypeBT4;
351: boolean _writeEndMark = false;
352: boolean _needReleaseMFStream = false;
353:
354: void create() {
355:• if (_matchFinder == null) {
356: BinTree bt = new BinTree();
357: int numHashBytes = 4;
358:• if (_matchFinderType == EMatchFinderTypeBT2) {
359: numHashBytes = 2;
360: }
361: bt.setType(numHashBytes);
362: _matchFinder = bt;
363: }
364: _literalEncoder.create(_numLiteralPosStateBits, _numLiteralContextBits);
365:
366:• if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes) {
367: return;
368: }
369: _matchFinder.create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen + 1);
370: _dictionarySizePrev = _dictionarySize;
371: _numFastBytesPrev = _numFastBytes;
372: }
373:
374: public Encoder() {
375:• for (int i = 0; i < kNumOpts; i++) {
376: _optimum[i] = new Optimal();
377: }
378:• for (int i = 0; i < Base.kNumLenToPosStates; i++) {
379: _posSlotEncoder[i] = new BitTreeEncoder(Base.kNumPosSlotBits);
380: }
381: }
382:
383: void setWriteEndMarkerMode(boolean writeEndMarker) {
384: _writeEndMark = writeEndMarker;
385: }
386:
387: void init() {
388: baseInit();
389: _rangeEncoder.init();
390:
391: RangeEncoder.initBitModels(_isMatch);
392: RangeEncoder.initBitModels(_isRep0Long);
393: RangeEncoder.initBitModels(_isRep);
394: RangeEncoder.initBitModels(_isRepG0);
395: RangeEncoder.initBitModels(_isRepG1);
396: RangeEncoder.initBitModels(_isRepG2);
397: RangeEncoder.initBitModels(_posEncoders);
398:
399: _literalEncoder.init();
400:• for (int i = 0; i < Base.kNumLenToPosStates; i++) {
401: _posSlotEncoder[i].init();
402: }
403:
404: _lenEncoder.init(1 << _posStateBits);
405: _repMatchLenEncoder.init(1 << _posStateBits);
406:
407: _posAlignEncoder.init();
408:
409: _longestMatchWasFound = false;
410: _optimumEndIndex = 0;
411: _optimumCurrentIndex = 0;
412: _additionalOffset = 0;
413: }
414:
415: int readMatchDistances() throws java.io.IOException {
416: int lenRes = 0;
417: _numDistancePairs = _matchFinder.getMatches(_matchDistances);
418:• if (_numDistancePairs > 0) {
419: lenRes = _matchDistances[_numDistancePairs - 2];
420:• if (lenRes == _numFastBytes) {
421: lenRes += _matchFinder.getMatchLen(lenRes - 1, _matchDistances[_numDistancePairs - 1], Base.kMatchMaxLen - lenRes);
422: }
423: }
424: _additionalOffset++;
425: return lenRes;
426: }
427:
428: void movePos(int num) throws java.io.IOException {
429:• if (num > 0) {
430: _matchFinder.skip(num);
431: _additionalOffset += num;
432: }
433: }
434:
435: int getRepLen1Price(int state, int posState) {
436: return RangeEncoder.getPrice0(_isRepG0[state]) + RangeEncoder.getPrice0(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]);
437: }
438:
439: int getPureRepPrice(int repIndex, int state, int posState) {
440: int price;
441:• if (repIndex == 0) {
442: price = RangeEncoder.getPrice0(_isRepG0[state]);
443: price += RangeEncoder.getPrice1(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]);
444: } else {
445: price = RangeEncoder.getPrice1(_isRepG0[state]);
446:• if (repIndex == 1) {
447: price += RangeEncoder.getPrice0(_isRepG1[state]);
448: } else {
449: price += RangeEncoder.getPrice1(_isRepG1[state]);
450: price += RangeEncoder.getPrice(_isRepG2[state], repIndex - 2);
451: }
452: }
453: return price;
454: }
455:
456: int getRepPrice(int repIndex, int len, int state, int posState) {
457: int price = _repMatchLenEncoder.getPrice(len - Base.kMatchMinLen, posState);
458: return price + getPureRepPrice(repIndex, state, posState);
459: }
460:
461: int getPosLenPrice(int pos, int len, int posState) {
462: int price;
463: int lenToPosState = Base.getLenToPosState(len);
464:• if (pos < Base.kNumFullDistances) {
465: price = _distancesPrices[lenToPosState * Base.kNumFullDistances + pos];
466: } else {
467: price = _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits) + getPosSlot2(pos)] + _alignPrices[pos & Base.kAlignMask];
468: }
469: return price + _lenEncoder.getPrice(len - Base.kMatchMinLen, posState);
470: }
471:
472: int backward(int cur) {
473: _optimumEndIndex = cur;
474: int posMem = _optimum[cur].PosPrev;
475: int backMem = _optimum[cur].BackPrev;
476: do {
477:• if (_optimum[cur].Prev1IsChar) {
478: _optimum[posMem].makeAsChar();
479: _optimum[posMem].PosPrev = posMem - 1;
480:• if (_optimum[cur].Prev2) {
481: _optimum[posMem - 1].Prev1IsChar = false;
482: _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2;
483: _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2;
484: }
485: }
486: int posPrev = posMem;
487: int backCur = backMem;
488:
489: backMem = _optimum[posPrev].BackPrev;
490: posMem = _optimum[posPrev].PosPrev;
491:
492: _optimum[posPrev].BackPrev = backCur;
493: _optimum[posPrev].PosPrev = cur;
494: cur = posPrev;
495:• } while (cur > 0);
496: backRes = _optimum[0].BackPrev;
497: _optimumCurrentIndex = _optimum[0].PosPrev;
498: return _optimumCurrentIndex;
499: }
500:
501: final int[] reps = new int[Base.kNumRepDistances];
502: final int[] repLens = new int[Base.kNumRepDistances];
503: int backRes;
504:
505: int getOptimum(int position) throws IOException {
506:• if (_optimumEndIndex != _optimumCurrentIndex) {
507: int lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex;
508: backRes = _optimum[_optimumCurrentIndex].BackPrev;
509: _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev;
510: return lenRes;
511: }
512: _optimumCurrentIndex = _optimumEndIndex = 0;
513:
514: int lenMain, numDistancePairs;
515:• if (!_longestMatchWasFound) {
516: lenMain = readMatchDistances();
517: } else {
518: lenMain = _longestMatchLength;
519: _longestMatchWasFound = false;
520: }
521: numDistancePairs = _numDistancePairs;
522:
523: int numAvailableBytes = _matchFinder.getNumAvailableBytes() + 1;
524:• if (numAvailableBytes < 2) {
525: backRes = -1;
526: return 1;
527: }
528:• if (numAvailableBytes > Base.kMatchMaxLen) {
529: numAvailableBytes = Base.kMatchMaxLen;
530: }
531:
532: int repMaxIndex = 0;
533: int i;
534:• for (i = 0; i < Base.kNumRepDistances; i++) {
535: reps[i] = _repDistances[i];
536: repLens[i] = _matchFinder.getMatchLen(0 - 1, reps[i], Base.kMatchMaxLen);
537:• if (repLens[i] > repLens[repMaxIndex]) {
538: repMaxIndex = i;
539: }
540: }
541:• if (repLens[repMaxIndex] >= _numFastBytes) {
542: backRes = repMaxIndex;
543: int lenRes = repLens[repMaxIndex];
544: movePos(lenRes - 1);
545: return lenRes;
546: }
547:
548:• if (lenMain >= _numFastBytes) {
549: backRes = _matchDistances[numDistancePairs - 1] + Base.kNumRepDistances;
550: movePos(lenMain - 1);
551: return lenMain;
552: }
553:
554: byte currentByte = _matchFinder.getIndexByte(0 - 1);
555: byte matchByte = _matchFinder.getIndexByte(0 - _repDistances[0] - 1 - 1);
556:
557:• if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2) {
558: backRes = -1;
559: return 1;
560: }
561:
562: _optimum[0].State = _state;
563:
564: int posState = position & _posStateMask;
565:
566: _optimum[1].Price = RangeEncoder.getPrice0(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState])
567:• + _literalEncoder.getSubCoder(position, _previousByte).getPrice(!Base.stateIsCharState(_state), matchByte, currentByte);
568: _optimum[1].makeAsChar();
569:
570: int matchPrice = RangeEncoder.getPrice1(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]);
571: int repMatchPrice = matchPrice + RangeEncoder.getPrice1(_isRep[_state]);
572:
573:• if (matchByte == currentByte) {
574: int shortRepPrice = repMatchPrice + getRepLen1Price(_state, posState);
575:• if (shortRepPrice < _optimum[1].Price) {
576: _optimum[1].Price = shortRepPrice;
577: _optimum[1].makeAsShortRep();
578: }
579: }
580:
581:• int lenEnd = lenMain >= repLens[repMaxIndex] ? lenMain : repLens[repMaxIndex];
582:
583:• if (lenEnd < 2) {
584: backRes = _optimum[1].BackPrev;
585: return 1;
586: }
587:
588: _optimum[1].PosPrev = 0;
589:
590: _optimum[0].Backs0 = reps[0];
591: _optimum[0].Backs1 = reps[1];
592: _optimum[0].Backs2 = reps[2];
593: _optimum[0].Backs3 = reps[3];
594:
595: int len = lenEnd;
596: do {
597: _optimum[len--].Price = kIfinityPrice;
598:• } while (len >= 2);
599:
600:• for (i = 0; i < Base.kNumRepDistances; i++) {
601: int repLen = repLens[i];
602:• if (repLen < 2) {
603: continue;
604: }
605: int price = repMatchPrice + getPureRepPrice(i, _state, posState);
606: do {
607: int curAndLenPrice = price + _repMatchLenEncoder.getPrice(repLen - 2, posState);
608: Optimal optimum = _optimum[repLen];
609:• if (curAndLenPrice < optimum.Price) {
610: optimum.Price = curAndLenPrice;
611: optimum.PosPrev = 0;
612: optimum.BackPrev = i;
613: optimum.Prev1IsChar = false;
614: }
615:• } while (--repLen >= 2);
616: }
617:
618: int normalMatchPrice = matchPrice + RangeEncoder.getPrice0(_isRep[_state]);
619:
620:• len = repLens[0] >= 2 ? repLens[0] + 1 : 2;
621:• if (len <= lenMain) {
622: int offs = 0;
623:• while (len > _matchDistances[offs]) {
624: offs += 2;
625: }
626: for (;; len++) {
627: int distance = _matchDistances[offs + 1];
628: int curAndLenPrice = normalMatchPrice + getPosLenPrice(distance, len, posState);
629: Optimal optimum = _optimum[len];
630:• if (curAndLenPrice < optimum.Price) {
631: optimum.Price = curAndLenPrice;
632: optimum.PosPrev = 0;
633: optimum.BackPrev = distance + Base.kNumRepDistances;
634: optimum.Prev1IsChar = false;
635: }
636:• if (len == _matchDistances[offs]) {
637: offs += 2;
638:• if (offs == numDistancePairs) {
639: break;
640: }
641: }
642: }
643: }
644:
645: int cur = 0;
646:
647: while (true) {
648: cur++;
649:• if (cur == lenEnd) {
650: return backward(cur);
651: }
652: int newLen = readMatchDistances();
653: numDistancePairs = _numDistancePairs;
654:• if (newLen >= _numFastBytes) {
655:
656: _longestMatchLength = newLen;
657: _longestMatchWasFound = true;
658: return backward(cur);
659: }
660: position++;
661: int posPrev = _optimum[cur].PosPrev;
662: int state;
663:• if (_optimum[cur].Prev1IsChar) {
664: posPrev--;
665:• if (_optimum[cur].Prev2) {
666: state = _optimum[_optimum[cur].PosPrev2].State;
667:• if (_optimum[cur].BackPrev2 < Base.kNumRepDistances) {
668: state = Base.stateUpdateRep(state);
669: } else {
670: state = Base.stateUpdateMatch(state);
671: }
672: } else {
673: state = _optimum[posPrev].State;
674: }
675: state = Base.stateUpdateChar(state);
676: } else {
677: state = _optimum[posPrev].State;
678: }
679:• if (posPrev == cur - 1) {
680:• if (_optimum[cur].isShortRep()) {
681: state = Base.stateUpdateShortRep(state);
682: } else {
683: state = Base.stateUpdateChar(state);
684: }
685: } else {
686: int pos;
687:• if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2) {
688: posPrev = _optimum[cur].PosPrev2;
689: pos = _optimum[cur].BackPrev2;
690: state = Base.stateUpdateRep(state);
691: } else {
692: pos = _optimum[cur].BackPrev;
693:• if (pos < Base.kNumRepDistances) {
694: state = Base.stateUpdateRep(state);
695: } else {
696: state = Base.stateUpdateMatch(state);
697: }
698: }
699: Optimal opt = _optimum[posPrev];
700:• if (pos < Base.kNumRepDistances) {
701:• if (pos == 0) {
702: reps[0] = opt.Backs0;
703: reps[1] = opt.Backs1;
704: reps[2] = opt.Backs2;
705: reps[3] = opt.Backs3;
706:• } else if (pos == 1) {
707: reps[0] = opt.Backs1;
708: reps[1] = opt.Backs0;
709: reps[2] = opt.Backs2;
710: reps[3] = opt.Backs3;
711:• } else if (pos == 2) {
712: reps[0] = opt.Backs2;
713: reps[1] = opt.Backs0;
714: reps[2] = opt.Backs1;
715: reps[3] = opt.Backs3;
716: } else {
717: reps[0] = opt.Backs3;
718: reps[1] = opt.Backs0;
719: reps[2] = opt.Backs1;
720: reps[3] = opt.Backs2;
721: }
722: } else {
723: reps[0] = pos - Base.kNumRepDistances;
724: reps[1] = opt.Backs0;
725: reps[2] = opt.Backs1;
726: reps[3] = opt.Backs2;
727: }
728: }
729: _optimum[cur].State = state;
730: _optimum[cur].Backs0 = reps[0];
731: _optimum[cur].Backs1 = reps[1];
732: _optimum[cur].Backs2 = reps[2];
733: _optimum[cur].Backs3 = reps[3];
734: int curPrice = _optimum[cur].Price;
735:
736: currentByte = _matchFinder.getIndexByte(0 - 1);
737: matchByte = _matchFinder.getIndexByte(0 - reps[0] - 1 - 1);
738:
739: posState = position & _posStateMask;
740:
741: int curAnd1Price = curPrice + RangeEncoder.getPrice0(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState])
742:• + _literalEncoder.getSubCoder(position, _matchFinder.getIndexByte(0 - 2)).getPrice(!Base.stateIsCharState(state), matchByte, currentByte);
743:
744: Optimal nextOptimum = _optimum[cur + 1];
745:
746: boolean nextIsChar = false;
747:• if (curAnd1Price < nextOptimum.Price) {
748: nextOptimum.Price = curAnd1Price;
749: nextOptimum.PosPrev = cur;
750: nextOptimum.makeAsChar();
751: nextIsChar = true;
752: }
753:
754: matchPrice = curPrice + RangeEncoder.getPrice1(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]);
755: repMatchPrice = matchPrice + RangeEncoder.getPrice1(_isRep[state]);
756:
757:• if (matchByte == currentByte && !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) {
758: int shortRepPrice = repMatchPrice + getRepLen1Price(state, posState);
759:• if (shortRepPrice <= nextOptimum.Price) {
760: nextOptimum.Price = shortRepPrice;
761: nextOptimum.PosPrev = cur;
762: nextOptimum.makeAsShortRep();
763: nextIsChar = true;
764: }
765: }
766:
767: int numAvailableBytesFull = _matchFinder.getNumAvailableBytes() + 1;
768: numAvailableBytesFull = Math.min(kNumOpts - 1 - cur, numAvailableBytesFull);
769: numAvailableBytes = numAvailableBytesFull;
770:
771:• if (numAvailableBytes < 2) {
772: continue;
773: }
774:• if (numAvailableBytes > _numFastBytes) {
775: numAvailableBytes = _numFastBytes;
776: }
777:• if (!nextIsChar && matchByte != currentByte) {
778: // try Literal + rep0
779: int t = Math.min(numAvailableBytesFull - 1, _numFastBytes);
780: int lenTest2 = _matchFinder.getMatchLen(0, reps[0], t);
781:• if (lenTest2 >= 2) {
782: int state2 = Base.stateUpdateChar(state);
783:
784: int posStateNext = position + 1 & _posStateMask;
785: int nextRepMatchPrice = curAnd1Price + RangeEncoder.getPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext])
786: + RangeEncoder.getPrice1(_isRep[state2]);
787: {
788: int offset = cur + 1 + lenTest2;
789:• while (lenEnd < offset) {
790: _optimum[++lenEnd].Price = kIfinityPrice;
791: }
792: int curAndLenPrice = nextRepMatchPrice + getRepPrice(0, lenTest2, state2, posStateNext);
793: Optimal optimum = _optimum[offset];
794:• if (curAndLenPrice < optimum.Price) {
795: optimum.Price = curAndLenPrice;
796: optimum.PosPrev = cur + 1;
797: optimum.BackPrev = 0;
798: optimum.Prev1IsChar = true;
799: optimum.Prev2 = false;
800: }
801: }
802: }
803: }
804:
805: int startLen = 2; // speed optimization
806:
807:• for (int repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++) {
808: int lenTest = _matchFinder.getMatchLen(0 - 1, reps[repIndex], numAvailableBytes);
809:• if (lenTest < 2) {
810: continue;
811: }
812: int lenTestTemp = lenTest;
813: do {
814:• while (lenEnd < cur + lenTest) {
815: _optimum[++lenEnd].Price = kIfinityPrice;
816: }
817: int curAndLenPrice = repMatchPrice + getRepPrice(repIndex, lenTest, state, posState);
818: Optimal optimum = _optimum[cur + lenTest];
819:• if (curAndLenPrice < optimum.Price) {
820: optimum.Price = curAndLenPrice;
821: optimum.PosPrev = cur;
822: optimum.BackPrev = repIndex;
823: optimum.Prev1IsChar = false;
824: }
825:• } while (--lenTest >= 2);
826: lenTest = lenTestTemp;
827:
828:• if (repIndex == 0) {
829: startLen = lenTest + 1;
830: }
831:
832: // if (_maxMode)
833:• if (lenTest < numAvailableBytesFull) {
834: int t = Math.min(numAvailableBytesFull - 1 - lenTest, _numFastBytes);
835: int lenTest2 = _matchFinder.getMatchLen(lenTest, reps[repIndex], t);
836:• if (lenTest2 >= 2) {
837: int state2 = Base.stateUpdateRep(state);
838:
839: int posStateNext = position + lenTest & _posStateMask;
840: int curAndLenCharPrice = repMatchPrice + getRepPrice(repIndex, lenTest, state, posState)
841: + RangeEncoder.getPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext])
842: + _literalEncoder.getSubCoder(position + lenTest, _matchFinder.getIndexByte(lenTest - 1 - 1)).getPrice(true,
843: _matchFinder.getIndexByte(lenTest - 1 - (reps[repIndex] + 1)), _matchFinder.getIndexByte(lenTest - 1));
844: state2 = Base.stateUpdateChar(state2);
845: posStateNext = position + lenTest + 1 & _posStateMask;
846: int nextMatchPrice = curAndLenCharPrice + RangeEncoder.getPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]);
847: int nextRepMatchPrice = nextMatchPrice + RangeEncoder.getPrice1(_isRep[state2]);
848:
849: // for(; lenTest2 >= 2; lenTest2--)
850: {
851: int offset = lenTest + 1 + lenTest2;
852:• while (lenEnd < cur + offset) {
853: _optimum[++lenEnd].Price = kIfinityPrice;
854: }
855: int curAndLenPrice = nextRepMatchPrice + getRepPrice(0, lenTest2, state2, posStateNext);
856: Optimal optimum = _optimum[cur + offset];
857:• if (curAndLenPrice < optimum.Price) {
858: optimum.Price = curAndLenPrice;
859: optimum.PosPrev = cur + lenTest + 1;
860: optimum.BackPrev = 0;
861: optimum.Prev1IsChar = true;
862: optimum.Prev2 = true;
863: optimum.PosPrev2 = cur;
864: optimum.BackPrev2 = repIndex;
865: }
866: }
867: }
868: }
869: }
870:
871:• if (newLen > numAvailableBytes) {
872: newLen = numAvailableBytes;
873:• for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2) {
874: ;
875: }
876: _matchDistances[numDistancePairs] = newLen;
877: numDistancePairs += 2;
878: }
879:• if (newLen >= startLen) {
880: normalMatchPrice = matchPrice + RangeEncoder.getPrice0(_isRep[state]);
881:• while (lenEnd < cur + newLen) {
882: _optimum[++lenEnd].Price = kIfinityPrice;
883: }
884:
885: int offs = 0;
886:• while (startLen > _matchDistances[offs]) {
887: offs += 2;
888: }
889:
890: for (int lenTest = startLen;; lenTest++) {
891: int curBack = _matchDistances[offs + 1];
892: int curAndLenPrice = normalMatchPrice + getPosLenPrice(curBack, lenTest, posState);
893: Optimal optimum = _optimum[cur + lenTest];
894:• if (curAndLenPrice < optimum.Price) {
895: optimum.Price = curAndLenPrice;
896: optimum.PosPrev = cur;
897: optimum.BackPrev = curBack + Base.kNumRepDistances;
898: optimum.Prev1IsChar = false;
899: }
900:
901:• if (lenTest == _matchDistances[offs]) {
902:• if (lenTest < numAvailableBytesFull) {
903: int t = Math.min(numAvailableBytesFull - 1 - lenTest, _numFastBytes);
904: int lenTest2 = _matchFinder.getMatchLen(lenTest, curBack, t);
905:• if (lenTest2 >= 2) {
906: int state2 = Base.stateUpdateMatch(state);
907:
908: int posStateNext = position + lenTest & _posStateMask;
909: int curAndLenCharPrice = curAndLenPrice + RangeEncoder.getPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext])
910: + _literalEncoder.getSubCoder(position + lenTest, _matchFinder.getIndexByte(lenTest - 1 - 1)).getPrice(true,
911: _matchFinder.getIndexByte(lenTest - (curBack + 1) - 1), _matchFinder.getIndexByte(lenTest - 1));
912: state2 = Base.stateUpdateChar(state2);
913: posStateNext = position + lenTest + 1 & _posStateMask;
914: int nextMatchPrice = curAndLenCharPrice
915: + RangeEncoder.getPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]);
916: int nextRepMatchPrice = nextMatchPrice + RangeEncoder.getPrice1(_isRep[state2]);
917:
918: int offset = lenTest + 1 + lenTest2;
919:• while (lenEnd < cur + offset) {
920: _optimum[++lenEnd].Price = kIfinityPrice;
921: }
922: curAndLenPrice = nextRepMatchPrice + getRepPrice(0, lenTest2, state2, posStateNext);
923: optimum = _optimum[cur + offset];
924:• if (curAndLenPrice < optimum.Price) {
925: optimum.Price = curAndLenPrice;
926: optimum.PosPrev = cur + lenTest + 1;
927: optimum.BackPrev = 0;
928: optimum.Prev1IsChar = true;
929: optimum.Prev2 = true;
930: optimum.PosPrev2 = cur;
931: optimum.BackPrev2 = curBack + Base.kNumRepDistances;
932: }
933: }
934: }
935: offs += 2;
936:• if (offs == numDistancePairs) {
937: break;
938: }
939: }
940: }
941: }
942: }
943: }
944:
945: boolean changePair(int smallDist, int bigDist) {
946: int kDif = 7;
947:• return smallDist < 1 << 32 - kDif && bigDist >= smallDist << kDif;
948: }
949:
950: void writeEndMarker(int posState) throws IOException {
951:• if (!_writeEndMark) {
952: return;
953: }
954: _rangeEncoder.encode(_isMatch, (_state << Base.kNumPosStatesBitsMax) + posState, 1);
955: _rangeEncoder.encode(_isRep, _state, 0);
956: _state = Base.stateUpdateMatch(_state);
957: int len = Base.kMatchMinLen;
958: _lenEncoder.encode(_rangeEncoder, len - Base.kMatchMinLen, posState);
959: int posSlot = (1 << Base.kNumPosSlotBits) - 1;
960: int lenToPosState = Base.getLenToPosState(len);
961: _posSlotEncoder[lenToPosState].encode(_rangeEncoder, posSlot);
962: int footerBits = 30;
963: int posReduced = (1 << footerBits) - 1;
964: _rangeEncoder.encodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits);
965: _posAlignEncoder.reverseEncode(_rangeEncoder, posReduced & Base.kAlignMask);
966: }
967:
968: void flush(int nowPos) throws IOException {
969: releaseMFBuffer();
970: writeEndMarker(nowPos & _posStateMask);
971: _rangeEncoder.flushData();
972: }
973:
974: public void codeOneBlock(long[] inSize, long[] outSize, boolean[] finished) throws IOException {
975: inSize[0] = 0;
976: outSize[0] = 0;
977: finished[0] = true;
978:
979:• if (_src != null) {
980: _matchFinder.setBuffer(_src);
981: _matchFinder.init();
982: _needReleaseMFStream = true;
983: _src = null;
984: }
985:
986:• if (_finished) {
987: return;
988: }
989: _finished = true;
990:
991: long progressPosValuePrev = nowPos64;
992:• if (nowPos64 == 0) {
993:• if (_matchFinder.getNumAvailableBytes() == 0) {
994: flush((int) nowPos64);
995: return;
996: }
997:
998: readMatchDistances();
999: int posState = (int) nowPos64 & _posStateMask;
1000: _rangeEncoder.encode(_isMatch, (_state << Base.kNumPosStatesBitsMax) + posState, 0);
1001: _state = Base.stateUpdateChar(_state);
1002: byte curByte = _matchFinder.getIndexByte(0 - _additionalOffset);
1003: _literalEncoder.getSubCoder((int) nowPos64, _previousByte).encode(_rangeEncoder, curByte);
1004: _previousByte = curByte;
1005: _additionalOffset--;
1006: nowPos64++;
1007: }
1008:• if (_matchFinder.getNumAvailableBytes() == 0) {
1009: flush((int) nowPos64);
1010: return;
1011: }
1012: while (true) {
1013:
1014: int len = getOptimum((int) nowPos64);
1015: int pos = backRes;
1016: int posState = (int) nowPos64 & _posStateMask;
1017: int complexState = (_state << Base.kNumPosStatesBitsMax) + posState;
1018:• if (len == 1 && pos == -1) {
1019: _rangeEncoder.encode(_isMatch, complexState, 0);
1020: byte curByte = _matchFinder.getIndexByte(0 - _additionalOffset);
1021: LiteralEncoder.Encoder2 subCoder = _literalEncoder.getSubCoder((int) nowPos64, _previousByte);
1022:• if (!Base.stateIsCharState(_state)) {
1023: byte matchByte = _matchFinder.getIndexByte(0 - _repDistances[0] - 1 - _additionalOffset);
1024: subCoder.encodeMatched(_rangeEncoder, matchByte, curByte);
1025: } else {
1026: subCoder.encode(_rangeEncoder, curByte);
1027: }
1028: _previousByte = curByte;
1029: _state = Base.stateUpdateChar(_state);
1030: } else {
1031: _rangeEncoder.encode(_isMatch, complexState, 1);
1032:• if (pos < Base.kNumRepDistances) {
1033: _rangeEncoder.encode(_isRep, _state, 1);
1034:• if (pos == 0) {
1035: _rangeEncoder.encode(_isRepG0, _state, 0);
1036:• if (len == 1) {
1037: _rangeEncoder.encode(_isRep0Long, complexState, 0);
1038: } else {
1039: _rangeEncoder.encode(_isRep0Long, complexState, 1);
1040: }
1041: } else {
1042: _rangeEncoder.encode(_isRepG0, _state, 1);
1043:• if (pos == 1) {
1044: _rangeEncoder.encode(_isRepG1, _state, 0);
1045: } else {
1046: _rangeEncoder.encode(_isRepG1, _state, 1);
1047: _rangeEncoder.encode(_isRepG2, _state, pos - 2);
1048: }
1049: }
1050:• if (len == 1) {
1051: _state = Base.stateUpdateShortRep(_state);
1052: } else {
1053: _repMatchLenEncoder.encode(_rangeEncoder, len - Base.kMatchMinLen, posState);
1054: _state = Base.stateUpdateRep(_state);
1055: }
1056: int distance = _repDistances[pos];
1057:• if (pos != 0) {
1058: System.arraycopy(_repDistances, 0, _repDistances, 1, pos);
1059: _repDistances[0] = distance;
1060: }
1061: } else {
1062: _rangeEncoder.encode(_isRep, _state, 0);
1063: _state = Base.stateUpdateMatch(_state);
1064: _lenEncoder.encode(_rangeEncoder, len - Base.kMatchMinLen, posState);
1065: pos -= Base.kNumRepDistances;
1066: int posSlot = getPosSlot(pos);
1067: int lenToPosState = Base.getLenToPosState(len);
1068: _posSlotEncoder[lenToPosState].encode(_rangeEncoder, posSlot);
1069:
1070:• if (posSlot >= Base.kStartPosModelIndex) {
1071: int footerBits = (posSlot >> 1) - 1;
1072: int baseVal = (2 | posSlot & 1) << footerBits;
1073: int posReduced = pos - baseVal;
1074:
1075:• if (posSlot < Base.kEndPosModelIndex) {
1076: BitTreeEncoder.reverseEncode(_posEncoders, baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced);
1077: } else {
1078: _rangeEncoder.encodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits);
1079: _posAlignEncoder.reverseEncode(_rangeEncoder, posReduced & Base.kAlignMask);
1080: _alignPriceCount++;
1081: }
1082: }
1083: int distance = pos;
1084: System.arraycopy(_repDistances, 0, _repDistances, 1, Base.kNumRepDistances - 1);
1085: _repDistances[0] = distance;
1086: _matchPriceCount++;
1087: }
1088: _previousByte = _matchFinder.getIndexByte(len - 1 - _additionalOffset);
1089: }
1090: _additionalOffset -= len;
1091: nowPos64 += len;
1092:• if (_additionalOffset == 0) {
1093: // if (!_fastMode)
1094:• if (_matchPriceCount >= 1 << 7) {
1095: fillDistancesPrices();
1096: }
1097:• if (_alignPriceCount >= Base.kAlignTableSize) {
1098: fillAlignPrices();
1099: }
1100: inSize[0] = nowPos64;
1101: outSize[0] = _rangeEncoder.getProcessedSizeAdd();
1102:• if (_matchFinder.getNumAvailableBytes() == 0) {
1103: flush((int) nowPos64);
1104: return;
1105: }
1106:
1107:• if (nowPos64 - progressPosValuePrev >= 1 << 12) {
1108: _finished = false;
1109: finished[0] = false;
1110: return;
1111: }
1112: }
1113: }
1114: }
1115:
1116: void releaseMFBuffer() {
1117:• if (_matchFinder != null && _needReleaseMFStream) {
1118: _matchFinder.releaseBuffer();
1119: _needReleaseMFStream = false;
1120: }
1121: }
1122:
1123: void setDstBuffer(Buffer dst, MemoryManager mm) {
1124: _rangeEncoder.setBuffer(dst, mm);
1125: }
1126:
1127: Buffer releaseDstBuffer() {
1128: return _rangeEncoder.releaseBuffer();
1129: }
1130:
1131: void releaseBuffers(LZMAEncoder.LZMAOutputState state) {
1132: releaseMFBuffer();
1133: state.setDst(releaseDstBuffer());
1134: }
1135:
1136: void setStreams(Buffer src, Buffer dst, MemoryManager mm, long inSize, long outSize) {
1137: _src = src;
1138: _finished = false;
1139: create();
1140: setDstBuffer(dst, mm);
1141: init();
1142:
1143: // if (!_fastMode)
1144: {
1145: fillDistancesPrices();
1146: fillAlignPrices();
1147: }
1148:
1149: _lenEncoder.setTableSize(_numFastBytes + 1 - Base.kMatchMinLen);
1150: _lenEncoder.updateTables(1 << _posStateBits);
1151: _repMatchLenEncoder.setTableSize(_numFastBytes + 1 - Base.kMatchMinLen);
1152: _repMatchLenEncoder.updateTables(1 << _posStateBits);
1153:
1154: nowPos64 = 0;
1155: }
1156:
1157: final long[] processedInSize = new long[1];
1158: final long[] processedOutSize = new long[1];
1159: final boolean[] finished = new boolean[1];
1160:
1161: public void code(LZMAEncoder.LZMAOutputState state, long inSize, long outSize) throws IOException {
1162: _needReleaseMFStream = false;
1163: try {
1164: setStreams(state.getSrc(), state.getDst(), state.getMemoryManager(), inSize, outSize);
1165: while (true) {
1166: codeOneBlock(processedInSize, processedOutSize, finished);
1167:• if (finished[0]) {
1168: return;
1169: }
1170: }
1171: } finally {
1172: releaseBuffers(state);
1173: }
1174: }
1175:
1176: //        public static final int kPropSize = 5;
1177: //        byte[] properties = new byte[kPropSize];
1178: public void writeCoderProperties(Buffer dst) throws IOException {
1179: //                properties[0] = (byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits);
1180: //                for (int i = 0; i < 4; i++)
1181: //                        properties[1 + i] = (byte)(_dictionarySize >> (8 * i));
1182: //                outStream.write(properties, 0, kPropSize);
1183:
1184: dst.put((byte) ((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits));
1185:• for (int i = 0; i < 4; i++) {
1186: dst.put((byte) (_dictionarySize >> 8 * i));
1187: }
1188: }
1189:
1190: final int[] tempPrices = new int[Base.kNumFullDistances];
1191: int _matchPriceCount;
1192:
1193: void fillDistancesPrices() {
1194:• for (int i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++) {
1195: int posSlot = getPosSlot(i);
1196: int footerBits = (posSlot >> 1) - 1;
1197: int baseVal = (2 | posSlot & 1) << footerBits;
1198: tempPrices[i] = BitTreeEncoder.reverseGetPrice(_posEncoders, baseVal - posSlot - 1, footerBits, i - baseVal);
1199: }
1200:
1201:• for (int lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) {
1202: int posSlot;
1203: BitTreeEncoder encoder = _posSlotEncoder[lenToPosState];
1204:
1205: int st = lenToPosState << Base.kNumPosSlotBits;
1206:• for (posSlot = 0; posSlot < _distTableSize; posSlot++) {
1207: _posSlotPrices[st + posSlot] = encoder.getPrice(posSlot);
1208: }
1209:• for (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++) {
1210: _posSlotPrices[st + posSlot] += (posSlot >> 1) - 1 - Base.kNumAlignBits << RangeEncoder.kNumBitPriceShiftBits;
1211: }
1212:
1213: int st2 = lenToPosState * Base.kNumFullDistances;
1214: int i;
1215:• for (i = 0; i < Base.kStartPosModelIndex; i++) {
1216: _distancesPrices[st2 + i] = _posSlotPrices[st + i];
1217: }
1218:• for (; i < Base.kNumFullDistances; i++) {
1219: _distancesPrices[st2 + i] = _posSlotPrices[st + getPosSlot(i)] + tempPrices[i];
1220: }
1221: }
1222: _matchPriceCount = 0;
1223: }
1224:
1225: void fillAlignPrices() {
1226:• for (int i = 0; i < Base.kAlignTableSize; i++) {
1227: _alignPrices[i] = _posAlignEncoder.reverseGetPrice(i);
1228: }
1229: _alignPriceCount = 0;
1230: }
1231:
1232: public boolean setAlgorithm(int algorithm) {
1233: /*
1234: * _fastMode = (algorithm == 0); _maxMode = (algorithm >= 2);
1235: */
1236: return true;
1237: }
1238:
1239: public boolean setDictionarySize(int dictionarySize) {
1240: int kDicLogSizeMaxCompress = 29;
1241:• if (dictionarySize < 1 << Base.kDicLogSizeMin || dictionarySize > 1 << kDicLogSizeMaxCompress) {
1242: return false;
1243: }
1244: _dictionarySize = dictionarySize;
1245: int dicLogSize;
1246:• for (dicLogSize = 0; dictionarySize > 1 << dicLogSize; dicLogSize++) {
1247: ;
1248: }
1249: _distTableSize = dicLogSize * 2;
1250: return true;
1251: }
1252:
1253: public boolean setNumFastBytes(int numFastBytes) {
1254:• if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen) {
1255: return false;
1256: }
1257: _numFastBytes = numFastBytes;
1258: return true;
1259: }
1260:
1261: public boolean setMatchFinder(int matchFinderIndex) {
1262:• if (matchFinderIndex < 0 || matchFinderIndex > 2) {
1263: return false;
1264: }
1265: int matchFinderIndexPrev = _matchFinderType;
1266: _matchFinderType = matchFinderIndex;
1267:• if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType) {
1268: _dictionarySizePrev = -1;
1269: _matchFinder = null;
1270: }
1271: return true;
1272: }
1273:
1274: public boolean setLcLpPb(int lc, int lp, int pb) {
1275:• if (lp < 0 || lp > Base.kNumLitPosStatesBitsEncodingMax || lc < 0 || lc > Base.kNumLitContextBitsMax || pb < 0
1276: || pb > Base.kNumPosStatesBitsEncodingMax) {
1277: return false;
1278: }
1279: _numLiteralPosStateBits = lp;
1280: _numLiteralContextBits = lc;
1281: _posStateBits = pb;
1282: _posStateMask = (1 << _posStateBits) - 1;
1283: return true;
1284: }
1285:
1286: public void setEndMarkerMode(boolean endMarkerMode) {
1287: _writeEndMark = endMarkerMode;
1288: }
1289: }