Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5098 | clevermous | 1 | #include "LZMAEncoder.h" |
2 | #include "MatchFinder.h" |
||
3 | |||
4 | const byte kLiteralNextStates[kNumStates] = {0,0,0,0,1,2,3,4,5,6,4,5}; |
||
5 | const byte kMatchNextStates[kNumStates] = {7,7,7,7,7,7,7,10,10,10,10,10}; |
||
6 | const byte kRepNextStates[kNumStates] = {8,8,8,8,8,8,8,11,11,11,11,11}; |
||
7 | const byte kShortRepNextStates[kNumStates] = {9,9,9,9,9,9,9,11,11,11,11,11}; |
||
8 | |||
9 | static CState _state; |
||
10 | static byte _previousByte; |
||
11 | static unsigned _repDistances[kNumRepDistances]; |
||
12 | |||
13 | static COptimal _optimum[kNumOpts]; |
||
14 | static CMyBitEncoder _isMatch[kNumStates][kNumPosStatesEncodingMax]; |
||
15 | static CMyBitEncoder _isRep[kNumStates]; |
||
16 | static CMyBitEncoder _isRepG0[kNumStates]; |
||
17 | static CMyBitEncoder _isRepG1[kNumStates]; |
||
18 | static CMyBitEncoder _isRepG2[kNumStates]; |
||
19 | static CMyBitEncoder _isRep0Long[kNumStates][kNumPosStatesEncodingMax]; |
||
20 | static NRangeCoder_CBitTreeEncoder _posSlotEncoder[kNumLenToPosStates]; |
||
21 | static CMyBitEncoder _posEncoders[kNumFullDistances - kEndPosModelIndex]; |
||
22 | static NRangeCoder_CBitTreeEncoder _posAlignEncoder; |
||
23 | static NLength_CPriceTableEncoder _lenEncoder; |
||
24 | static NLength_CPriceTableEncoder _repMatchLenEncoder; |
||
25 | static CLiteralEncoder _literalEncoder; |
||
26 | static unsigned _matchDistances[kMatchMaxLen+1]; |
||
27 | static unsigned _numFastBytes; |
||
28 | static unsigned _longestMatchLength; |
||
29 | static unsigned _additionalOffset; |
||
30 | static unsigned _optimumEndIndex; |
||
31 | static unsigned _optimumCurrentIndex; |
||
32 | static bool _longestMatchWasFound; |
||
33 | static unsigned _posSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; |
||
34 | static unsigned _distancesPrices[kNumLenToPosStates][kNumFullDistances]; |
||
35 | static unsigned _alignPrices[kAlignTableSize]; |
||
36 | static unsigned _alignPriceCount; |
||
37 | static unsigned _distTableSize; |
||
38 | static unsigned _posStateBits; |
||
39 | static unsigned _posStateMask; |
||
40 | static unsigned _numLiteralPosStateBits; |
||
41 | static unsigned _numLiteralContextBits; |
||
42 | static unsigned _dictionarySize; |
||
43 | static uint64 lastPosSlotFillingPos; |
||
44 | static uint64 nowPos64; |
||
45 | static bool _finished; |
||
46 | static bool _writeEndMark; |
||
47 | |||
48 | static byte g_FastPos[1024]; |
||
49 | |||
50 | // must be called before work |
||
51 | static void FastPosInit(void) |
||
52 | { |
||
53 | int c = 2; |
||
54 | int slotFast; |
||
55 | unsigned j,k; |
||
56 | g_FastPos[0] = 0; |
||
57 | g_FastPos[1] = 1; |
||
58 | for (slotFast = 2; slotFast < 20; slotFast++) |
||
59 | { |
||
60 | k = (1 << ((slotFast >> 1) - 1)); |
||
61 | for (j=0;j |
||
62 | } |
||
63 | } |
||
64 | static unsigned GetPosSlot(unsigned pos) |
||
65 | { |
||
66 | if (pos < (1<<10)) |
||
67 | return g_FastPos[pos]; |
||
68 | if (pos < (1<<19)) |
||
69 | return g_FastPos[pos>>9]+18; |
||
70 | return g_FastPos[pos>>18]+36; |
||
71 | } |
||
72 | static unsigned GetPosSlot2(unsigned pos) |
||
73 | { |
||
74 | if (pos < (1<<16)) |
||
75 | return g_FastPos[pos>>6]+12; |
||
76 | if (pos < (1<<25)) |
||
77 | return g_FastPos[pos>>15]+30; |
||
78 | return g_FastPos[pos>>24]+48; |
||
79 | } |
||
80 | |||
81 | unsigned pack_length; |
||
82 | unsigned pack_pos; |
||
83 | const byte* curin; |
||
84 | byte* curout; |
||
85 | |||
86 | static void NLength_CEncoder_Init(NLength_CEncoder*e, unsigned numPosStates) |
||
87 | { |
||
88 | unsigned posState; |
||
89 | CMyBitEncoder_Init(e->_choice); |
||
90 | CMyBitEncoder_Init(e->_choice2); |
||
91 | for (posState=0;posState |
||
92 | { |
||
93 | CBitTreeEncoder_Init(&e->_lowCoder[posState],kNumLowBits); |
||
94 | CBitTreeEncoder_Init(&e->_midCoder[posState],kNumMidBits); |
||
95 | } |
||
96 | CBitTreeEncoder_Init(&e->_highCoder,kNumHighBits); |
||
97 | } |
||
98 | |||
99 | static void NLength_CEncoder_Encode(NLength_CEncoder*e, unsigned symbol, unsigned posState) |
||
100 | { |
||
101 | if (symbol < kNumLowSymbols) |
||
102 | { |
||
103 | CMyBitEncoder_Encode(&e->_choice,0); |
||
104 | CBitTreeEncoder_Encode(&e->_lowCoder[posState],symbol); |
||
105 | } |
||
106 | else |
||
107 | { |
||
108 | CMyBitEncoder_Encode(&e->_choice,1); |
||
109 | if (symbol < kNumLowSymbols + kNumMidSymbols) |
||
110 | { |
||
111 | CMyBitEncoder_Encode(&e->_choice2,0); |
||
112 | CBitTreeEncoder_Encode(&e->_midCoder[posState],symbol-kNumLowSymbols); |
||
113 | } |
||
114 | else |
||
115 | { |
||
116 | CMyBitEncoder_Encode(&e->_choice2,1); |
||
117 | CBitTreeEncoder_Encode(&e->_highCoder,symbol-kNumLowSymbols-kNumMidSymbols); |
||
118 | } |
||
119 | } |
||
120 | } |
||
121 | |||
122 | static unsigned NLength_CEncoder_GetPrice(NLength_CEncoder*e, unsigned symbol, unsigned posState) |
||
123 | { |
||
124 | unsigned price; |
||
125 | if (symbol < kNumLowSymbols) |
||
126 | return CMyBitEncoder_GetPrice0(&e->_choice) + |
||
127 | CBitTreeEncoder_GetPrice(&e->_lowCoder[posState],symbol); |
||
128 | price = CMyBitEncoder_GetPrice1(&e->_choice); |
||
129 | if (symbol < kNumLowSymbols + kNumMidSymbols) |
||
130 | { |
||
131 | price += CMyBitEncoder_GetPrice0(&e->_choice2); |
||
132 | price += CBitTreeEncoder_GetPrice(&e->_midCoder[posState],symbol-kNumLowSymbols); |
||
133 | } |
||
134 | else |
||
135 | { |
||
136 | price += CMyBitEncoder_GetPrice1(&e->_choice2); |
||
137 | price += CBitTreeEncoder_GetPrice(&e->_highCoder,symbol-kNumLowSymbols-kNumMidSymbols); |
||
138 | } |
||
139 | return price; |
||
140 | } |
||
141 | |||
142 | static void CPriceTableEncoder_SetTableSize(NLength_CPriceTableEncoder*pte,unsigned tableSize) |
||
143 | {pte->_tableSize = tableSize;} |
||
144 | static unsigned CPriceTableEncoder_GetPrice(NLength_CPriceTableEncoder*pte,unsigned symbol,unsigned posState) |
||
145 | {return pte->_prices[symbol][posState];} |
||
146 | static void CPriceTableEncoder_UpdateTable(NLength_CPriceTableEncoder*pte,unsigned posState) |
||
147 | { |
||
148 | unsigned len; |
||
149 | for (len=0;len |
||
150 | pte->_prices[len][posState] = NLength_CEncoder_GetPrice(&pte->base,len,posState); |
||
151 | pte->_counters[posState] = pte->_tableSize; |
||
152 | } |
||
153 | static void CPriceTableEncoder_UpdateTables(NLength_CPriceTableEncoder*pte,unsigned numPosStates) |
||
154 | { |
||
155 | unsigned posState; |
||
156 | for (posState=0;posState |
||
157 | CPriceTableEncoder_UpdateTable(pte,posState); |
||
158 | } |
||
159 | static void CPriceTableEncoder_Encode(NLength_CPriceTableEncoder*pte, unsigned symbol, unsigned posState) |
||
160 | { |
||
161 | NLength_CEncoder_Encode(&pte->base,symbol,posState); |
||
162 | if (--pte->_counters[posState] == 0) |
||
163 | CPriceTableEncoder_UpdateTable(pte,posState); |
||
164 | } |
||
165 | |||
166 | static void CBaseState_Init(void) |
||
167 | { |
||
168 | unsigned i; |
||
169 | CState_Init(_state); |
||
170 | _previousByte = 0; |
||
171 | for (i=0;i |
||
172 | _repDistances[i] = 0; |
||
173 | } |
||
174 | |||
175 | static void CLiteralEncoder2_Init(CLiteralEncoder2 le) |
||
176 | { |
||
177 | int i; |
||
178 | for (i=0;i<0x300;i++) |
||
179 | CMyBitEncoder_Init(le[i]); |
||
180 | } |
||
181 | |||
182 | static void CLiteralEncoder2_Encode(CLiteralEncoder2 le, byte symbol) |
||
183 | { |
||
184 | unsigned context = 1; |
||
185 | int i; |
||
186 | unsigned bit; |
||
187 | for (i=8;i--;) |
||
188 | { |
||
189 | bit = (symbol >> i) & 1; |
||
190 | CMyBitEncoder_Encode(&le[context],bit); |
||
191 | context = (context << 1) | bit; |
||
192 | } |
||
193 | } |
||
194 | |||
195 | static void CLiteralEncoder2_EncodeMatched(CLiteralEncoder2 le, byte matchByte, byte symbol) |
||
196 | { |
||
197 | unsigned context = 1; |
||
198 | int i; |
||
199 | unsigned bit,matchBit; |
||
200 | for (i=8;i--;) |
||
201 | { |
||
202 | bit = (symbol >> i) & 1; |
||
203 | matchBit = (matchByte >> i) & 1; |
||
204 | CMyBitEncoder_Encode(&le[0x100 + (matchBit<<8) + context],bit); |
||
205 | context = (context << 1) | bit; |
||
206 | if (matchBit != bit) |
||
207 | { |
||
208 | while (i--) |
||
209 | { |
||
210 | bit = (symbol >> i) & 1; |
||
211 | CMyBitEncoder_Encode(&le[context],bit); |
||
212 | context = (context << 1) | bit; |
||
213 | } |
||
214 | break; |
||
215 | } |
||
216 | } |
||
217 | } |
||
218 | |||
219 | static unsigned CLiteralEncoder2_GetPrice(CLiteralEncoder2 le, bool matchMode, byte matchByte, byte symbol) |
||
220 | { |
||
221 | unsigned price = 0; |
||
222 | unsigned context = 1; |
||
223 | unsigned bit,matchBit; |
||
224 | int i = 8; |
||
225 | if (matchMode) |
||
226 | { |
||
227 | do |
||
228 | { |
||
229 | i--; |
||
230 | matchBit = (matchByte >> i) & 1; |
||
231 | bit = (symbol >> i) & 1; |
||
232 | price += CMyBitEncoder_GetPrice(&le[0x100 + (matchBit<<8) + context],bit); |
||
233 | context = (context << 1) | bit; |
||
234 | if (matchBit != bit) |
||
235 | break; |
||
236 | } while (i); |
||
237 | } |
||
238 | while (i--) |
||
239 | { |
||
240 | bit = (symbol >> i) & 1; |
||
241 | price += CMyBitEncoder_GetPrice(&le[context],bit); |
||
242 | context = (context << 1) | bit; |
||
243 | } |
||
244 | return price; |
||
245 | } |
||
246 | |||
247 | static void WriteEndMarker(unsigned posState) |
||
248 | { |
||
249 | unsigned posSlot; |
||
250 | if (!_writeEndMark) |
||
251 | return; |
||
252 | CMyBitEncoder_Encode(&_isMatch[_state][posState],1); |
||
253 | CMyBitEncoder_Encode(&_isRep[_state],0); |
||
254 | CState_UpdateMatch(_state); |
||
255 | CPriceTableEncoder_Encode(&_lenEncoder,0,posState); |
||
256 | posSlot = (1< |
||
257 | CBitTreeEncoder_Encode(&_posSlotEncoder[GetLenToPosState(kMatchMinLen)],posSlot); |
||
258 | RangeEncoder_EncodeDirectBits(((1<<30)-1)>>kNumAlignBits,30-kNumAlignBits); |
||
259 | CBitTreeEncoder_ReverseEncode(&_posAlignEncoder,((1<<30)-1) & kAlignMask); |
||
260 | } |
||
261 | |||
262 | static void CEncoder_Flush(void) |
||
263 | { |
||
264 | WriteEndMarker((unsigned)nowPos64 & _posStateMask); |
||
265 | RangeEncoder_FlushData(); |
||
266 | } |
||
267 | |||
268 | static void CLiteralEncoder_Create(CLiteralEncoder*le, byte** memory, int numPosBits, int numPrevBits) |
||
269 | { |
||
270 | unsigned numStates; |
||
271 | le->_coders = (CLiteralEncoder2*)*memory; |
||
272 | numStates = 1 << (numPosBits+numPrevBits); |
||
273 | *memory = (byte*)(le->_coders + numStates); |
||
274 | le->_numPosBits = numPosBits; |
||
275 | le->_posMask = (1< |
||
276 | le->_numPrevBits = numPrevBits; |
||
277 | } |
||
278 | |||
279 | static void CLiteralEncoder_Init(CLiteralEncoder*le) |
||
280 | { |
||
281 | unsigned numStates,i; |
||
282 | numStates = 1 << (le->_numPosBits + le->_numPrevBits); |
||
283 | for (i=0;i |
||
284 | CLiteralEncoder2_Init(le->_coders[i]); |
||
285 | } |
||
286 | |||
287 | static unsigned CLiteralEncoder_GetState(CLiteralEncoder*le,unsigned pos,byte prevByte) |
||
288 | {return ((pos&le->_posMask)< |
||
289 | static CLiteralEncoder2* CLiteralEncoder_GetSubCoder(CLiteralEncoder*le,unsigned pos,byte prevByte) |
||
290 | {return &le->_coders[CLiteralEncoder_GetState(le,pos,prevByte)];} |
||
291 | |||
292 | static unsigned CLiteralEncoder_GetPrice(CLiteralEncoder*le,unsigned pos,byte prevByte, |
||
293 | bool matchMode, byte matchByte, byte symbol) |
||
294 | { |
||
295 | return CLiteralEncoder2_GetPrice(le->_coders[CLiteralEncoder_GetState(le,pos,prevByte)], |
||
296 | matchMode, matchByte, symbol); |
||
297 | } |
||
298 | |||
299 | static void CEncoder_Create(void*workmem) |
||
300 | { |
||
301 | byte* workpos = (byte*)workmem; |
||
302 | /* align on dword boundary */ |
||
303 | unsigned a; |
||
304 | a = (unsigned)workpos & 3; |
||
305 | if (a) workpos += 4-a; |
||
306 | /* sizeof(CLiteralEncoder2) * (1<<(numPosBits+numPrevBits)) for literal encoders */ |
||
307 | /* = 0xC00 * 8 = 0x6000 with current settings */ |
||
308 | CLiteralEncoder_Create(&_literalEncoder,&workpos,_numLiteralPosStateBits,_numLiteralContextBits); |
||
309 | /* (dictsize+0x1223)*1.5+256 for LZ input window */ |
||
310 | /* (0x140400 + (dictsize+1)*2) * 4 for match finder hash */ |
||
311 | MatchFinder_Create(_dictionarySize,kNumOpts,_numFastBytes, |
||
312 | kMatchMaxLen*2+1-_numFastBytes,&workpos); |
||
313 | /* total 0x508C3C + dictsize*9.5 */ |
||
314 | /* plus max 6 bytes for alignment */ |
||
315 | } |
||
316 | |||
317 | static void CEncoder_Init(void) |
||
318 | { |
||
319 | int i; |
||
320 | unsigned j; |
||
321 | CBaseState_Init(); |
||
322 | RangeEncoder_Init(); |
||
323 | for (i=0;i |
||
324 | { |
||
325 | for (j=0;j<=_posStateMask;j++) |
||
326 | { |
||
327 | CMyBitEncoder_Init(_isMatch[i][j]); |
||
328 | CMyBitEncoder_Init(_isRep0Long[i][j]); |
||
329 | } |
||
330 | CMyBitEncoder_Init(_isRep[i]); |
||
331 | CMyBitEncoder_Init(_isRepG0[i]); |
||
332 | CMyBitEncoder_Init(_isRepG1[i]); |
||
333 | CMyBitEncoder_Init(_isRepG2[i]); |
||
334 | } |
||
335 | CLiteralEncoder_Init(&_literalEncoder); |
||
336 | for (i=0;i |
||
337 | CBitTreeEncoder_Init(_posSlotEncoder+i,kNumPosSlotBits); |
||
338 | for (i=0;i |
||
339 | CMyBitEncoder_Init(_posEncoders[i]); |
||
340 | CPriceTableEncoder_Init(_lenEncoder, 1<<_posStateBits); |
||
341 | CPriceTableEncoder_Init(_repMatchLenEncoder,1<<_posStateBits); |
||
342 | CBitTreeEncoder_Init(&_posAlignEncoder,kNumAlignBits); |
||
343 | _longestMatchWasFound = false; |
||
344 | _optimumEndIndex = 0; |
||
345 | _optimumCurrentIndex = 0; |
||
346 | _additionalOffset = 0; |
||
347 | } |
||
348 | |||
349 | static void MovePos(unsigned num) |
||
350 | { |
||
351 | for (;num--;) |
||
352 | { |
||
353 | DummyLongestMatch(); |
||
354 | MatchFinder_MovePos(); |
||
355 | _additionalOffset++; |
||
356 | } |
||
357 | } |
||
358 | |||
359 | static unsigned Backward(unsigned* backRes, unsigned cur) |
||
360 | { |
||
361 | unsigned posMem,backMem; |
||
362 | unsigned posPrev,backCur; |
||
363 | _optimumEndIndex = cur; |
||
364 | posMem = _optimum[cur].PosPrev; |
||
365 | backMem = _optimum[cur].BackPrev; |
||
366 | do |
||
367 | { |
||
368 | if (_optimum[cur].Prev1IsChar) |
||
369 | { |
||
370 | COptimal_MakeAsChar(&_optimum[posMem]); |
||
371 | _optimum[posMem].PosPrev = posMem-1; |
||
372 | if (_optimum[cur].Prev2) |
||
373 | { |
||
374 | _optimum[posMem-1].Prev1IsChar = false; |
||
375 | _optimum[posMem-1].PosPrev = _optimum[cur].PosPrev2; |
||
376 | _optimum[posMem-1].BackPrev = _optimum[cur].BackPrev2; |
||
377 | } |
||
378 | } |
||
379 | posPrev = posMem; |
||
380 | backCur = backMem; |
||
381 | backMem = _optimum[posPrev].BackPrev; |
||
382 | posMem = _optimum[posPrev].PosPrev; |
||
383 | _optimum[posPrev].BackPrev = backCur; |
||
384 | _optimum[posPrev].PosPrev = cur; |
||
385 | cur = posPrev; |
||
386 | } while (cur); |
||
387 | *backRes = _optimum[0].BackPrev; |
||
388 | _optimumCurrentIndex = _optimum[0].PosPrev; |
||
389 | return _optimumCurrentIndex; |
||
390 | } |
||
391 | |||
392 | static unsigned ReadMatchDistances(void) |
||
393 | { |
||
394 | unsigned res; |
||
395 | res = GetLongestMatch(_matchDistances); |
||
396 | if (res == _numFastBytes) |
||
397 | res += GetMatchLen(res,_matchDistances[res],kMatchMaxLen-res); |
||
398 | _additionalOffset++; |
||
399 | MatchFinder_MovePos(); |
||
400 | return res; |
||
401 | } |
||
402 | |||
403 | static void FillPosSlotPrices(void) |
||
404 | { |
||
405 | unsigned lenToPosState,posSlot; |
||
406 | for (lenToPosState=0;lenToPosState |
||
407 | { |
||
408 | for (posSlot=0;posSlot |
||
409 | _posSlotPrices[lenToPosState][posSlot] = CBitTreeEncoder_GetPrice(&_posSlotEncoder[lenToPosState],posSlot); |
||
410 | for (;posSlot<_distTableSize;posSlot++) |
||
411 | _posSlotPrices[lenToPosState][posSlot] = CBitTreeEncoder_GetPrice(&_posSlotEncoder[lenToPosState],posSlot) + |
||
412 | (((posSlot>>1)-1-kNumAlignBits)< |
||
413 | } |
||
414 | } |
||
415 | |||
416 | static void FillDistancesPrices(void) |
||
417 | { |
||
418 | unsigned lenToPosState,i; |
||
419 | unsigned posSlot,footerBits,base; |
||
420 | for (lenToPosState=0;lenToPosState |
||
421 | { |
||
422 | for (i=0;i |
||
423 | _distancesPrices[lenToPosState][i] = _posSlotPrices[lenToPosState][i]; |
||
424 | for (;i |
||
425 | { |
||
426 | posSlot = GetPosSlot(i); |
||
427 | footerBits = ((posSlot>>1)-1); |
||
428 | base = (2|(posSlot&1))< |
||
429 | _distancesPrices[lenToPosState][i] = _posSlotPrices[lenToPosState][posSlot] + |
||
430 | ReverseBitTreeGetPrice(_posEncoders+base-posSlot-1,footerBits,i-base); |
||
431 | } |
||
432 | } |
||
433 | } |
||
434 | |||
435 | static void FillAlignPrices(void) |
||
436 | { |
||
437 | unsigned i; |
||
438 | for (i=0;i |
||
439 | _alignPrices[i] = CBitTreeEncoder_ReverseGetPrice(&_posAlignEncoder,i); |
||
440 | _alignPriceCount = kAlignTableSize; |
||
441 | } |
||
442 | |||
443 | static unsigned GetRepLen1Price(CState state, unsigned posState) |
||
444 | { |
||
445 | return CMyBitEncoder_GetPrice0(&_isRepG0[state]) + |
||
446 | CMyBitEncoder_GetPrice0(&_isRep0Long[state][posState]); |
||
447 | } |
||
448 | static unsigned GetRepPrice(unsigned repIndex, unsigned len, CState state, unsigned posState) |
||
449 | { |
||
450 | unsigned price; |
||
451 | price = CPriceTableEncoder_GetPrice(&_repMatchLenEncoder,len-kMatchMinLen,posState); |
||
452 | if (!repIndex) |
||
453 | { |
||
454 | price += CMyBitEncoder_GetPrice0(&_isRepG0[state]); |
||
455 | price += CMyBitEncoder_GetPrice1(&_isRep0Long[state][posState]); |
||
456 | } |
||
457 | else |
||
458 | { |
||
459 | price += CMyBitEncoder_GetPrice1(&_isRepG0[state]); |
||
460 | if (repIndex == 1) |
||
461 | price += CMyBitEncoder_GetPrice0(&_isRepG1[state]); |
||
462 | else |
||
463 | { |
||
464 | price += CMyBitEncoder_GetPrice1(&_isRepG1[state]); |
||
465 | price += CMyBitEncoder_GetPrice(&_isRepG2[state],repIndex-2); |
||
466 | } |
||
467 | } |
||
468 | return price; |
||
469 | } |
||
470 | static unsigned GetPosLenPrice(unsigned pos, unsigned len, unsigned posState) |
||
471 | { |
||
472 | unsigned price,lenToPosState; |
||
473 | if (len==2 && pos>=0x80) |
||
474 | return kIfinityPrice; |
||
475 | lenToPosState = GetLenToPosState(len); |
||
476 | if (pos < kNumFullDistances) |
||
477 | price = _distancesPrices[lenToPosState][pos]; |
||
478 | else |
||
479 | price = _posSlotPrices[lenToPosState][GetPosSlot2(pos)] + |
||
480 | _alignPrices[pos & kAlignMask]; |
||
481 | return price + CPriceTableEncoder_GetPrice(&_lenEncoder,len-kMatchMinLen,posState); |
||
482 | } |
||
483 | |||
484 | static void GetOptimum(unsigned position,unsigned*backRes,unsigned*lenRes) |
||
485 | { |
||
486 | int lenMain,lenEnd; |
||
487 | COptimal* opt,*prevOpt; |
||
488 | int reps[kNumRepDistances]; |
||
489 | int repLens[kNumRepDistances]; |
||
490 | int repIndex,repMaxIndex; |
||
491 | int i,len,repLen,lenTest,newLen,lenTestTemp,lenTest2; |
||
492 | int posState,posStateNext; |
||
493 | byte currentByte,matchByte; |
||
494 | unsigned matchPrice,repMatchPrice,shortRepPrice,normalMatchPrice,curAndLenPrice,curPrice,curAnd1Price,curAndLenCharPrice; |
||
495 | unsigned nextMatchPrice,nextRepMatchPrice; |
||
496 | int cur,posPrev,pos; |
||
497 | CState state,state2; |
||
498 | const byte* data; |
||
499 | bool nextIsChar; |
||
500 | int numAvailableBytesFull,numAvailableBytes; |
||
501 | int backOffset,offset; |
||
502 | int limit; |
||
503 | if (_optimumEndIndex != _optimumCurrentIndex) |
||
504 | { |
||
505 | opt = &_optimum[_optimumCurrentIndex]; |
||
506 | *lenRes = opt->PosPrev - _optimumCurrentIndex; |
||
507 | *backRes = opt->BackPrev; |
||
508 | _optimumCurrentIndex = opt->PosPrev; |
||
509 | return; |
||
510 | } |
||
511 | _optimumCurrentIndex = _optimumEndIndex = 0; |
||
512 | if (!_longestMatchWasFound) |
||
513 | lenMain = ReadMatchDistances(); |
||
514 | else |
||
515 | { |
||
516 | lenMain = _longestMatchLength; |
||
517 | _longestMatchWasFound = false; |
||
518 | } |
||
519 | for (i=0;i |
||
520 | { |
||
521 | reps[i] = _repDistances[i]; |
||
522 | repLens[i] = GetMatchLen(0-1,reps[i],kMatchMaxLen); |
||
523 | if (i==0 || repLens[i] > repLens[repMaxIndex]) |
||
524 | repMaxIndex = i; |
||
525 | } |
||
526 | if (repLens[repMaxIndex] >= _numFastBytes) |
||
527 | { |
||
528 | *backRes = repMaxIndex; |
||
529 | *lenRes = repLens[repMaxIndex]; |
||
530 | MovePos(*lenRes-1); |
||
531 | return; |
||
532 | } |
||
533 | if (lenMain >= _numFastBytes) |
||
534 | { |
||
535 | *backRes = _matchDistances[_numFastBytes]+kNumRepDistances; |
||
536 | *lenRes = lenMain; |
||
537 | MovePos(lenMain-1); |
||
538 | return; |
||
539 | } |
||
540 | currentByte = GetIndexByte(0-1); |
||
541 | _optimum[0].State = _state; |
||
542 | matchByte = GetIndexByte(0-_repDistances[0]-2); |
||
543 | posState = position & _posStateMask; |
||
544 | _optimum[1].Price = CMyBitEncoder_GetPrice0(&_isMatch[_state][posState]) + |
||
545 | CLiteralEncoder_GetPrice(&_literalEncoder,position,_previousByte, |
||
546 | (bool)!CState_IsCharState(_state),matchByte,currentByte); |
||
547 | COptimal_MakeAsChar(&_optimum[1]); |
||
548 | _optimum[1].PosPrev = 0; |
||
549 | for (i=0;i |
||
550 | _optimum[0].Backs[i] = reps[i]; |
||
551 | matchPrice = CMyBitEncoder_GetPrice1(&_isMatch[_state][posState]); |
||
552 | repMatchPrice = matchPrice + CMyBitEncoder_GetPrice1(&_isRep[_state]); |
||
553 | if (matchByte == currentByte) |
||
554 | { |
||
555 | shortRepPrice = repMatchPrice + GetRepLen1Price(_state,posState); |
||
556 | if (shortRepPrice < _optimum[1].Price) |
||
557 | { |
||
558 | _optimum[1].Price = shortRepPrice; |
||
559 | COptimal_MakeAsShortRep(&_optimum[1]); |
||
560 | } |
||
561 | } |
||
562 | if (lenMain < 2) |
||
563 | { |
||
564 | *backRes = _optimum[1].BackPrev; |
||
565 | *lenRes = 1; |
||
566 | return; |
||
567 | } |
||
568 | normalMatchPrice = matchPrice + CMyBitEncoder_GetPrice0(&_isRep[_state]); |
||
569 | if (lenMain <= repLens[repMaxIndex]) |
||
570 | lenMain = 0; |
||
571 | for (len=2;len<=lenMain;len++) |
||
572 | { |
||
573 | _optimum[len].PosPrev = 0; |
||
574 | _optimum[len].BackPrev = _matchDistances[len] + kNumRepDistances; |
||
575 | _optimum[len].Price = normalMatchPrice + GetPosLenPrice(_matchDistances[len],len,posState); |
||
576 | _optimum[len].Prev1IsChar = false; |
||
577 | } |
||
578 | if (lenMain < repLens[repMaxIndex]) |
||
579 | lenMain = repLens[repMaxIndex]; |
||
580 | for (;len<=lenMain;len++) |
||
581 | _optimum[len].Price = kIfinityPrice; |
||
582 | for (i=0;i |
||
583 | { |
||
584 | repLen = repLens[i]; |
||
585 | for (lenTest=2;lenTest<=repLen;lenTest++) |
||
586 | { |
||
587 | curAndLenPrice = repMatchPrice + GetRepPrice(i,lenTest,_state,posState); |
||
588 | opt = &_optimum[lenTest]; |
||
589 | if (curAndLenPrice < opt->Price) |
||
590 | { |
||
591 | opt->Price = curAndLenPrice; |
||
592 | opt->PosPrev = 0; |
||
593 | opt->BackPrev = i; |
||
594 | opt->Prev1IsChar = false; |
||
595 | } |
||
596 | } |
||
597 | } |
||
598 | cur=0; |
||
599 | lenEnd = lenMain; |
||
600 | while (1) |
||
601 | { |
||
602 | cur++; |
||
603 | if (cur==lenEnd) |
||
604 | { |
||
605 | *lenRes = Backward(backRes,cur); |
||
606 | return; |
||
607 | } |
||
608 | position++; |
||
609 | opt = &_optimum[cur]; |
||
610 | posPrev = opt->PosPrev; |
||
611 | if (opt->Prev1IsChar) |
||
612 | { |
||
613 | posPrev--; |
||
614 | if (opt->Prev2) |
||
615 | { |
||
616 | state = _optimum[opt->PosPrev2].State; |
||
617 | if (opt->BackPrev2 < kNumRepDistances) |
||
618 | CState_UpdateRep(state); |
||
619 | else |
||
620 | CState_UpdateMatch(state); |
||
621 | } |
||
622 | else |
||
623 | state = _optimum[posPrev].State; |
||
624 | CState_UpdateChar(state); |
||
625 | } |
||
626 | else |
||
627 | state = _optimum[posPrev].State; |
||
628 | if (posPrev == cur-1) |
||
629 | { |
||
630 | if (COptimal_IsShortRep(opt)) |
||
631 | CState_UpdateShortRep(state); |
||
632 | else |
||
633 | CState_UpdateChar(state); |
||
634 | } |
||
635 | else |
||
636 | { |
||
637 | if (opt->Prev1IsChar && opt->Prev2) |
||
638 | { |
||
639 | posPrev = opt->PosPrev2; |
||
640 | pos = opt->BackPrev2; |
||
641 | CState_UpdateRep(state); |
||
642 | } |
||
643 | else |
||
644 | { |
||
645 | pos = opt->BackPrev; |
||
646 | if (pos < kNumRepDistances) |
||
647 | CState_UpdateRep(state); |
||
648 | else |
||
649 | CState_UpdateMatch(state); |
||
650 | } |
||
651 | prevOpt = &_optimum[posPrev]; |
||
652 | if (pos < kNumRepDistances) |
||
653 | { |
||
654 | reps[0] = prevOpt->Backs[pos]; |
||
655 | for (i=1;i<=pos;i++) |
||
656 | reps[i] = prevOpt->Backs[i-1]; |
||
657 | for (;i |
||
658 | reps[i] = prevOpt->Backs[i]; |
||
659 | } |
||
660 | else |
||
661 | { |
||
662 | reps[0] = pos-kNumRepDistances; |
||
663 | for (i=1;i |
||
664 | reps[i] = prevOpt->Backs[i-1]; |
||
665 | } |
||
666 | } |
||
667 | opt->State = state; |
||
668 | for (i=0;i |
||
669 | opt->Backs[i] = reps[i]; |
||
670 | newLen = ReadMatchDistances(); |
||
671 | if (newLen >= _numFastBytes) |
||
672 | { |
||
673 | _longestMatchLength = newLen; |
||
674 | _longestMatchWasFound = true; |
||
675 | *lenRes = Backward(backRes,cur); |
||
676 | return; |
||
677 | } |
||
678 | curPrice = opt->Price; |
||
679 | data = GetPointerToCurrentPos()-1; |
||
680 | currentByte = *data; |
||
681 | matchByte = data[-1-reps[0]]; |
||
682 | posState = position & _posStateMask; |
||
683 | curAnd1Price = curPrice + CMyBitEncoder_GetPrice0(&_isMatch[state][posState]) + |
||
684 | CLiteralEncoder_GetPrice(&_literalEncoder,position,data[-1],(bool)!CState_IsCharState(state),matchByte,currentByte); |
||
685 | opt = &_optimum[cur+1]; |
||
686 | nextIsChar = false; |
||
687 | if (curAnd1Price < opt->Price) |
||
688 | { |
||
689 | opt->Price = curAnd1Price; |
||
690 | opt->PosPrev = cur; |
||
691 | COptimal_MakeAsChar(opt); |
||
692 | nextIsChar = true; |
||
693 | } |
||
694 | matchPrice = curPrice + CMyBitEncoder_GetPrice1(&_isMatch[state][posState]); |
||
695 | repMatchPrice = matchPrice + CMyBitEncoder_GetPrice1(&_isRep[state]); |
||
696 | if (matchByte == currentByte && !(opt->PosPrev |
||
697 | { |
||
698 | shortRepPrice = repMatchPrice + GetRepLen1Price(state,posState); |
||
699 | if (shortRepPrice <= opt->Price) |
||
700 | { |
||
701 | opt->Price = shortRepPrice; |
||
702 | opt->PosPrev = cur; |
||
703 | COptimal_MakeAsShortRep(opt); |
||
704 | } |
||
705 | } |
||
706 | numAvailableBytesFull = GetNumAvailableBytes()+1; |
||
707 | if (numAvailableBytesFull > kNumOpts-1-cur) |
||
708 | numAvailableBytesFull = kNumOpts-1-cur; |
||
709 | numAvailableBytes = numAvailableBytesFull; |
||
710 | if (numAvailableBytes < 2) |
||
711 | continue; |
||
712 | if (numAvailableBytes > _numFastBytes) |
||
713 | numAvailableBytes = _numFastBytes; |
||
714 | if (numAvailableBytes >= 3 && !nextIsChar) |
||
715 | { |
||
716 | // try Literal + rep0 |
||
717 | int temp; |
||
718 | backOffset = reps[0]+1; |
||
719 | for (temp=1;temp |
||
720 | if (data[temp]!=data[temp-backOffset]) |
||
721 | break; |
||
722 | lenTest = temp-1; |
||
723 | if (lenTest>=2) |
||
724 | { |
||
725 | int posStateNext; |
||
726 | unsigned nextRepMatchPrice; |
||
727 | state2 = state; |
||
728 | CState_UpdateChar(state2); |
||
729 | posStateNext = (position+1) & _posStateMask; |
||
730 | nextRepMatchPrice = curAnd1Price + |
||
731 | CMyBitEncoder_GetPrice1(&_isMatch[state2][posStateNext]) + |
||
732 | CMyBitEncoder_GetPrice1(&_isRep[state2]); |
||
733 | while (lenEnd < cur+1+lenTest) |
||
734 | _optimum[++lenEnd].Price = kIfinityPrice; |
||
735 | curAndLenPrice = nextRepMatchPrice + GetRepPrice(0,lenTest,state2,posStateNext); |
||
736 | opt = &_optimum[cur+1+lenTest]; |
||
737 | if (curAndLenPrice < opt->Price) |
||
738 | { |
||
739 | opt->Price = curAndLenPrice; |
||
740 | opt->PosPrev = cur+1; |
||
741 | opt->BackPrev = 0; |
||
742 | opt->Prev1IsChar = true; |
||
743 | opt->Prev2 = false; |
||
744 | } |
||
745 | } |
||
746 | } |
||
747 | for (repIndex=0;repIndex |
||
748 | { |
||
749 | backOffset = reps[repIndex]+1; |
||
750 | if (data[0] != data[0-backOffset] || |
||
751 | data[1] != data[1-backOffset]) |
||
752 | continue; |
||
753 | for (lenTest=2;lenTest |
||
754 | if (data[lenTest]!=data[lenTest-backOffset]) |
||
755 | break; |
||
756 | lenTestTemp = lenTest; |
||
757 | do |
||
758 | { |
||
759 | while (lenEnd < cur+lenTest) |
||
760 | _optimum[++lenEnd].Price = kIfinityPrice; |
||
761 | curAndLenPrice = repMatchPrice + GetRepPrice(repIndex,lenTest,state,posState); |
||
762 | opt = &_optimum[cur+lenTest]; |
||
763 | if (curAndLenPrice < opt->Price) |
||
764 | { |
||
765 | opt->Price = curAndLenPrice; |
||
766 | opt->PosPrev = cur; |
||
767 | opt->BackPrev = repIndex; |
||
768 | opt->Prev1IsChar = false; |
||
769 | } |
||
770 | } while (--lenTest>=2); |
||
771 | lenTest = lenTestTemp; |
||
772 | lenTest2 = lenTest+1; |
||
773 | limit = lenTest2 + _numFastBytes; |
||
774 | if (limit > numAvailableBytesFull) |
||
775 | limit = numAvailableBytesFull; |
||
776 | for (;lenTest2 |
||
777 | if (data[lenTest2] != data[lenTest2-backOffset]) |
||
778 | break; |
||
779 | lenTest2 -= lenTest+1; |
||
780 | if (lenTest2 >= 2) |
||
781 | { |
||
782 | unsigned nextMatchPrice,nextRepMatchPrice; |
||
783 | int offset; |
||
784 | state2 = state; |
||
785 | CState_UpdateRep(state2); |
||
786 | posStateNext = (position+lenTest)&_posStateMask; |
||
787 | curAndLenCharPrice = repMatchPrice + GetRepPrice(repIndex,lenTest,state,posState) + |
||
788 | CMyBitEncoder_GetPrice0(&_isMatch[state2][posStateNext]) + |
||
789 | CLiteralEncoder_GetPrice(&_literalEncoder,position+lenTest,data[lenTest-1],true,data[lenTest-backOffset],data[lenTest]); |
||
790 | CState_UpdateChar(state2); |
||
791 | posStateNext = (position+lenTest+1)&_posStateMask; |
||
792 | nextMatchPrice = curAndLenCharPrice + CMyBitEncoder_GetPrice1(&_isMatch[state2][posStateNext]); |
||
793 | nextRepMatchPrice = nextMatchPrice + CMyBitEncoder_GetPrice1(&_isRep[state2]); |
||
794 | offset = lenTest+1+lenTest2; |
||
795 | while (lenEnd |
||
796 | _optimum[++lenEnd].Price = kIfinityPrice; |
||
797 | curAndLenPrice = nextRepMatchPrice + GetRepPrice(0,lenTest2,state2,posStateNext); |
||
798 | opt = &_optimum[cur+offset]; |
||
799 | if (curAndLenPrice < opt->Price) |
||
800 | { |
||
801 | opt->Price = curAndLenPrice; |
||
802 | opt->PosPrev = cur+lenTest+1; |
||
803 | opt->BackPrev = 0; |
||
804 | opt->Prev1IsChar = true; |
||
805 | opt->Prev2 = true; |
||
806 | opt->PosPrev2 = cur; |
||
807 | opt->BackPrev2 = repIndex; |
||
808 | } |
||
809 | } |
||
810 | } |
||
811 | if (newLen > numAvailableBytes) |
||
812 | newLen = numAvailableBytes; |
||
813 | if (newLen >= 2) |
||
814 | { |
||
815 | if (newLen==2 && _matchDistances[2] >= 0x80) |
||
816 | continue; |
||
817 | normalMatchPrice = matchPrice + CMyBitEncoder_GetPrice0(&_isRep[state]); |
||
818 | while (lenEnd < cur+newLen) |
||
819 | _optimum[++lenEnd].Price = kIfinityPrice; |
||
820 | for (lenTest=newLen;lenTest>=2;lenTest--) |
||
821 | { |
||
822 | backOffset = _matchDistances[lenTest]; |
||
823 | curAndLenPrice = normalMatchPrice + GetPosLenPrice(backOffset,lenTest,posState); |
||
824 | opt = &_optimum[cur+lenTest]; |
||
825 | if (curAndLenPrice < opt->Price) |
||
826 | { |
||
827 | opt->Price = curAndLenPrice; |
||
828 | opt->PosPrev = cur; |
||
829 | opt->BackPrev = backOffset+kNumRepDistances; |
||
830 | opt->Prev1IsChar = false; |
||
831 | } |
||
832 | if (lenTest==newLen || backOffset!=_matchDistances[lenTest+1]) |
||
833 | { |
||
834 | // Try Match + Literal + Rep0 |
||
835 | backOffset++; |
||
836 | lenTest2 = lenTest+1; |
||
837 | limit = lenTest2+_numFastBytes; |
||
838 | if (limit > numAvailableBytesFull) |
||
839 | limit = numAvailableBytesFull; |
||
840 | for (;lenTest2 |
||
841 | if (data[lenTest2]!=data[lenTest2-backOffset]) |
||
842 | break; |
||
843 | lenTest2 -= lenTest+1; |
||
844 | if (lenTest2 >= 2) |
||
845 | { |
||
846 | state2 = state; |
||
847 | CState_UpdateMatch(state2); |
||
848 | posStateNext = (position+lenTest)&_posStateMask; |
||
849 | curAndLenCharPrice = curAndLenPrice + CMyBitEncoder_GetPrice0(&_isMatch[state2][posStateNext]) + |
||
850 | CLiteralEncoder_GetPrice(&_literalEncoder,position+lenTest,data[lenTest-1],true,data[lenTest-backOffset],data[lenTest]); |
||
851 | CState_UpdateChar(state2); |
||
852 | posStateNext = (position+lenTest+1)&_posStateMask; |
||
853 | nextMatchPrice = curAndLenCharPrice + CMyBitEncoder_GetPrice1(&_isMatch[state2][posStateNext]); |
||
854 | nextRepMatchPrice = nextMatchPrice + CMyBitEncoder_GetPrice1(&_isRep[state2]); |
||
855 | offset = lenTest+1+lenTest2; |
||
856 | while (lenEnd |
||
857 | _optimum[++lenEnd].Price = kIfinityPrice; |
||
858 | curAndLenPrice = nextRepMatchPrice + GetRepPrice(0,lenTest2,state2,posStateNext); |
||
859 | opt = &_optimum[cur+offset]; |
||
860 | if (curAndLenPrice < opt->Price) |
||
861 | { |
||
862 | opt->Price = curAndLenPrice; |
||
863 | opt->PosPrev = cur+lenTest+1; |
||
864 | opt->BackPrev = 0; |
||
865 | opt->Prev1IsChar = true; |
||
866 | opt->Prev2 = true; |
||
867 | opt->PosPrev2 = cur; |
||
868 | opt->BackPrev2 = backOffset - 1 + kNumRepDistances; |
||
869 | } |
||
870 | } |
||
871 | } |
||
872 | } |
||
873 | } |
||
874 | } |
||
875 | } |
||
876 | |||
877 | static bool CodeOneBlock(void) |
||
878 | { |
||
879 | unsigned posState; |
||
880 | byte curByte,matchByte; |
||
881 | unsigned pos,len,distance,i; |
||
882 | unsigned posSlot,lenToPosState; |
||
883 | CLiteralEncoder2* subCoder; |
||
884 | uint64 progressPosValuePrev; |
||
885 | |||
886 | if (_finished) |
||
887 | return false; |
||
888 | _finished = true; |
||
889 | progressPosValuePrev = nowPos64; |
||
890 | if (nowPos64 == 0) |
||
891 | { |
||
892 | if (GetNumAvailableBytes() == 0) |
||
893 | { |
||
894 | CEncoder_Flush(); |
||
895 | return false; |
||
896 | } |
||
897 | ReadMatchDistances(); |
||
898 | posState = (unsigned)nowPos64 & _posStateMask; |
||
899 | CMyBitEncoder_Encode(&_isMatch[_state][posState],0); |
||
900 | CState_UpdateChar(_state); |
||
901 | curByte = GetIndexByte(0 - _additionalOffset); |
||
902 | CLiteralEncoder2_Encode( |
||
903 | *CLiteralEncoder_GetSubCoder(&_literalEncoder,(unsigned)nowPos64,_previousByte), |
||
904 | curByte); |
||
905 | _previousByte = curByte; |
||
906 | _additionalOffset--; |
||
907 | nowPos64++; |
||
908 | } |
||
909 | if (GetNumAvailableBytes() == 0) |
||
910 | { |
||
911 | CEncoder_Flush(); |
||
912 | return false; |
||
913 | } |
||
914 | for (;;) |
||
915 | { |
||
916 | posState = (unsigned)nowPos64 & _posStateMask; |
||
917 | GetOptimum((unsigned)nowPos64,&pos,&len); |
||
918 | if (len==1 && pos==0xFFFFFFFF) |
||
919 | { |
||
920 | CMyBitEncoder_Encode(&_isMatch[_state][posState],0); |
||
921 | curByte = GetIndexByte(0-_additionalOffset); |
||
922 | subCoder = CLiteralEncoder_GetSubCoder(&_literalEncoder,(unsigned)nowPos64, |
||
923 | _previousByte); |
||
924 | if (!CState_IsCharState(_state)) |
||
925 | { |
||
926 | matchByte = GetIndexByte(0-_repDistances[0]-1-_additionalOffset); |
||
927 | CLiteralEncoder2_EncodeMatched(*subCoder,matchByte,curByte); |
||
928 | } |
||
929 | else |
||
930 | CLiteralEncoder2_Encode(*subCoder,curByte); |
||
931 | CState_UpdateChar(_state); |
||
932 | _previousByte = curByte; |
||
933 | } |
||
934 | else |
||
935 | { |
||
936 | CMyBitEncoder_Encode(&_isMatch[_state][posState],1); |
||
937 | if (pos < kNumRepDistances) |
||
938 | { |
||
939 | CMyBitEncoder_Encode(&_isRep[_state],1); |
||
940 | if (pos==0) |
||
941 | { |
||
942 | CMyBitEncoder_Encode(&_isRepG0[_state],0); |
||
943 | CMyBitEncoder_Encode(&_isRep0Long[_state][posState], |
||
944 | (len==1) ? 0 : 1); |
||
945 | } |
||
946 | else |
||
947 | { |
||
948 | CMyBitEncoder_Encode(&_isRepG0[_state],1); |
||
949 | if (pos==1) |
||
950 | CMyBitEncoder_Encode(&_isRepG1[_state],0); |
||
951 | else |
||
952 | { |
||
953 | CMyBitEncoder_Encode(&_isRepG1[_state],1); |
||
954 | CMyBitEncoder_Encode(&_isRepG2[_state],pos-2); |
||
955 | } |
||
956 | } |
||
957 | if (len==1) |
||
958 | CState_UpdateShortRep(_state); |
||
959 | else |
||
960 | { |
||
961 | CPriceTableEncoder_Encode(&_repMatchLenEncoder,len-kMatchMinLen,posState); |
||
962 | CState_UpdateRep(_state); |
||
963 | } |
||
964 | distance = _repDistances[pos]; |
||
965 | if (pos) |
||
966 | { |
||
967 | for (i=pos;i;i--) |
||
968 | _repDistances[i] = _repDistances[i-1]; |
||
969 | _repDistances[0] = distance; |
||
970 | } |
||
971 | } |
||
972 | else |
||
973 | { |
||
974 | CMyBitEncoder_Encode(&_isRep[_state],0); |
||
975 | CState_UpdateMatch(_state); |
||
976 | CPriceTableEncoder_Encode(&_lenEncoder,len-kMatchMinLen,posState); |
||
977 | pos -= kNumRepDistances; |
||
978 | posSlot = GetPosSlot(pos); |
||
979 | lenToPosState = GetLenToPosState(len); |
||
980 | CBitTreeEncoder_Encode(&_posSlotEncoder[lenToPosState],posSlot); |
||
981 | if (posSlot >= kStartPosModelIndex) |
||
982 | { |
||
983 | unsigned footerBits; |
||
984 | unsigned base,posReduced; |
||
985 | footerBits = (posSlot>>1)-1; |
||
986 | base = (2 | (posSlot&1)) << footerBits; |
||
987 | posReduced = pos-base; |
||
988 | if (posSlot < kEndPosModelIndex) |
||
989 | ReverseBitTreeEncode(_posEncoders+base-posSlot-1, |
||
990 | footerBits,posReduced); |
||
991 | else |
||
992 | { |
||
993 | RangeEncoder_EncodeDirectBits(posReduced>>kNumAlignBits,footerBits-kNumAlignBits); |
||
994 | CBitTreeEncoder_ReverseEncode(&_posAlignEncoder,posReduced&kAlignMask); |
||
995 | if (--_alignPriceCount == 0) |
||
996 | FillAlignPrices(); |
||
997 | } |
||
998 | } |
||
999 | distance = pos; |
||
1000 | for (i=kNumRepDistances-1;i;i--) |
||
1001 | _repDistances[i] = _repDistances[i-1]; |
||
1002 | _repDistances[0] = distance; |
||
1003 | } |
||
1004 | _previousByte = GetIndexByte(len-1-_additionalOffset); |
||
1005 | } |
||
1006 | _additionalOffset -= len; |
||
1007 | nowPos64 += len; |
||
1008 | if (nowPos64 - lastPosSlotFillingPos >= (1<<9)) |
||
1009 | { |
||
1010 | FillPosSlotPrices(); |
||
1011 | FillDistancesPrices(); |
||
1012 | lastPosSlotFillingPos = nowPos64; |
||
1013 | } |
||
1014 | if (!_additionalOffset) |
||
1015 | { |
||
1016 | if (GetNumAvailableBytes() == 0) |
||
1017 | { |
||
1018 | CEncoder_Flush(); |
||
1019 | return false; |
||
1020 | } |
||
1021 | if (nowPos64 - progressPosValuePrev >= (1<<12)) |
||
1022 | { |
||
1023 | _finished = false; |
||
1024 | return true; |
||
1025 | } |
||
1026 | } |
||
1027 | } |
||
1028 | } |
||
1029 | |||
1030 | extern void __stdcall lzma_set_dict_size( |
||
1031 | unsigned logdictsize) |
||
1032 | { |
||
1033 | _dictionarySize = 1 << logdictsize; |
||
1034 | _distTableSize = logdictsize*2; |
||
1035 | } |
||
1036 | |||
1037 | extern unsigned __stdcall lzma_compress( |
||
1038 | const void* source, |
||
1039 | void* destination, |
||
1040 | unsigned length, |
||
1041 | void* workmem) |
||
1042 | { |
||
1043 | FastPosInit(); |
||
1044 | //memset(&encoder,0,sizeof(encoder)); |
||
1045 | //memset(&rangeEncoder,0,sizeof(rangeEncoder)); |
||
1046 | // CEncoder::CEncoder, CEncoder::SetCoderProperties |
||
1047 | _numFastBytes = 128; |
||
1048 | #ifdef FOR_KERPACK |
||
1049 | _posStateBits = 0; |
||
1050 | _posStateMask = 0; |
||
1051 | #else |
||
1052 | _posStateBits = 2; |
||
1053 | _posStateMask = 3; |
||
1054 | #endif |
||
1055 | _numLiteralContextBits = 3; |
||
1056 | _numLiteralPosStateBits = 0; |
||
1057 | _writeEndMark = false; |
||
1058 | // CEncoder::Code - поехали! |
||
1059 | _finished = false; |
||
1060 | CEncoder_Create(workmem); |
||
1061 | CEncoder_Init(); |
||
1062 | FillPosSlotPrices(); |
||
1063 | FillDistancesPrices(); |
||
1064 | FillAlignPrices(); |
||
1065 | CPriceTableEncoder_SetTableSize(&_lenEncoder,_numFastBytes+1-kMatchMinLen); |
||
1066 | CPriceTableEncoder_UpdateTables(&_lenEncoder,1<<_posStateBits); |
||
1067 | CPriceTableEncoder_SetTableSize(&_repMatchLenEncoder,_numFastBytes+1-kMatchMinLen); |
||
1068 | CPriceTableEncoder_UpdateTables(&_repMatchLenEncoder,1<<_posStateBits); |
||
1069 | lastPosSlotFillingPos = 0; |
||
1070 | nowPos64 = 0; |
||
1071 | pack_length = length; |
||
1072 | pack_pos = 0; |
||
1073 | curin = (const byte*)source; |
||
1074 | curout = (byte*)destination; |
||
1075 | MatchFinder_Init(); |
||
1076 | while (CodeOneBlock()) ; |
||
1077 | return curout - (byte*)destination; |
||
1078 | } |