OLD | NEW |
| (Empty) |
1 package SevenZip.Compression.LZMA; | |
2 | |
3 import SevenZip.Compression.RangeCoder.BitTreeEncoder; | |
4 import SevenZip.Compression.LZMA.Base; | |
5 import SevenZip.Compression.LZ.BinTree; | |
6 import SevenZip.ICodeProgress; | |
7 import java.io.IOException; | |
8 | |
9 public class Encoder | |
10 { | |
11 public static final int EMatchFinderTypeBT2 = 0; | |
12 public static final int EMatchFinderTypeBT4 = 1; | |
13 | |
14 | |
15 | |
16 | |
17 static final int kIfinityPrice = 0xFFFFFFF; | |
18 | |
19 static byte[] g_FastPos = new byte[1 << 11]; | |
20 | |
21 static | |
22 { | |
23 int kFastSlots = 22; | |
24 int c = 2; | |
25 g_FastPos[0] = 0; | |
26 g_FastPos[1] = 1; | |
27 for (int slotFast = 2; slotFast < kFastSlots; slotFast++) | |
28 { | |
29 int k = (1 << ((slotFast >> 1) - 1)); | |
30 for (int j = 0; j < k; j++, c++) | |
31 g_FastPos[c] = (byte)slotFast; | |
32 } | |
33 } | |
34 | |
35 static int GetPosSlot(int pos) | |
36 { | |
37 if (pos < (1 << 11)) | |
38 return g_FastPos[pos]; | |
39 if (pos < (1 << 21)) | |
40 return (g_FastPos[pos >> 10] + 20); | |
41 return (g_FastPos[pos >> 20] + 40); | |
42 } | |
43 | |
44 static int GetPosSlot2(int pos) | |
45 { | |
46 if (pos < (1 << 17)) | |
47 return (g_FastPos[pos >> 6] + 12); | |
48 if (pos < (1 << 27)) | |
49 return (g_FastPos[pos >> 16] + 32); | |
50 return (g_FastPos[pos >> 26] + 52); | |
51 } | |
52 | |
53 int _state = Base.StateInit(); | |
54 byte _previousByte; | |
55 int[] _repDistances = new int[Base.kNumRepDistances]; | |
56 | |
57 void BaseInit() | |
58 { | |
59 _state = Base.StateInit(); | |
60 _previousByte = 0; | |
61 for (int i = 0; i < Base.kNumRepDistances; i++) | |
62 _repDistances[i] = 0; | |
63 } | |
64 | |
65 static final int kDefaultDictionaryLogSize = 22; | |
66 static final int kNumFastBytesDefault = 0x20; | |
67 | |
68 class LiteralEncoder | |
69 { | |
70 class Encoder2 | |
71 { | |
72 short[] m_Encoders = new short[0x300]; | |
73 | |
74 public void Init() { SevenZip.Compression.RangeCoder.Enc
oder.InitBitModels(m_Encoders); } | |
75 | |
76 | |
77 | |
78 public void Encode(SevenZip.Compression.RangeCoder.Encod
er rangeEncoder, byte symbol) throws IOException | |
79 { | |
80 int context = 1; | |
81 for (int i = 7; i >= 0; i--) | |
82 { | |
83 int bit = ((symbol >> i) & 1); | |
84 rangeEncoder.Encode(m_Encoders, context,
bit); | |
85 context = (context << 1) | bit; | |
86 } | |
87 } | |
88 | |
89 public void EncodeMatched(SevenZip.Compression.RangeCode
r.Encoder rangeEncoder, byte matchByte, byte symbol) throws IOException | |
90 { | |
91 int context = 1; | |
92 boolean same = true; | |
93 for (int i = 7; i >= 0; i--) | |
94 { | |
95 int bit = ((symbol >> i) & 1); | |
96 int state = context; | |
97 if (same) | |
98 { | |
99 int matchBit = ((matchByte >> i)
& 1); | |
100 state += ((1 + matchBit) << 8); | |
101 same = (matchBit == bit); | |
102 } | |
103 rangeEncoder.Encode(m_Encoders, state, b
it); | |
104 context = (context << 1) | bit; | |
105 } | |
106 } | |
107 | |
108 public int GetPrice(boolean matchMode, byte matchByte, b
yte symbol) | |
109 { | |
110 int price = 0; | |
111 int context = 1; | |
112 int i = 7; | |
113 if (matchMode) | |
114 { | |
115 for (; i >= 0; i--) | |
116 { | |
117 int matchBit = (matchByte >> i)
& 1; | |
118 int bit = (symbol >> i) & 1; | |
119 price += SevenZip.Compression.Ra
ngeCoder.Encoder.GetPrice(m_Encoders[((1 + matchBit) << 8) + context], bit); | |
120 context = (context << 1) | bit; | |
121 if (matchBit != bit) | |
122 { | |
123 i--; | |
124 break; | |
125 } | |
126 } | |
127 } | |
128 for (; i >= 0; i--) | |
129 { | |
130 int bit = (symbol >> i) & 1; | |
131 price += SevenZip.Compression.RangeCoder
.Encoder.GetPrice(m_Encoders[context], bit); | |
132 context = (context << 1) | bit; | |
133 } | |
134 return price; | |
135 } | |
136 } | |
137 | |
138 Encoder2[] m_Coders; | |
139 int m_NumPrevBits; | |
140 int m_NumPosBits; | |
141 int m_PosMask; | |
142 | |
143 public void Create(int numPosBits, int numPrevBits) | |
144 { | |
145 if (m_Coders != null && m_NumPrevBits == numPrevBits &&
m_NumPosBits == numPosBits) | |
146 return; | |
147 m_NumPosBits = numPosBits; | |
148 m_PosMask = (1 << numPosBits) - 1; | |
149 m_NumPrevBits = numPrevBits; | |
150 int numStates = 1 << (m_NumPrevBits + m_NumPosBits); | |
151 m_Coders = new Encoder2[numStates]; | |
152 for (int i = 0; i < numStates; i++) | |
153 m_Coders[i] = new Encoder2(); | |
154 } | |
155 | |
156 public void Init() | |
157 { | |
158 int numStates = 1 << (m_NumPrevBits + m_NumPosBits); | |
159 for (int i = 0; i < numStates; i++) | |
160 m_Coders[i].Init(); | |
161 } | |
162 | |
163 public Encoder2 GetSubCoder(int pos, byte prevByte) | |
164 { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + ((prevB
yte & 0xFF) >>> (8 - m_NumPrevBits))]; } | |
165 } | |
166 | |
167 class LenEncoder | |
168 { | |
169 short[] _choice = new short[2]; | |
170 BitTreeEncoder[] _lowCoder = new BitTreeEncoder[Base.kNumPosStat
esEncodingMax]; | |
171 BitTreeEncoder[] _midCoder = new BitTreeEncoder[Base.kNumPosStat
esEncodingMax]; | |
172 BitTreeEncoder _highCoder = new BitTreeEncoder(Base.kNumHighLenB
its); | |
173 | |
174 | |
175 public LenEncoder() | |
176 { | |
177 for (int posState = 0; posState < Base.kNumPosStatesEnco
dingMax; posState++) | |
178 { | |
179 _lowCoder[posState] = new BitTreeEncoder(Base.kN
umLowLenBits); | |
180 _midCoder[posState] = new BitTreeEncoder(Base.kN
umMidLenBits); | |
181 } | |
182 } | |
183 | |
184 public void Init(int numPosStates) | |
185 { | |
186 SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_c
hoice); | |
187 | |
188 for (int posState = 0; posState < numPosStates; posState
++) | |
189 { | |
190 _lowCoder[posState].Init(); | |
191 _midCoder[posState].Init(); | |
192 } | |
193 _highCoder.Init(); | |
194 } | |
195 | |
196 public void Encode(SevenZip.Compression.RangeCoder.Encoder range
Encoder, int symbol, int posState) throws IOException | |
197 { | |
198 if (symbol < Base.kNumLowLenSymbols) | |
199 { | |
200 rangeEncoder.Encode(_choice, 0, 0); | |
201 _lowCoder[posState].Encode(rangeEncoder, symbol)
; | |
202 } | |
203 else | |
204 { | |
205 symbol -= Base.kNumLowLenSymbols; | |
206 rangeEncoder.Encode(_choice, 0, 1); | |
207 if (symbol < Base.kNumMidLenSymbols) | |
208 { | |
209 rangeEncoder.Encode(_choice, 1, 0); | |
210 _midCoder[posState].Encode(rangeEncoder,
symbol); | |
211 } | |
212 else | |
213 { | |
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 { | |
222 int a0 = SevenZip.Compression.RangeCoder.Encoder.GetPric
e0(_choice[0]); | |
223 int a1 = SevenZip.Compression.RangeCoder.Encoder.GetPric
e1(_choice[0]); | |
224 int b0 = a1 + SevenZip.Compression.RangeCoder.Encoder.Ge
tPrice0(_choice[1]); | |
225 int b1 = a1 + SevenZip.Compression.RangeCoder.Encoder.Ge
tPrice1(_choice[1]); | |
226 int i = 0; | |
227 for (i = 0; i < Base.kNumLowLenSymbols; i++) | |
228 { | |
229 if (i >= numSymbols) | |
230 return; | |
231 prices[st + i] = a0 + _lowCoder[posState].GetPri
ce(i); | |
232 } | |
233 for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbo
ls; i++) | |
234 { | |
235 if (i >= numSymbols) | |
236 return; | |
237 prices[st + i] = b0 + _midCoder[posState].GetPri
ce(i - Base.kNumLowLenSymbols); | |
238 } | |
239 for (; i < numSymbols; i++) | |
240 prices[st + i] = b1 + _highCoder.GetPrice(i - Ba
se.kNumLowLenSymbols - Base.kNumMidLenSymbols); | |
241 } | |
242 }; | |
243 | |
244 public static final int kNumLenSpecSymbols = Base.kNumLowLenSymbols + Ba
se.kNumMidLenSymbols; | |
245 | |
246 class LenPriceTableEncoder extends LenEncoder | |
247 { | |
248 int[] _prices = new int[Base.kNumLenSymbols<<Base.kNumPosStatesB
itsEncodingMax]; | |
249 int _tableSize; | |
250 int[] _counters = new int[Base.kNumPosStatesEncodingMax]; | |
251 | |
252 public void SetTableSize(int tableSize) { _tableSize = tableSize
; } | |
253 | |
254 public int GetPrice(int symbol, int posState) | |
255 { | |
256 return _prices[posState * Base.kNumLenSymbols + symbol]; | |
257 } | |
258 | |
259 void UpdateTable(int posState) | |
260 { | |
261 SetPrices(posState, _tableSize, _prices, posState * Base
.kNumLenSymbols); | |
262 _counters[posState] = _tableSize; | |
263 } | |
264 | |
265 public void UpdateTables(int numPosStates) | |
266 { | |
267 for (int posState = 0; posState < numPosStates; posState
++) | |
268 UpdateTable(posState); | |
269 } | |
270 | |
271 public void Encode(SevenZip.Compression.RangeCoder.Encoder range
Encoder, int symbol, int posState) throws IOException | |
272 { | |
273 super.Encode(rangeEncoder, symbol, posState); | |
274 if (--_counters[posState] == 0) | |
275 UpdateTable(posState); | |
276 } | |
277 } | |
278 | |
279 static final int kNumOpts = 1 << 12; | |
280 class Optimal | |
281 { | |
282 public int State; | |
283 | |
284 public boolean Prev1IsChar; | |
285 public boolean Prev2; | |
286 | |
287 public int PosPrev2; | |
288 public int BackPrev2; | |
289 | |
290 public int Price; | |
291 public int PosPrev; | |
292 public int BackPrev; | |
293 | |
294 public int Backs0; | |
295 public int Backs1; | |
296 public int Backs2; | |
297 public int Backs3; | |
298 | |
299 public void MakeAsChar() { BackPrev = -1; Prev1IsChar = false; } | |
300 public void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = fal
se; } | |
301 public boolean IsShortRep() { return (BackPrev == 0); } | |
302 }; | |
303 Optimal[] _optimum = new Optimal[kNumOpts]; | |
304 SevenZip.Compression.LZ.BinTree _matchFinder = null; | |
305 SevenZip.Compression.RangeCoder.Encoder _rangeEncoder = new SevenZip.Com
pression.RangeCoder.Encoder(); | |
306 | |
307 short[] _isMatch = new short[Base.kNumStates<<Base.kNumPosStatesBitsMax]
; | |
308 short[] _isRep = new short[Base.kNumStates]; | |
309 short[] _isRepG0 = new short[Base.kNumStates]; | |
310 short[] _isRepG1 = new short[Base.kNumStates]; | |
311 short[] _isRepG2 = new short[Base.kNumStates]; | |
312 short[] _isRep0Long = new short[Base.kNumStates<<Base.kNumPosStatesBitsM
ax]; | |
313 | |
314 BitTreeEncoder[] _posSlotEncoder = new BitTreeEncoder[Base.kNumLenToPosS
tates]; // kNumPosSlotBits | |
315 | |
316 short[] _posEncoders = new short[Base.kNumFullDistances-Base.kEndPosMode
lIndex]; | |
317 BitTreeEncoder _posAlignEncoder = new BitTreeEncoder(Base.kNumAlignBits)
; | |
318 | |
319 LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder(); | |
320 LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder(); | |
321 | |
322 LiteralEncoder _literalEncoder = new LiteralEncoder(); | |
323 | |
324 int[] _matchDistances = new int[Base.kMatchMaxLen*2+2]; | |
325 | |
326 int _numFastBytes = kNumFastBytesDefault; | |
327 int _longestMatchLength; | |
328 int _numDistancePairs; | |
329 | |
330 int _additionalOffset; | |
331 | |
332 int _optimumEndIndex; | |
333 int _optimumCurrentIndex; | |
334 | |
335 boolean _longestMatchWasFound; | |
336 | |
337 int[] _posSlotPrices = new int[1<<(Base.kNumPosSlotBits+Base.kNumLenToPo
sStatesBits)]; | |
338 int[] _distancesPrices = new int[Base.kNumFullDistances<<Base.kNumLenToP
osStatesBits]; | |
339 int[] _alignPrices = new int[Base.kAlignTableSize]; | |
340 int _alignPriceCount; | |
341 | |
342 int _distTableSize = (kDefaultDictionaryLogSize * 2); | |
343 | |
344 int _posStateBits = 2; | |
345 int _posStateMask = (4 - 1); | |
346 int _numLiteralPosStateBits = 0; | |
347 int _numLiteralContextBits = 3; | |
348 | |
349 int _dictionarySize = (1 << kDefaultDictionaryLogSize); | |
350 int _dictionarySizePrev = -1; | |
351 int _numFastBytesPrev = -1; | |
352 | |
353 long nowPos64; | |
354 boolean _finished; | |
355 java.io.InputStream _inStream; | |
356 | |
357 int _matchFinderType = EMatchFinderTypeBT4; | |
358 boolean _writeEndMark = false; | |
359 | |
360 boolean _needReleaseMFStream = false; | |
361 | |
362 void Create() | |
363 { | |
364 if (_matchFinder == null) | |
365 { | |
366 SevenZip.Compression.LZ.BinTree bt = new SevenZip.Compre
ssion.LZ.BinTree(); | |
367 int numHashBytes = 4; | |
368 if (_matchFinderType == EMatchFinderTypeBT2) | |
369 numHashBytes = 2; | |
370 bt.SetType(numHashBytes); | |
371 _matchFinder = bt; | |
372 } | |
373 _literalEncoder.Create(_numLiteralPosStateBits, _numLiteralConte
xtBits); | |
374 | |
375 if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev
== _numFastBytes) | |
376 return; | |
377 _matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Ba
se.kMatchMaxLen + 1); | |
378 _dictionarySizePrev = _dictionarySize; | |
379 _numFastBytesPrev = _numFastBytes; | |
380 } | |
381 | |
382 public Encoder() | |
383 { | |
384 for (int i = 0; i < kNumOpts; i++) | |
385 _optimum[i] = new Optimal(); | |
386 for (int i = 0; i < Base.kNumLenToPosStates; i++) | |
387 _posSlotEncoder[i] = new BitTreeEncoder(Base.kNumPosSlot
Bits); | |
388 } | |
389 | |
390 void SetWriteEndMarkerMode(boolean writeEndMarker) | |
391 { | |
392 _writeEndMark = writeEndMarker; | |
393 } | |
394 | |
395 void Init() | |
396 { | |
397 BaseInit(); | |
398 _rangeEncoder.Init(); | |
399 | |
400 SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isMatch); | |
401 SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRep0Lon
g); | |
402 SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRep); | |
403 SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG0); | |
404 SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG1); | |
405 SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG2); | |
406 SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_posEncode
rs); | |
407 | |
408 | |
409 | |
410 | |
411 | |
412 | |
413 | |
414 _literalEncoder.Init(); | |
415 for (int i = 0; i < Base.kNumLenToPosStates; i++) | |
416 _posSlotEncoder[i].Init(); | |
417 | |
418 | |
419 | |
420 _lenEncoder.Init(1 << _posStateBits); | |
421 _repMatchLenEncoder.Init(1 << _posStateBits); | |
422 | |
423 _posAlignEncoder.Init(); | |
424 | |
425 _longestMatchWasFound = false; | |
426 _optimumEndIndex = 0; | |
427 _optimumCurrentIndex = 0; | |
428 _additionalOffset = 0; | |
429 } | |
430 | |
431 int ReadMatchDistances() throws java.io.IOException | |
432 { | |
433 int lenRes = 0; | |
434 _numDistancePairs = _matchFinder.GetMatches(_matchDistances); | |
435 if (_numDistancePairs > 0) | |
436 { | |
437 lenRes = _matchDistances[_numDistancePairs - 2]; | |
438 if (lenRes == _numFastBytes) | |
439 lenRes += _matchFinder.GetMatchLen((int)lenRes -
1, _matchDistances[_numDistancePairs - 1], | |
440 Base.kMatchMaxLen - lenRes); | |
441 } | |
442 _additionalOffset++; | |
443 return lenRes; | |
444 } | |
445 | |
446 void MovePos(int num) throws java.io.IOException | |
447 { | |
448 if (num > 0) | |
449 { | |
450 _matchFinder.Skip(num); | |
451 _additionalOffset += num; | |
452 } | |
453 } | |
454 | |
455 int GetRepLen1Price(int state, int posState) | |
456 { | |
457 return SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG
0[state]) + | |
458 SevenZip.Compression.RangeCoder.Encoder.GetPrice
0(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]); | |
459 } | |
460 | |
461 int GetPureRepPrice(int repIndex, int state, int posState) | |
462 { | |
463 int price; | |
464 if (repIndex == 0) | |
465 { | |
466 price = SevenZip.Compression.RangeCoder.Encoder.GetPrice
0(_isRepG0[state]); | |
467 price += SevenZip.Compression.RangeCoder.Encoder.GetPric
e1(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]); | |
468 } | |
469 else | |
470 { | |
471 price = SevenZip.Compression.RangeCoder.Encoder.GetPrice
1(_isRepG0[state]); | |
472 if (repIndex == 1) | |
473 price += SevenZip.Compression.RangeCoder.Encoder
.GetPrice0(_isRepG1[state]); | |
474 else | |
475 { | |
476 price += SevenZip.Compression.RangeCoder.Encoder
.GetPrice1(_isRepG1[state]); | |
477 price += SevenZip.Compression.RangeCoder.Encoder
.GetPrice(_isRepG2[state], repIndex - 2); | |
478 } | |
479 } | |
480 return price; | |
481 } | |
482 | |
483 int GetRepPrice(int repIndex, int len, int state, int posState) | |
484 { | |
485 int price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen
, posState); | |
486 return price + GetPureRepPrice(repIndex, state, posState); | |
487 } | |
488 | |
489 int GetPosLenPrice(int pos, int len, int posState) | |
490 { | |
491 int price; | |
492 int lenToPosState = Base.GetLenToPosState(len); | |
493 if (pos < Base.kNumFullDistances) | |
494 price = _distancesPrices[(lenToPosState * Base.kNumFullD
istances) + pos]; | |
495 else | |
496 price = _posSlotPrices[(lenToPosState << Base.kNumPosSlo
tBits) + GetPosSlot2(pos)] + | |
497 _alignPrices[pos & Base.kAlignMask]; | |
498 return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, pos
State); | |
499 } | |
500 | |
501 int Backward(int cur) | |
502 { | |
503 _optimumEndIndex = cur; | |
504 int posMem = _optimum[cur].PosPrev; | |
505 int backMem = _optimum[cur].BackPrev; | |
506 do | |
507 { | |
508 if (_optimum[cur].Prev1IsChar) | |
509 { | |
510 _optimum[posMem].MakeAsChar(); | |
511 _optimum[posMem].PosPrev = posMem - 1; | |
512 if (_optimum[cur].Prev2) | |
513 { | |
514 _optimum[posMem - 1].Prev1IsChar = false
; | |
515 _optimum[posMem - 1].PosPrev = _optimum[
cur].PosPrev2; | |
516 _optimum[posMem - 1].BackPrev = _optimum
[cur].BackPrev2; | |
517 } | |
518 } | |
519 int posPrev = posMem; | |
520 int backCur = backMem; | |
521 | |
522 backMem = _optimum[posPrev].BackPrev; | |
523 posMem = _optimum[posPrev].PosPrev; | |
524 | |
525 _optimum[posPrev].BackPrev = backCur; | |
526 _optimum[posPrev].PosPrev = cur; | |
527 cur = posPrev; | |
528 } | |
529 while (cur > 0); | |
530 backRes = _optimum[0].BackPrev; | |
531 _optimumCurrentIndex = _optimum[0].PosPrev; | |
532 return _optimumCurrentIndex; | |
533 } | |
534 | |
535 int[] reps = new int[Base.kNumRepDistances]; | |
536 int[] repLens = new int[Base.kNumRepDistances]; | |
537 int backRes; | |
538 | |
539 int GetOptimum(int position) throws IOException | |
540 { | |
541 if (_optimumEndIndex != _optimumCurrentIndex) | |
542 { | |
543 int lenRes = _optimum[_optimumCurrentIndex].PosPrev - _o
ptimumCurrentIndex; | |
544 backRes = _optimum[_optimumCurrentIndex].BackPrev; | |
545 _optimumCurrentIndex = _optimum[_optimumCurrentIndex].Po
sPrev; | |
546 return lenRes; | |
547 } | |
548 _optimumCurrentIndex = _optimumEndIndex = 0; | |
549 | |
550 int lenMain, numDistancePairs; | |
551 if (!_longestMatchWasFound) | |
552 { | |
553 lenMain = ReadMatchDistances(); | |
554 } | |
555 else | |
556 { | |
557 lenMain = _longestMatchLength; | |
558 _longestMatchWasFound = false; | |
559 } | |
560 numDistancePairs = _numDistancePairs; | |
561 | |
562 int numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1; | |
563 if (numAvailableBytes < 2) | |
564 { | |
565 backRes = -1; | |
566 return 1; | |
567 } | |
568 if (numAvailableBytes > Base.kMatchMaxLen) | |
569 numAvailableBytes = Base.kMatchMaxLen; | |
570 | |
571 int repMaxIndex = 0; | |
572 int i; | |
573 for (i = 0; i < Base.kNumRepDistances; i++) | |
574 { | |
575 reps[i] = _repDistances[i]; | |
576 repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Ba
se.kMatchMaxLen); | |
577 if (repLens[i] > repLens[repMaxIndex]) | |
578 repMaxIndex = i; | |
579 } | |
580 if (repLens[repMaxIndex] >= _numFastBytes) | |
581 { | |
582 backRes = repMaxIndex; | |
583 int lenRes = repLens[repMaxIndex]; | |
584 MovePos(lenRes - 1); | |
585 return lenRes; | |
586 } | |
587 | |
588 if (lenMain >= _numFastBytes) | |
589 { | |
590 backRes = _matchDistances[numDistancePairs - 1] + Base.k
NumRepDistances; | |
591 MovePos(lenMain - 1); | |
592 return lenMain; | |
593 } | |
594 | |
595 byte currentByte = _matchFinder.GetIndexByte(0 - 1); | |
596 byte matchByte = _matchFinder.GetIndexByte(0 - _repDistances[0]
- 1 - 1); | |
597 | |
598 if (lenMain < 2 && currentByte != matchByte && repLens[repMaxInd
ex] < 2) | |
599 { | |
600 backRes = -1; | |
601 return 1; | |
602 } | |
603 | |
604 _optimum[0].State = _state; | |
605 | |
606 int posState = (position & _posStateMask); | |
607 | |
608 _optimum[1].Price = SevenZip.Compression.RangeCoder.Encoder.GetP
rice0(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]) + | |
609 _literalEncoder.GetSubCoder(position, _previousB
yte).GetPrice(!Base.StateIsCharState(_state), matchByte, currentByte); | |
610 _optimum[1].MakeAsChar(); | |
611 | |
612 int matchPrice = SevenZip.Compression.RangeCoder.Encoder.GetPric
e1(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]); | |
613 int repMatchPrice = matchPrice + SevenZip.Compression.RangeCoder
.Encoder.GetPrice1(_isRep[_state]); | |
614 | |
615 if (matchByte == currentByte) | |
616 { | |
617 int shortRepPrice = repMatchPrice + GetRepLen1Price(_sta
te, posState); | |
618 if (shortRepPrice < _optimum[1].Price) | |
619 { | |
620 _optimum[1].Price = shortRepPrice; | |
621 _optimum[1].MakeAsShortRep(); | |
622 } | |
623 } | |
624 | |
625 int lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repL
ens[repMaxIndex]); | |
626 | |
627 if (lenEnd < 2) | |
628 { | |
629 backRes = _optimum[1].BackPrev; | |
630 return 1; | |
631 } | |
632 | |
633 _optimum[1].PosPrev = 0; | |
634 | |
635 _optimum[0].Backs0 = reps[0]; | |
636 _optimum[0].Backs1 = reps[1]; | |
637 _optimum[0].Backs2 = reps[2]; | |
638 _optimum[0].Backs3 = reps[3]; | |
639 | |
640 int len = lenEnd; | |
641 do | |
642 _optimum[len--].Price = kIfinityPrice; | |
643 while (len >= 2); | |
644 | |
645 for (i = 0; i < Base.kNumRepDistances; i++) | |
646 { | |
647 int repLen = repLens[i]; | |
648 if (repLen < 2) | |
649 continue; | |
650 int price = repMatchPrice + GetPureRepPrice(i, _state, p
osState); | |
651 do | |
652 { | |
653 int curAndLenPrice = price + _repMatchLenEncoder
.GetPrice(repLen - 2, posState); | |
654 Optimal optimum = _optimum[repLen]; | |
655 if (curAndLenPrice < optimum.Price) | |
656 { | |
657 optimum.Price = curAndLenPrice; | |
658 optimum.PosPrev = 0; | |
659 optimum.BackPrev = i; | |
660 optimum.Prev1IsChar = false; | |
661 } | |
662 } | |
663 while (--repLen >= 2); | |
664 } | |
665 | |
666 int normalMatchPrice = matchPrice + SevenZip.Compression.RangeCo
der.Encoder.GetPrice0(_isRep[_state]); | |
667 | |
668 len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); | |
669 if (len <= lenMain) | |
670 { | |
671 int offs = 0; | |
672 while (len > _matchDistances[offs]) | |
673 offs += 2; | |
674 for (; ; len++) | |
675 { | |
676 int distance = _matchDistances[offs + 1]; | |
677 int curAndLenPrice = normalMatchPrice + GetPosLe
nPrice(distance, len, posState); | |
678 Optimal optimum = _optimum[len]; | |
679 if (curAndLenPrice < optimum.Price) | |
680 { | |
681 optimum.Price = curAndLenPrice; | |
682 optimum.PosPrev = 0; | |
683 optimum.BackPrev = distance + Base.kNumR
epDistances; | |
684 optimum.Prev1IsChar = false; | |
685 } | |
686 if (len == _matchDistances[offs]) | |
687 { | |
688 offs += 2; | |
689 if (offs == numDistancePairs) | |
690 break; | |
691 } | |
692 } | |
693 } | |
694 | |
695 int cur = 0; | |
696 | |
697 while (true) | |
698 { | |
699 cur++; | |
700 if (cur == lenEnd) | |
701 return Backward(cur); | |
702 int newLen = ReadMatchDistances(); | |
703 numDistancePairs = _numDistancePairs; | |
704 if (newLen >= _numFastBytes) | |
705 { | |
706 | |
707 _longestMatchLength = newLen; | |
708 _longestMatchWasFound = true; | |
709 return Backward(cur); | |
710 } | |
711 position++; | |
712 int posPrev = _optimum[cur].PosPrev; | |
713 int state; | |
714 if (_optimum[cur].Prev1IsChar) | |
715 { | |
716 posPrev--; | |
717 if (_optimum[cur].Prev2) | |
718 { | |
719 state = _optimum[_optimum[cur].PosPrev2]
.State; | |
720 if (_optimum[cur].BackPrev2 < Base.kNumR
epDistances) | |
721 state = Base.StateUpdateRep(stat
e); | |
722 else | |
723 state = Base.StateUpdateMatch(st
ate); | |
724 } | |
725 else | |
726 state = _optimum[posPrev].State; | |
727 state = Base.StateUpdateChar(state); | |
728 } | |
729 else | |
730 state = _optimum[posPrev].State; | |
731 if (posPrev == cur - 1) | |
732 { | |
733 if (_optimum[cur].IsShortRep()) | |
734 state = Base.StateUpdateShortRep(state); | |
735 else | |
736 state = Base.StateUpdateChar(state); | |
737 } | |
738 else | |
739 { | |
740 int pos; | |
741 if (_optimum[cur].Prev1IsChar && _optimum[cur].P
rev2) | |
742 { | |
743 posPrev = _optimum[cur].PosPrev2; | |
744 pos = _optimum[cur].BackPrev2; | |
745 state = Base.StateUpdateRep(state); | |
746 } | |
747 else | |
748 { | |
749 pos = _optimum[cur].BackPrev; | |
750 if (pos < Base.kNumRepDistances) | |
751 state = Base.StateUpdateRep(stat
e); | |
752 else | |
753 state = Base.StateUpdateMatch(st
ate); | |
754 } | |
755 Optimal opt = _optimum[posPrev]; | |
756 if (pos < Base.kNumRepDistances) | |
757 { | |
758 if (pos == 0) | |
759 { | |
760 reps[0] = opt.Backs0; | |
761 reps[1] = opt.Backs1; | |
762 reps[2] = opt.Backs2; | |
763 reps[3] = opt.Backs3; | |
764 } | |
765 else if (pos == 1) | |
766 { | |
767 reps[0] = opt.Backs1; | |
768 reps[1] = opt.Backs0; | |
769 reps[2] = opt.Backs2; | |
770 reps[3] = opt.Backs3; | |
771 } | |
772 else if (pos == 2) | |
773 { | |
774 reps[0] = opt.Backs2; | |
775 reps[1] = opt.Backs0; | |
776 reps[2] = opt.Backs1; | |
777 reps[3] = opt.Backs3; | |
778 } | |
779 else | |
780 { | |
781 reps[0] = opt.Backs3; | |
782 reps[1] = opt.Backs0; | |
783 reps[2] = opt.Backs1; | |
784 reps[3] = opt.Backs2; | |
785 } | |
786 } | |
787 else | |
788 { | |
789 reps[0] = (pos - Base.kNumRepDistances); | |
790 reps[1] = opt.Backs0; | |
791 reps[2] = opt.Backs1; | |
792 reps[3] = opt.Backs2; | |
793 } | |
794 } | |
795 _optimum[cur].State = state; | |
796 _optimum[cur].Backs0 = reps[0]; | |
797 _optimum[cur].Backs1 = reps[1]; | |
798 _optimum[cur].Backs2 = reps[2]; | |
799 _optimum[cur].Backs3 = reps[3]; | |
800 int curPrice = _optimum[cur].Price; | |
801 | |
802 currentByte = _matchFinder.GetIndexByte(0 - 1); | |
803 matchByte = _matchFinder.GetIndexByte(0 - reps[0] - 1 -
1); | |
804 | |
805 posState = (position & _posStateMask); | |
806 | |
807 int curAnd1Price = curPrice + | |
808 SevenZip.Compression.RangeCoder.Encoder.GetPrice
0(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]) + | |
809 _literalEncoder.GetSubCoder(position, _matchFind
er.GetIndexByte(0 - 2)). | |
810 GetPrice(!Base.StateIsCharState(state), matchByt
e, currentByte); | |
811 | |
812 Optimal nextOptimum = _optimum[cur + 1]; | |
813 | |
814 boolean nextIsChar = false; | |
815 if (curAnd1Price < nextOptimum.Price) | |
816 { | |
817 nextOptimum.Price = curAnd1Price; | |
818 nextOptimum.PosPrev = cur; | |
819 nextOptimum.MakeAsChar(); | |
820 nextIsChar = true; | |
821 } | |
822 | |
823 matchPrice = curPrice + SevenZip.Compression.RangeCoder.
Encoder.GetPrice1(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]); | |
824 repMatchPrice = matchPrice + SevenZip.Compression.RangeC
oder.Encoder.GetPrice1(_isRep[state]); | |
825 | |
826 if (matchByte == currentByte && | |
827 !(nextOptimum.PosPrev < cur && nextOptimum.BackP
rev == 0)) | |
828 { | |
829 int shortRepPrice = repMatchPrice + GetRepLen1Pr
ice(state, posState); | |
830 if (shortRepPrice <= nextOptimum.Price) | |
831 { | |
832 nextOptimum.Price = shortRepPrice; | |
833 nextOptimum.PosPrev = cur; | |
834 nextOptimum.MakeAsShortRep(); | |
835 nextIsChar = true; | |
836 } | |
837 } | |
838 | |
839 int numAvailableBytesFull = _matchFinder.GetNumAvailable
Bytes() + 1; | |
840 numAvailableBytesFull = Math.min(kNumOpts - 1 - cur, num
AvailableBytesFull); | |
841 numAvailableBytes = numAvailableBytesFull; | |
842 | |
843 if (numAvailableBytes < 2) | |
844 continue; | |
845 if (numAvailableBytes > _numFastBytes) | |
846 numAvailableBytes = _numFastBytes; | |
847 if (!nextIsChar && matchByte != currentByte) | |
848 { | |
849 // try Literal + rep0 | |
850 int t = Math.min(numAvailableBytesFull - 1, _num
FastBytes); | |
851 int lenTest2 = _matchFinder.GetMatchLen(0, reps[
0], t); | |
852 if (lenTest2 >= 2) | |
853 { | |
854 int state2 = Base.StateUpdateChar(state)
; | |
855 | |
856 int posStateNext = (position + 1) & _pos
StateMask; | |
857 int nextRepMatchPrice = curAnd1Price + | |
858 SevenZip.Compression.RangeCoder.
Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]
) + | |
859 SevenZip.Compression.RangeCoder.
Encoder.GetPrice1(_isRep[state2]); | |
860 { | |
861 int offset = cur + 1 + lenTest2; | |
862 while (lenEnd < offset) | |
863 _optimum[++lenEnd].Price
= kIfinityPrice; | |
864 int curAndLenPrice = nextRepMatc
hPrice + GetRepPrice( | |
865 0, lenTest2, sta
te2, posStateNext); | |
866 Optimal optimum = _optimum[offse
t]; | |
867 if (curAndLenPrice < optimum.Pri
ce) | |
868 { | |
869 optimum.Price = curAndLe
nPrice; | |
870 optimum.PosPrev = cur +
1; | |
871 optimum.BackPrev = 0; | |
872 optimum.Prev1IsChar = tr
ue; | |
873 optimum.Prev2 = false; | |
874 } | |
875 } | |
876 } | |
877 } | |
878 | |
879 int startLen = 2; // speed optimization | |
880 | |
881 for (int repIndex = 0; repIndex < Base.kNumRepDistances;
repIndex++) | |
882 { | |
883 int lenTest = _matchFinder.GetMatchLen(0 - 1, re
ps[repIndex], numAvailableBytes); | |
884 if (lenTest < 2) | |
885 continue; | |
886 int lenTestTemp = lenTest; | |
887 do | |
888 { | |
889 while (lenEnd < cur + lenTest) | |
890 _optimum[++lenEnd].Price = kIfin
ityPrice; | |
891 int curAndLenPrice = repMatchPrice + Get
RepPrice(repIndex, lenTest, state, posState); | |
892 Optimal optimum = _optimum[cur + lenTest
]; | |
893 if (curAndLenPrice < optimum.Price) | |
894 { | |
895 optimum.Price = curAndLenPrice; | |
896 optimum.PosPrev = cur; | |
897 optimum.BackPrev = repIndex; | |
898 optimum.Prev1IsChar = false; | |
899 } | |
900 } | |
901 while (--lenTest >= 2); | |
902 lenTest = lenTestTemp; | |
903 | |
904 if (repIndex == 0) | |
905 startLen = lenTest + 1; | |
906 | |
907 // if (_maxMode) | |
908 if (lenTest < numAvailableBytesFull) | |
909 { | |
910 int t = Math.min(numAvailableBytesFull -
1 - lenTest, _numFastBytes); | |
911 int lenTest2 = _matchFinder.GetMatchLen(
lenTest, reps[repIndex], t); | |
912 if (lenTest2 >= 2) | |
913 { | |
914 int state2 = Base.StateUpdateRep
(state); | |
915 | |
916 int posStateNext = (position + l
enTest) & _posStateMask; | |
917 int curAndLenCharPrice = | |
918 repMatchPrice +
GetRepPrice(repIndex, lenTest, state, posState) + | |
919 SevenZip.Compres
sion.RangeCoder.Encoder.GetPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax)
+ posStateNext]) + | |
920 _literalEncoder.
GetSubCoder(position + lenTest, | |
921 _matchFinder.Get
IndexByte(lenTest - 1 - 1)).GetPrice(true, | |
922 _matchFinder.Get
IndexByte(lenTest - 1 - (reps[repIndex] + 1)), | |
923 _matchFinder.Get
IndexByte(lenTest - 1)); | |
924 state2 = Base.StateUpdateChar(st
ate2); | |
925 posStateNext = (position + lenTe
st + 1) & _posStateMask; | |
926 int nextMatchPrice = curAndLenCh
arPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 <<
Base.kNumPosStatesBitsMax) + posStateNext]); | |
927 int nextRepMatchPrice = nextMatc
hPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); | |
928 | |
929 // for(; lenTest2 >= 2; lenTest2
--) | |
930 { | |
931 int offset = lenTest + 1
+ lenTest2; | |
932 while (lenEnd < cur + of
fset) | |
933 _optimum[++lenEn
d].Price = kIfinityPrice; | |
934 int curAndLenPrice = nex
tRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); | |
935 Optimal optimum = _optim
um[cur + offset]; | |
936 if (curAndLenPrice < opt
imum.Price) | |
937 { | |
938 optimum.Price =
curAndLenPrice; | |
939 optimum.PosPrev
= cur + lenTest + 1; | |
940 optimum.BackPrev
= 0; | |
941 optimum.Prev1IsC
har = true; | |
942 optimum.Prev2 =
true; | |
943 optimum.PosPrev2
= cur; | |
944 optimum.BackPrev
2 = repIndex; | |
945 } | |
946 } | |
947 } | |
948 } | |
949 } | |
950 | |
951 if (newLen > numAvailableBytes) | |
952 { | |
953 newLen = numAvailableBytes; | |
954 for (numDistancePairs = 0; newLen > _matchDistan
ces[numDistancePairs]; numDistancePairs += 2) ; | |
955 _matchDistances[numDistancePairs] = newLen; | |
956 numDistancePairs += 2; | |
957 } | |
958 if (newLen >= startLen) | |
959 { | |
960 normalMatchPrice = matchPrice + SevenZip.Compres
sion.RangeCoder.Encoder.GetPrice0(_isRep[state]); | |
961 while (lenEnd < cur + newLen) | |
962 _optimum[++lenEnd].Price = kIfinityPrice
; | |
963 | |
964 int offs = 0; | |
965 while (startLen > _matchDistances[offs]) | |
966 offs += 2; | |
967 | |
968 for (int lenTest = startLen; ; lenTest++) | |
969 { | |
970 int curBack = _matchDistances[offs + 1]; | |
971 int curAndLenPrice = normalMatchPrice +
GetPosLenPrice(curBack, lenTest, posState); | |
972 Optimal optimum = _optimum[cur + lenTest
]; | |
973 if (curAndLenPrice < optimum.Price) | |
974 { | |
975 optimum.Price = curAndLenPrice; | |
976 optimum.PosPrev = cur; | |
977 optimum.BackPrev = curBack + Bas
e.kNumRepDistances; | |
978 optimum.Prev1IsChar = false; | |
979 } | |
980 | |
981 if (lenTest == _matchDistances[offs]) | |
982 { | |
983 if (lenTest < numAvailableBytesF
ull) | |
984 { | |
985 int t = Math.min(numAvai
lableBytesFull - 1 - lenTest, _numFastBytes); | |
986 int lenTest2 = _matchFin
der.GetMatchLen(lenTest, curBack, t); | |
987 if (lenTest2 >= 2) | |
988 { | |
989 int state2 = Bas
e.StateUpdateMatch(state); | |
990 | |
991 int posStateNext
= (position + lenTest) & _posStateMask; | |
992 int curAndLenCha
rPrice = curAndLenPrice + | |
993 SevenZip
.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state2 << Base.kNumPosStates
BitsMax) + posStateNext]) + | |
994 _literal
Encoder.GetSubCoder(position + lenTest, | |
995 _matchFi
nder.GetIndexByte(lenTest - 1 - 1)). | |
996 GetPrice
(true, | |
997 _matchFi
nder.GetIndexByte(lenTest - (curBack + 1) - 1), | |
998 _matchFi
nder.GetIndexByte(lenTest - 1)); | |
999 state2 = Base.St
ateUpdateChar(state2); | |
1000 posStateNext = (
position + lenTest + 1) & _posStateMask; | |
1001 int nextMatchPri
ce = curAndLenCharPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isM
atch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]); | |
1002 int nextRepMatch
Price = nextMatchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRe
p[state2]); | |
1003 | |
1004 int offset = len
Test + 1 + lenTest2; | |
1005 while (lenEnd <
cur + offset) | |
1006 _optimum
[++lenEnd].Price = kIfinityPrice; | |
1007 curAndLenPrice =
nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); | |
1008 optimum = _optim
um[cur + offset]; | |
1009 if (curAndLenPri
ce < optimum.Price) | |
1010 { | |
1011 optimum.
Price = curAndLenPrice; | |
1012 optimum.
PosPrev = cur + lenTest + 1; | |
1013 optimum.
BackPrev = 0; | |
1014 optimum.
Prev1IsChar = true; | |
1015 optimum.
Prev2 = true; | |
1016 optimum.
PosPrev2 = cur; | |
1017 optimum.
BackPrev2 = curBack + Base.kNumRepDistances; | |
1018 } | |
1019 } | |
1020 } | |
1021 offs += 2; | |
1022 if (offs == numDistancePairs) | |
1023 break; | |
1024 } | |
1025 } | |
1026 } | |
1027 } | |
1028 } | |
1029 | |
1030 boolean ChangePair(int smallDist, int bigDist) | |
1031 { | |
1032 int kDif = 7; | |
1033 return (smallDist < (1 << (32 - kDif)) && bigDist >= (smallDist
<< kDif)); | |
1034 } | |
1035 | |
1036 void WriteEndMarker(int posState) throws IOException | |
1037 { | |
1038 if (!_writeEndMark) | |
1039 return; | |
1040 | |
1041 _rangeEncoder.Encode(_isMatch, (_state << Base.kNumPosStatesBits
Max) + posState, 1); | |
1042 _rangeEncoder.Encode(_isRep, _state, 0); | |
1043 _state = Base.StateUpdateMatch(_state); | |
1044 int len = Base.kMatchMinLen; | |
1045 _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posSt
ate); | |
1046 int posSlot = (1 << Base.kNumPosSlotBits) - 1; | |
1047 int lenToPosState = Base.GetLenToPosState(len); | |
1048 _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); | |
1049 int footerBits = 30; | |
1050 int posReduced = (1 << footerBits) - 1; | |
1051 _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits,
footerBits - Base.kNumAlignBits); | |
1052 _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.
kAlignMask); | |
1053 } | |
1054 | |
1055 void Flush(int nowPos) throws IOException | |
1056 { | |
1057 ReleaseMFStream(); | |
1058 WriteEndMarker(nowPos & _posStateMask); | |
1059 _rangeEncoder.FlushData(); | |
1060 _rangeEncoder.FlushStream(); | |
1061 } | |
1062 | |
1063 public void CodeOneBlock(long[] inSize, long[] outSize, boolean[] finish
ed) throws IOException | |
1064 { | |
1065 inSize[0] = 0; | |
1066 outSize[0] = 0; | |
1067 finished[0] = true; | |
1068 | |
1069 if (_inStream != null) | |
1070 { | |
1071 _matchFinder.SetStream(_inStream); | |
1072 _matchFinder.Init(); | |
1073 _needReleaseMFStream = true; | |
1074 _inStream = null; | |
1075 } | |
1076 | |
1077 if (_finished) | |
1078 return; | |
1079 _finished = true; | |
1080 | |
1081 | |
1082 long progressPosValuePrev = nowPos64; | |
1083 if (nowPos64 == 0) | |
1084 { | |
1085 if (_matchFinder.GetNumAvailableBytes() == 0) | |
1086 { | |
1087 Flush((int)nowPos64); | |
1088 return; | |
1089 } | |
1090 | |
1091 ReadMatchDistances(); | |
1092 int posState = (int)(nowPos64) & _posStateMask; | |
1093 _rangeEncoder.Encode(_isMatch, (_state << Base.kNumPosSt
atesBitsMax) + posState, 0); | |
1094 _state = Base.StateUpdateChar(_state); | |
1095 byte curByte = _matchFinder.GetIndexByte(0 - _additional
Offset); | |
1096 _literalEncoder.GetSubCoder((int)(nowPos64), _previousBy
te).Encode(_rangeEncoder, curByte); | |
1097 _previousByte = curByte; | |
1098 _additionalOffset--; | |
1099 nowPos64++; | |
1100 } | |
1101 if (_matchFinder.GetNumAvailableBytes() == 0) | |
1102 { | |
1103 Flush((int)nowPos64); | |
1104 return; | |
1105 } | |
1106 while (true) | |
1107 { | |
1108 | |
1109 int len = GetOptimum((int)nowPos64); | |
1110 int pos = backRes; | |
1111 int posState = ((int)nowPos64) & _posStateMask; | |
1112 int complexState = (_state << Base.kNumPosStatesBitsMax)
+ posState; | |
1113 if (len == 1 && pos == -1) | |
1114 { | |
1115 _rangeEncoder.Encode(_isMatch, complexState, 0); | |
1116 byte curByte = _matchFinder.GetIndexByte((int)(0
- _additionalOffset)); | |
1117 LiteralEncoder.Encoder2 subCoder = _literalEncod
er.GetSubCoder((int)nowPos64, _previousByte); | |
1118 if (!Base.StateIsCharState(_state)) | |
1119 { | |
1120 byte matchByte = _matchFinder.GetIndexBy
te((int)(0 - _repDistances[0] - 1 - _additionalOffset)); | |
1121 subCoder.EncodeMatched(_rangeEncoder, ma
tchByte, curByte); | |
1122 } | |
1123 else | |
1124 subCoder.Encode(_rangeEncoder, curByte); | |
1125 _previousByte = curByte; | |
1126 _state = Base.StateUpdateChar(_state); | |
1127 } | |
1128 else | |
1129 { | |
1130 _rangeEncoder.Encode(_isMatch, complexState, 1); | |
1131 if (pos < Base.kNumRepDistances) | |
1132 { | |
1133 _rangeEncoder.Encode(_isRep, _state, 1); | |
1134 if (pos == 0) | |
1135 { | |
1136 _rangeEncoder.Encode(_isRepG0, _
state, 0); | |
1137 if (len == 1) | |
1138 _rangeEncoder.Encode(_is
Rep0Long, complexState, 0); | |
1139 else | |
1140 _rangeEncoder.Encode(_is
Rep0Long, complexState, 1); | |
1141 } | |
1142 else | |
1143 { | |
1144 _rangeEncoder.Encode(_isRepG0, _
state, 1); | |
1145 if (pos == 1) | |
1146 _rangeEncoder.Encode(_is
RepG1, _state, 0); | |
1147 else | |
1148 { | |
1149 _rangeEncoder.Encode(_is
RepG1, _state, 1); | |
1150 _rangeEncoder.Encode(_is
RepG2, _state, pos - 2); | |
1151 } | |
1152 } | |
1153 if (len == 1) | |
1154 _state = Base.StateUpdateShortRe
p(_state); | |
1155 else | |
1156 { | |
1157 _repMatchLenEncoder.Encode(_rang
eEncoder, len - Base.kMatchMinLen, posState); | |
1158 _state = Base.StateUpdateRep(_st
ate); | |
1159 } | |
1160 int distance = _repDistances[pos]; | |
1161 if (pos != 0) | |
1162 { | |
1163 for (int i = pos; i >= 1; i--) | |
1164 _repDistances[i] = _repD
istances[i - 1]; | |
1165 _repDistances[0] = distance; | |
1166 } | |
1167 } | |
1168 else | |
1169 { | |
1170 _rangeEncoder.Encode(_isRep, _state, 0); | |
1171 _state = Base.StateUpdateMatch(_state); | |
1172 _lenEncoder.Encode(_rangeEncoder, len -
Base.kMatchMinLen, posState); | |
1173 pos -= Base.kNumRepDistances; | |
1174 int posSlot = GetPosSlot(pos); | |
1175 int lenToPosState = Base.GetLenToPosStat
e(len); | |
1176 _posSlotEncoder[lenToPosState].Encode(_r
angeEncoder, posSlot); | |
1177 | |
1178 if (posSlot >= Base.kStartPosModelIndex) | |
1179 { | |
1180 int footerBits = (int)((posSlot
>> 1) - 1); | |
1181 int baseVal = ((2 | (posSlot & 1
)) << footerBits); | |
1182 int posReduced = pos - baseVal; | |
1183 | |
1184 if (posSlot < Base.kEndPosModelI
ndex) | |
1185 BitTreeEncoder.ReverseEn
code(_posEncoders, | |
1186 baseVal
- posSlot - 1, _rangeEncoder, footerBits, posReduced); | |
1187 else | |
1188 { | |
1189 _rangeEncoder.EncodeDire
ctBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); | |
1190 _posAlignEncoder.Reverse
Encode(_rangeEncoder, posReduced & Base.kAlignMask); | |
1191 _alignPriceCount++; | |
1192 } | |
1193 } | |
1194 int distance = pos; | |
1195 for (int i = Base.kNumRepDistances - 1;
i >= 1; i--) | |
1196 _repDistances[i] = _repDistances
[i - 1]; | |
1197 _repDistances[0] = distance; | |
1198 _matchPriceCount++; | |
1199 } | |
1200 _previousByte = _matchFinder.GetIndexByte(len -
1 - _additionalOffset); | |
1201 } | |
1202 _additionalOffset -= len; | |
1203 nowPos64 += len; | |
1204 if (_additionalOffset == 0) | |
1205 { | |
1206 // if (!_fastMode) | |
1207 if (_matchPriceCount >= (1 << 7)) | |
1208 FillDistancesPrices(); | |
1209 if (_alignPriceCount >= Base.kAlignTableSize) | |
1210 FillAlignPrices(); | |
1211 inSize[0] = nowPos64; | |
1212 outSize[0] = _rangeEncoder.GetProcessedSizeAdd()
; | |
1213 if (_matchFinder.GetNumAvailableBytes() == 0) | |
1214 { | |
1215 Flush((int)nowPos64); | |
1216 return; | |
1217 } | |
1218 | |
1219 if (nowPos64 - progressPosValuePrev >= (1 << 12)
) | |
1220 { | |
1221 _finished = false; | |
1222 finished[0] = false; | |
1223 return; | |
1224 } | |
1225 } | |
1226 } | |
1227 } | |
1228 | |
1229 void ReleaseMFStream() | |
1230 { | |
1231 if (_matchFinder != null && _needReleaseMFStream) | |
1232 { | |
1233 _matchFinder.ReleaseStream(); | |
1234 _needReleaseMFStream = false; | |
1235 } | |
1236 } | |
1237 | |
1238 void SetOutStream(java.io.OutputStream outStream) | |
1239 { _rangeEncoder.SetStream(outStream); } | |
1240 void ReleaseOutStream() | |
1241 { _rangeEncoder.ReleaseStream(); } | |
1242 | |
1243 void ReleaseStreams() | |
1244 { | |
1245 ReleaseMFStream(); | |
1246 ReleaseOutStream(); | |
1247 } | |
1248 | |
1249 void SetStreams(java.io.InputStream inStream, java.io.OutputStream outSt
ream, | |
1250 long inSize, long outSize) | |
1251 { | |
1252 _inStream = inStream; | |
1253 _finished = false; | |
1254 Create(); | |
1255 SetOutStream(outStream); | |
1256 Init(); | |
1257 | |
1258 // if (!_fastMode) | |
1259 { | |
1260 FillDistancesPrices(); | |
1261 FillAlignPrices(); | |
1262 } | |
1263 | |
1264 _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); | |
1265 _lenEncoder.UpdateTables(1 << _posStateBits); | |
1266 _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatch
MinLen); | |
1267 _repMatchLenEncoder.UpdateTables(1 << _posStateBits); | |
1268 | |
1269 nowPos64 = 0; | |
1270 } | |
1271 | |
1272 long[] processedInSize = new long[1]; long[] processedOutSize = new long
[1]; boolean[] finished = new boolean[1]; | |
1273 public void Code(java.io.InputStream inStream, java.io.OutputStream outS
tream, | |
1274 long inSize, long outSize, ICodeProgress progress) throw
s IOException | |
1275 { | |
1276 _needReleaseMFStream = false; | |
1277 try | |
1278 { | |
1279 SetStreams(inStream, outStream, inSize, outSize); | |
1280 while (true) | |
1281 { | |
1282 | |
1283 | |
1284 | |
1285 CodeOneBlock(processedInSize, processedOutSize,
finished); | |
1286 if (finished[0]) | |
1287 return; | |
1288 if (progress != null) | |
1289 { | |
1290 progress.SetProgress(processedInSize[0],
processedOutSize[0]); | |
1291 } | |
1292 } | |
1293 } | |
1294 finally | |
1295 { | |
1296 ReleaseStreams(); | |
1297 } | |
1298 } | |
1299 | |
1300 public static final int kPropSize = 5; | |
1301 byte[] properties = new byte[kPropSize]; | |
1302 | |
1303 public void WriteCoderProperties(java.io.OutputStream outStream) throws
IOException | |
1304 { | |
1305 properties[0] = (byte)((_posStateBits * 5 + _numLiteralPosStateB
its) * 9 + _numLiteralContextBits); | |
1306 for (int i = 0; i < 4; i++) | |
1307 properties[1 + i] = (byte)(_dictionarySize >> (8 * i)); | |
1308 outStream.write(properties, 0, kPropSize); | |
1309 } | |
1310 | |
1311 int[] tempPrices = new int[Base.kNumFullDistances]; | |
1312 int _matchPriceCount; | |
1313 | |
1314 void FillDistancesPrices() | |
1315 { | |
1316 for (int i = Base.kStartPosModelIndex; i < Base.kNumFullDistance
s; i++) | |
1317 { | |
1318 int posSlot = GetPosSlot(i); | |
1319 int footerBits = (int)((posSlot >> 1) - 1); | |
1320 int baseVal = ((2 | (posSlot & 1)) << footerBits); | |
1321 tempPrices[i] = BitTreeEncoder.ReverseGetPrice(_posEncod
ers, | |
1322 baseVal - posSlot - 1, footerBits, i - baseVal); | |
1323 } | |
1324 | |
1325 for (int lenToPosState = 0; lenToPosState < Base.kNumLenToPosSta
tes; lenToPosState++) | |
1326 { | |
1327 int posSlot; | |
1328 BitTreeEncoder encoder = _posSlotEncoder[lenToPosState]; | |
1329 | |
1330 int st = (lenToPosState << Base.kNumPosSlotBits); | |
1331 for (posSlot = 0; posSlot < _distTableSize; posSlot++) | |
1332 _posSlotPrices[st + posSlot] = encoder.GetPrice(
posSlot); | |
1333 for (posSlot = Base.kEndPosModelIndex; posSlot < _distTa
bleSize; posSlot++) | |
1334 _posSlotPrices[st + posSlot] += ((((posSlot >> 1
) - 1) - Base.kNumAlignBits) << SevenZip.Compression.RangeCoder.Encoder.kNumBitP
riceShiftBits); | |
1335 | |
1336 int st2 = lenToPosState * Base.kNumFullDistances; | |
1337 int i; | |
1338 for (i = 0; i < Base.kStartPosModelIndex; i++) | |
1339 _distancesPrices[st2 + i] = _posSlotPrices[st +
i]; | |
1340 for (; i < Base.kNumFullDistances; i++) | |
1341 _distancesPrices[st2 + i] = _posSlotPrices[st +
GetPosSlot(i)] + tempPrices[i]; | |
1342 } | |
1343 _matchPriceCount = 0; | |
1344 } | |
1345 | |
1346 void FillAlignPrices() | |
1347 { | |
1348 for (int i = 0; i < Base.kAlignTableSize; i++) | |
1349 _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); | |
1350 _alignPriceCount = 0; | |
1351 } | |
1352 | |
1353 | |
1354 public boolean SetAlgorithm(int algorithm) | |
1355 { | |
1356 /* | |
1357 _fastMode = (algorithm == 0); | |
1358 _maxMode = (algorithm >= 2); | |
1359 */ | |
1360 return true; | |
1361 } | |
1362 | |
1363 public boolean SetDictionarySize(int dictionarySize) | |
1364 { | |
1365 int kDicLogSizeMaxCompress = 29; | |
1366 if (dictionarySize < (1 << Base.kDicLogSizeMin) || dictionarySiz
e > (1 << kDicLogSizeMaxCompress)) | |
1367 return false; | |
1368 _dictionarySize = dictionarySize; | |
1369 int dicLogSize; | |
1370 for (dicLogSize = 0; dictionarySize > (1 << dicLogSize); dicLogS
ize++) ; | |
1371 _distTableSize = dicLogSize * 2; | |
1372 return true; | |
1373 } | |
1374 | |
1375 public boolean SetNumFastBytes(int numFastBytes) | |
1376 { | |
1377 if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen) | |
1378 return false; | |
1379 _numFastBytes = numFastBytes; | |
1380 return true; | |
1381 } | |
1382 | |
1383 public boolean SetMatchFinder(int matchFinderIndex) | |
1384 { | |
1385 if (matchFinderIndex < 0 || matchFinderIndex > 2) | |
1386 return false; | |
1387 int matchFinderIndexPrev = _matchFinderType; | |
1388 _matchFinderType = matchFinderIndex; | |
1389 if (_matchFinder != null && matchFinderIndexPrev != _matchFinder
Type) | |
1390 { | |
1391 _dictionarySizePrev = -1; | |
1392 _matchFinder = null; | |
1393 } | |
1394 return true; | |
1395 } | |
1396 | |
1397 public boolean SetLcLpPb(int lc, int lp, int pb) | |
1398 { | |
1399 if ( | |
1400 lp < 0 || lp > Base.kNumLitPosStatesBitsEncoding
Max || | |
1401 lc < 0 || lc > Base.kNumLitContextBitsMax || | |
1402 pb < 0 || pb > Base.kNumPosStatesBitsEncodingMax
) | |
1403 return false; | |
1404 _numLiteralPosStateBits = lp; | |
1405 _numLiteralContextBits = lc; | |
1406 _posStateBits = pb; | |
1407 _posStateMask = ((1) << _posStateBits) - 1; | |
1408 return true; | |
1409 } | |
1410 | |
1411 public void SetEndMarkerMode(boolean endMarkerMode) | |
1412 { | |
1413 _writeEndMark = endMarkerMode; | |
1414 } | |
1415 } | |
1416 | |
OLD | NEW |