LZMAEncoder.cpp 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547
  1. // LZMA/Encoder.cpp
  2. #include "StdAfx.h"
  3. #include <stdio.h>
  4. #ifdef _WIN32
  5. #define USE_ALLOCA
  6. #endif
  7. #ifdef USE_ALLOCA
  8. #ifdef _WIN32
  9. #include <malloc.h>
  10. #else
  11. #include <stdlib.h>
  12. #endif
  13. #endif
  14. #include "../../../Common/Defs.h"
  15. #include "../../Common/StreamUtils.h"
  16. #include "LZMAEncoder.h"
  17. // extern "C" { #include "../../../../C/7zCrc.h" }
  18. // #define SHOW_STAT
  19. namespace NCompress {
  20. namespace NLZMA {
  21. // struct CCrcInit { CCrcInit() { InitCrcTable(); } } g_CrcInit;
  22. const int kDefaultDictionaryLogSize = 22;
  23. const UInt32 kNumFastBytesDefault = 0x20;
  24. #ifndef LZMA_LOG_BSR
  25. Byte g_FastPos[1 << kNumLogBits];
  26. class CFastPosInit
  27. {
  28. public:
  29. CFastPosInit() { Init(); }
  30. void Init()
  31. {
  32. const Byte kFastSlots = kNumLogBits * 2;
  33. int c = 2;
  34. g_FastPos[0] = 0;
  35. g_FastPos[1] = 1;
  36. for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++)
  37. {
  38. UInt32 k = (1 << ((slotFast >> 1) - 1));
  39. for (UInt32 j = 0; j < k; j++, c++)
  40. g_FastPos[c] = slotFast;
  41. }
  42. }
  43. } g_FastPosInit;
  44. #endif
  45. void CLiteralEncoder2::Encode(NRangeCoder::CEncoder *rangeEncoder, Byte symbol)
  46. {
  47. UInt32 context = 1;
  48. int i = 8;
  49. do
  50. {
  51. i--;
  52. UInt32 bit = (symbol >> i) & 1;
  53. _encoders[context].Encode(rangeEncoder, bit);
  54. context = (context << 1) | bit;
  55. }
  56. while(i != 0);
  57. }
  58. void CLiteralEncoder2::EncodeMatched(NRangeCoder::CEncoder *rangeEncoder,
  59. Byte matchByte, Byte symbol)
  60. {
  61. UInt32 context = 1;
  62. int i = 8;
  63. do
  64. {
  65. i--;
  66. UInt32 bit = (symbol >> i) & 1;
  67. UInt32 matchBit = (matchByte >> i) & 1;
  68. _encoders[0x100 + (matchBit << 8) + context].Encode(rangeEncoder, bit);
  69. context = (context << 1) | bit;
  70. if (matchBit != bit)
  71. {
  72. while(i != 0)
  73. {
  74. i--;
  75. UInt32 bit = (symbol >> i) & 1;
  76. _encoders[context].Encode(rangeEncoder, bit);
  77. context = (context << 1) | bit;
  78. }
  79. break;
  80. }
  81. }
  82. while(i != 0);
  83. }
  84. UInt32 CLiteralEncoder2::GetPrice(bool matchMode, Byte matchByte, Byte symbol) const
  85. {
  86. UInt32 price = 0;
  87. UInt32 context = 1;
  88. int i = 8;
  89. if (matchMode)
  90. {
  91. do
  92. {
  93. i--;
  94. UInt32 matchBit = (matchByte >> i) & 1;
  95. UInt32 bit = (symbol >> i) & 1;
  96. price += _encoders[0x100 + (matchBit << 8) + context].GetPrice(bit);
  97. context = (context << 1) | bit;
  98. if (matchBit != bit)
  99. break;
  100. }
  101. while (i != 0);
  102. }
  103. while(i != 0)
  104. {
  105. i--;
  106. UInt32 bit = (symbol >> i) & 1;
  107. price += _encoders[context].GetPrice(bit);
  108. context = (context << 1) | bit;
  109. }
  110. return price;
  111. };
  112. namespace NLength {
  113. void CEncoder::Init(UInt32 numPosStates)
  114. {
  115. _choice.Init();
  116. _choice2.Init();
  117. for (UInt32 posState = 0; posState < numPosStates; posState++)
  118. {
  119. _lowCoder[posState].Init();
  120. _midCoder[posState].Init();
  121. }
  122. _highCoder.Init();
  123. }
  124. void CEncoder::Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState)
  125. {
  126. if(symbol < kNumLowSymbols)
  127. {
  128. _choice.Encode(rangeEncoder, 0);
  129. _lowCoder[posState].Encode(rangeEncoder, symbol);
  130. }
  131. else
  132. {
  133. _choice.Encode(rangeEncoder, 1);
  134. if(symbol < kNumLowSymbols + kNumMidSymbols)
  135. {
  136. _choice2.Encode(rangeEncoder, 0);
  137. _midCoder[posState].Encode(rangeEncoder, symbol - kNumLowSymbols);
  138. }
  139. else
  140. {
  141. _choice2.Encode(rangeEncoder, 1);
  142. _highCoder.Encode(rangeEncoder, symbol - kNumLowSymbols - kNumMidSymbols);
  143. }
  144. }
  145. }
  146. void CEncoder::SetPrices(UInt32 posState, UInt32 numSymbols, UInt32 *prices) const
  147. {
  148. UInt32 a0 = _choice.GetPrice0();
  149. UInt32 a1 = _choice.GetPrice1();
  150. UInt32 b0 = a1 + _choice2.GetPrice0();
  151. UInt32 b1 = a1 + _choice2.GetPrice1();
  152. UInt32 i = 0;
  153. for (i = 0; i < kNumLowSymbols; i++)
  154. {
  155. if (i >= numSymbols)
  156. return;
  157. prices[i] = a0 + _lowCoder[posState].GetPrice(i);
  158. }
  159. for (; i < kNumLowSymbols + kNumMidSymbols; i++)
  160. {
  161. if (i >= numSymbols)
  162. return;
  163. prices[i] = b0 + _midCoder[posState].GetPrice(i - kNumLowSymbols);
  164. }
  165. for (; i < numSymbols; i++)
  166. prices[i] = b1 + _highCoder.GetPrice(i - kNumLowSymbols - kNumMidSymbols);
  167. }
  168. }
  169. CEncoder::CEncoder():
  170. _numFastBytes(kNumFastBytesDefault),
  171. _distTableSize(kDefaultDictionaryLogSize * 2),
  172. _posStateBits(2),
  173. _posStateMask(4 - 1),
  174. _numLiteralPosStateBits(0),
  175. _numLiteralContextBits(3),
  176. _dictionarySize(1 << kDefaultDictionaryLogSize),
  177. _matchFinderCycles(0),
  178. #ifdef COMPRESS_MF_MT
  179. _multiThread(false),
  180. #endif
  181. _writeEndMark(false)
  182. {
  183. MatchFinder_Construct(&_matchFinderBase);
  184. // _maxMode = false;
  185. _fastMode = false;
  186. #ifdef COMPRESS_MF_MT
  187. MatchFinderMt_Construct(&_matchFinderMt);
  188. _matchFinderMt.MatchFinder = &_matchFinderBase;
  189. #endif
  190. }
  191. static void *SzAlloc(size_t size) { return BigAlloc(size); }
  192. static void SzFree(void *address) { BigFree(address); }
  193. ISzAlloc g_Alloc = { SzAlloc, SzFree };
  194. CEncoder::~CEncoder()
  195. {
  196. #ifdef COMPRESS_MF_MT
  197. MatchFinderMt_Destruct(&_matchFinderMt, &g_Alloc);
  198. #endif
  199. MatchFinder_Free(&_matchFinderBase, &g_Alloc);
  200. }
  201. static const UInt32 kBigHashDicLimit = (UInt32)1 << 24;
  202. HRESULT CEncoder::Create()
  203. {
  204. if (!_rangeEncoder.Create(1 << 20))
  205. return E_OUTOFMEMORY;
  206. bool btMode = (_matchFinderBase.btMode != 0);
  207. #ifdef COMPRESS_MF_MT
  208. _mtMode = (_multiThread && !_fastMode && btMode);
  209. #endif
  210. if (!_literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits))
  211. return E_OUTOFMEMORY;
  212. _matchFinderBase.bigHash = (_dictionarySize > kBigHashDicLimit);
  213. UInt32 numCycles = 16 + (_numFastBytes >> 1);
  214. if (!btMode)
  215. numCycles >>= 1;
  216. if (_matchFinderCycles != 0)
  217. numCycles = _matchFinderCycles;
  218. _matchFinderBase.cutValue = numCycles;
  219. #ifdef COMPRESS_MF_MT
  220. if (_mtMode)
  221. {
  222. RINOK(MatchFinderMt_Create(&_matchFinderMt, _dictionarySize, kNumOpts, _numFastBytes, kMatchMaxLen, &g_Alloc));
  223. _matchFinderObj = &_matchFinderMt;
  224. MatchFinderMt_CreateVTable(&_matchFinderMt, &_matchFinder);
  225. }
  226. else
  227. #endif
  228. {
  229. if (!MatchFinder_Create(&_matchFinderBase, _dictionarySize, kNumOpts, _numFastBytes, kMatchMaxLen, &g_Alloc))
  230. return E_OUTOFMEMORY;
  231. _matchFinderObj = &_matchFinderBase;
  232. MatchFinder_CreateVTable(&_matchFinderBase, &_matchFinder);
  233. }
  234. return S_OK;
  235. }
  236. inline wchar_t GetUpperChar(wchar_t c)
  237. {
  238. if (c >= 'a' && c <= 'z')
  239. c -= 0x20;
  240. return c;
  241. }
  242. static int ParseMatchFinder(const wchar_t *s, int *btMode, UInt32 *numHashBytes /* , int *skipModeBits */)
  243. {
  244. wchar_t c = GetUpperChar(*s++);
  245. if (c == L'H')
  246. {
  247. if (GetUpperChar(*s++) != L'C')
  248. return 0;
  249. int numHashBytesLoc = (int)(*s++ - L'0');
  250. if (numHashBytesLoc < 4 || numHashBytesLoc > 4)
  251. return 0;
  252. if (*s++ != 0)
  253. return 0;
  254. *btMode = 0;
  255. *numHashBytes = numHashBytesLoc;
  256. return 1;
  257. }
  258. if (c != L'B')
  259. return 0;
  260. if (GetUpperChar(*s++) != L'T')
  261. return 0;
  262. int numHashBytesLoc = (int)(*s++ - L'0');
  263. if (numHashBytesLoc < 2 || numHashBytesLoc > 4)
  264. return 0;
  265. c = GetUpperChar(*s++);
  266. /*
  267. int skipModeBitsLoc = 0;
  268. if (c == L'D')
  269. {
  270. skipModeBitsLoc = 2;
  271. c = GetUpperChar(*s++);
  272. }
  273. */
  274. if (c != L'\0')
  275. return 0;
  276. *btMode = 1;
  277. *numHashBytes = numHashBytesLoc;
  278. // *skipModeBits = skipModeBitsLoc;
  279. return 1;
  280. }
  281. STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs,
  282. const PROPVARIANT *properties, UInt32 numProperties)
  283. {
  284. for (UInt32 i = 0; i < numProperties; i++)
  285. {
  286. const PROPVARIANT &prop = properties[i];
  287. switch(propIDs[i])
  288. {
  289. case NCoderPropID::kNumFastBytes:
  290. {
  291. if (prop.vt != VT_UI4)
  292. return E_INVALIDARG;
  293. UInt32 numFastBytes = prop.ulVal;
  294. if(numFastBytes < 5 || numFastBytes > kMatchMaxLen)
  295. return E_INVALIDARG;
  296. _numFastBytes = numFastBytes;
  297. break;
  298. }
  299. case NCoderPropID::kMatchFinderCycles:
  300. {
  301. if (prop.vt != VT_UI4)
  302. return E_INVALIDARG;
  303. _matchFinderCycles = prop.ulVal;
  304. break;
  305. }
  306. case NCoderPropID::kAlgorithm:
  307. {
  308. if (prop.vt != VT_UI4)
  309. return E_INVALIDARG;
  310. UInt32 maximize = prop.ulVal;
  311. _fastMode = (maximize == 0);
  312. // _maxMode = (maximize >= 2);
  313. break;
  314. }
  315. case NCoderPropID::kMatchFinder:
  316. {
  317. if (prop.vt != VT_BSTR)
  318. return E_INVALIDARG;
  319. if (!ParseMatchFinder(prop.bstrVal, &_matchFinderBase.btMode, &_matchFinderBase.numHashBytes /* , &_matchFinderBase.skipModeBits */))
  320. return E_INVALIDARG;
  321. break;
  322. }
  323. case NCoderPropID::kMultiThread:
  324. {
  325. if (prop.vt != VT_BOOL)
  326. return E_INVALIDARG;
  327. #ifdef COMPRESS_MF_MT
  328. Bool newMultiThread = (prop.boolVal == VARIANT_TRUE);
  329. if (newMultiThread != _multiThread)
  330. {
  331. ReleaseMatchFinder();
  332. _multiThread = newMultiThread;
  333. }
  334. #endif
  335. break;
  336. }
  337. case NCoderPropID::kNumThreads:
  338. {
  339. if (prop.vt != VT_UI4)
  340. return E_INVALIDARG;
  341. #ifdef COMPRESS_MF_MT
  342. Bool newMultiThread = (prop.ulVal > 1) ? True : False;
  343. if (newMultiThread != _multiThread)
  344. {
  345. ReleaseMatchFinder();
  346. _multiThread = newMultiThread;
  347. }
  348. #endif
  349. break;
  350. }
  351. case NCoderPropID::kDictionarySize:
  352. {
  353. const int kDicLogSizeMaxCompress = 30; // must be <= ((kNumLogBits - 1) * 2) + 7 = 31;
  354. if (prop.vt != VT_UI4)
  355. return E_INVALIDARG;
  356. UInt32 dictionarySize = prop.ulVal;
  357. if (dictionarySize < UInt32(1 << kDicLogSizeMin) ||
  358. dictionarySize > UInt32(1 << kDicLogSizeMaxCompress))
  359. return E_INVALIDARG;
  360. _dictionarySize = dictionarySize;
  361. UInt32 dicLogSize;
  362. for(dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++)
  363. if (dictionarySize <= (UInt32(1) << dicLogSize))
  364. break;
  365. _distTableSize = dicLogSize * 2;
  366. break;
  367. }
  368. case NCoderPropID::kPosStateBits:
  369. {
  370. if (prop.vt != VT_UI4)
  371. return E_INVALIDARG;
  372. UInt32 value = prop.ulVal;
  373. if (value > (UInt32)NLength::kNumPosStatesBitsEncodingMax)
  374. return E_INVALIDARG;
  375. _posStateBits = value;
  376. _posStateMask = (1 << _posStateBits) - 1;
  377. break;
  378. }
  379. case NCoderPropID::kLitPosBits:
  380. {
  381. if (prop.vt != VT_UI4)
  382. return E_INVALIDARG;
  383. UInt32 value = prop.ulVal;
  384. if (value > (UInt32)kNumLitPosStatesBitsEncodingMax)
  385. return E_INVALIDARG;
  386. _numLiteralPosStateBits = value;
  387. break;
  388. }
  389. case NCoderPropID::kLitContextBits:
  390. {
  391. if (prop.vt != VT_UI4)
  392. return E_INVALIDARG;
  393. UInt32 value = prop.ulVal;
  394. if (value > (UInt32)kNumLitContextBitsMax)
  395. return E_INVALIDARG;
  396. _numLiteralContextBits = value;
  397. break;
  398. }
  399. case NCoderPropID::kEndMarker:
  400. {
  401. if (prop.vt != VT_BOOL)
  402. return E_INVALIDARG;
  403. SetWriteEndMarkerMode(prop.boolVal == VARIANT_TRUE);
  404. break;
  405. }
  406. default:
  407. return E_INVALIDARG;
  408. }
  409. }
  410. return S_OK;
  411. }
  412. STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
  413. {
  414. const UInt32 kPropSize = 5;
  415. Byte properties[kPropSize];
  416. properties[0] = (Byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits);
  417. for (int i = 0; i < 4; i++)
  418. properties[1 + i] = Byte(_dictionarySize >> (8 * i));
  419. return WriteStream(outStream, properties, kPropSize, NULL);
  420. }
  421. STDMETHODIMP CEncoder::SetOutStream(ISequentialOutStream *outStream)
  422. {
  423. _rangeEncoder.SetStream(outStream);
  424. return S_OK;
  425. }
  426. STDMETHODIMP CEncoder::ReleaseOutStream()
  427. {
  428. _rangeEncoder.ReleaseStream();
  429. return S_OK;
  430. }
  431. HRESULT CEncoder::Init()
  432. {
  433. CBaseState::Init();
  434. _rangeEncoder.Init();
  435. for(int i = 0; i < kNumStates; i++)
  436. {
  437. for (UInt32 j = 0; j <= _posStateMask; j++)
  438. {
  439. _isMatch[i][j].Init();
  440. _isRep0Long[i][j].Init();
  441. }
  442. _isRep[i].Init();
  443. _isRepG0[i].Init();
  444. _isRepG1[i].Init();
  445. _isRepG2[i].Init();
  446. }
  447. _literalEncoder.Init();
  448. {
  449. for(UInt32 i = 0; i < kNumLenToPosStates; i++)
  450. _posSlotEncoder[i].Init();
  451. }
  452. {
  453. for(UInt32 i = 0; i < kNumFullDistances - kEndPosModelIndex; i++)
  454. _posEncoders[i].Init();
  455. }
  456. _lenEncoder.Init(1 << _posStateBits);
  457. _repMatchLenEncoder.Init(1 << _posStateBits);
  458. _posAlignEncoder.Init();
  459. _longestMatchWasFound = false;
  460. _optimumEndIndex = 0;
  461. _optimumCurrentIndex = 0;
  462. _additionalOffset = 0;
  463. return S_OK;
  464. }
  465. #ifdef SHOW_STAT
  466. static int ttt = 0;
  467. #endif
  468. void CEncoder::MovePos(UInt32 num)
  469. {
  470. #ifdef SHOW_STAT
  471. ttt += num;
  472. printf("\n MovePos %d", num);
  473. #endif
  474. if (num != 0)
  475. {
  476. _additionalOffset += num;
  477. _matchFinder.Skip(_matchFinderObj, num);
  478. }
  479. }
  480. UInt32 CEncoder::Backward(UInt32 &backRes, UInt32 cur)
  481. {
  482. _optimumEndIndex = cur;
  483. UInt32 posMem = _optimum[cur].PosPrev;
  484. UInt32 backMem = _optimum[cur].BackPrev;
  485. do
  486. {
  487. if (_optimum[cur].Prev1IsChar)
  488. {
  489. _optimum[posMem].MakeAsChar();
  490. _optimum[posMem].PosPrev = posMem - 1;
  491. if (_optimum[cur].Prev2)
  492. {
  493. _optimum[posMem - 1].Prev1IsChar = false;
  494. _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2;
  495. _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2;
  496. }
  497. }
  498. UInt32 posPrev = posMem;
  499. UInt32 backCur = backMem;
  500. backMem = _optimum[posPrev].BackPrev;
  501. posMem = _optimum[posPrev].PosPrev;
  502. _optimum[posPrev].BackPrev = backCur;
  503. _optimum[posPrev].PosPrev = cur;
  504. cur = posPrev;
  505. }
  506. while(cur != 0);
  507. backRes = _optimum[0].BackPrev;
  508. _optimumCurrentIndex = _optimum[0].PosPrev;
  509. return _optimumCurrentIndex;
  510. }
  511. /*
  512. Out:
  513. (lenRes == 1) && (backRes == 0xFFFFFFFF) means Literal
  514. */
  515. UInt32 CEncoder::GetOptimum(UInt32 position, UInt32 &backRes)
  516. {
  517. if(_optimumEndIndex != _optimumCurrentIndex)
  518. {
  519. const COptimal &optimum = _optimum[_optimumCurrentIndex];
  520. UInt32 lenRes = optimum.PosPrev - _optimumCurrentIndex;
  521. backRes = optimum.BackPrev;
  522. _optimumCurrentIndex = optimum.PosPrev;
  523. return lenRes;
  524. }
  525. _optimumCurrentIndex = _optimumEndIndex = 0;
  526. UInt32 numAvailableBytes = _matchFinder.GetNumAvailableBytes(_matchFinderObj);
  527. UInt32 lenMain, numDistancePairs;
  528. if (!_longestMatchWasFound)
  529. {
  530. lenMain = ReadMatchDistances(numDistancePairs);
  531. }
  532. else
  533. {
  534. lenMain = _longestMatchLength;
  535. numDistancePairs = _numDistancePairs;
  536. _longestMatchWasFound = false;
  537. }
  538. const Byte *data = _matchFinder.GetPointerToCurrentPos(_matchFinderObj) - 1;
  539. if (numAvailableBytes < 2)
  540. {
  541. backRes = (UInt32)(-1);
  542. return 1;
  543. }
  544. if (numAvailableBytes > kMatchMaxLen)
  545. numAvailableBytes = kMatchMaxLen;
  546. UInt32 reps[kNumRepDistances];
  547. UInt32 repLens[kNumRepDistances];
  548. UInt32 repMaxIndex = 0;
  549. UInt32 i;
  550. for(i = 0; i < kNumRepDistances; i++)
  551. {
  552. reps[i] = _repDistances[i];
  553. const Byte *data2 = data - (reps[i] + 1);
  554. if (data[0] != data2[0] || data[1] != data2[1])
  555. {
  556. repLens[i] = 0;
  557. continue;
  558. }
  559. UInt32 lenTest;
  560. for (lenTest = 2; lenTest < numAvailableBytes && data[lenTest] == data2[lenTest]; lenTest++);
  561. repLens[i] = lenTest;
  562. if (lenTest > repLens[repMaxIndex])
  563. repMaxIndex = i;
  564. }
  565. if(repLens[repMaxIndex] >= _numFastBytes)
  566. {
  567. backRes = repMaxIndex;
  568. UInt32 lenRes = repLens[repMaxIndex];
  569. MovePos(lenRes - 1);
  570. return lenRes;
  571. }
  572. UInt32 *matchDistances = _matchDistances;
  573. if(lenMain >= _numFastBytes)
  574. {
  575. backRes = matchDistances[numDistancePairs - 1] + kNumRepDistances;
  576. MovePos(lenMain - 1);
  577. return lenMain;
  578. }
  579. Byte currentByte = *data;
  580. Byte matchByte = *(data - (reps[0] + 1));
  581. if(lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2)
  582. {
  583. backRes = (UInt32)-1;
  584. return 1;
  585. }
  586. _optimum[0].State = _state;
  587. UInt32 posState = (position & _posStateMask);
  588. _optimum[1].Price = _isMatch[_state.Index][posState].GetPrice0() +
  589. _literalEncoder.GetSubCoder(position, _previousByte)->GetPrice(!_state.IsCharState(), matchByte, currentByte);
  590. _optimum[1].MakeAsChar();
  591. UInt32 matchPrice = _isMatch[_state.Index][posState].GetPrice1();
  592. UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1();
  593. if(matchByte == currentByte)
  594. {
  595. UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState);
  596. if(shortRepPrice < _optimum[1].Price)
  597. {
  598. _optimum[1].Price = shortRepPrice;
  599. _optimum[1].MakeAsShortRep();
  600. }
  601. }
  602. UInt32 lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]);
  603. if(lenEnd < 2)
  604. {
  605. backRes = _optimum[1].BackPrev;
  606. return 1;
  607. }
  608. _optimum[1].PosPrev = 0;
  609. for (i = 0; i < kNumRepDistances; i++)
  610. _optimum[0].Backs[i] = reps[i];
  611. UInt32 len = lenEnd;
  612. do
  613. _optimum[len--].Price = kIfinityPrice;
  614. while (len >= 2);
  615. for(i = 0; i < kNumRepDistances; i++)
  616. {
  617. UInt32 repLen = repLens[i];
  618. if (repLen < 2)
  619. continue;
  620. UInt32 price = repMatchPrice + GetPureRepPrice(i, _state, posState);
  621. do
  622. {
  623. UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState);
  624. COptimal &optimum = _optimum[repLen];
  625. if (curAndLenPrice < optimum.Price)
  626. {
  627. optimum.Price = curAndLenPrice;
  628. optimum.PosPrev = 0;
  629. optimum.BackPrev = i;
  630. optimum.Prev1IsChar = false;
  631. }
  632. }
  633. while(--repLen >= 2);
  634. }
  635. UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0();
  636. len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2);
  637. if (len <= lenMain)
  638. {
  639. UInt32 offs = 0;
  640. while (len > matchDistances[offs])
  641. offs += 2;
  642. for(; ; len++)
  643. {
  644. UInt32 distance = matchDistances[offs + 1];
  645. UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState);
  646. COptimal &optimum = _optimum[len];
  647. if (curAndLenPrice < optimum.Price)
  648. {
  649. optimum.Price = curAndLenPrice;
  650. optimum.PosPrev = 0;
  651. optimum.BackPrev = distance + kNumRepDistances;
  652. optimum.Prev1IsChar = false;
  653. }
  654. if (len == matchDistances[offs])
  655. {
  656. offs += 2;
  657. if (offs == numDistancePairs)
  658. break;
  659. }
  660. }
  661. }
  662. UInt32 cur = 0;
  663. for (;;)
  664. {
  665. cur++;
  666. if(cur == lenEnd)
  667. {
  668. return Backward(backRes, cur);
  669. }
  670. UInt32 numAvailableBytesFull = _matchFinder.GetNumAvailableBytes(_matchFinderObj);
  671. UInt32 newLen, numDistancePairs;
  672. newLen = ReadMatchDistances(numDistancePairs);
  673. if(newLen >= _numFastBytes)
  674. {
  675. _numDistancePairs = numDistancePairs;
  676. _longestMatchLength = newLen;
  677. _longestMatchWasFound = true;
  678. return Backward(backRes, cur);
  679. }
  680. position++;
  681. COptimal &curOptimum = _optimum[cur];
  682. UInt32 posPrev = curOptimum.PosPrev;
  683. CState state;
  684. if (curOptimum.Prev1IsChar)
  685. {
  686. posPrev--;
  687. if (curOptimum.Prev2)
  688. {
  689. state = _optimum[curOptimum.PosPrev2].State;
  690. if (curOptimum.BackPrev2 < kNumRepDistances)
  691. state.UpdateRep();
  692. else
  693. state.UpdateMatch();
  694. }
  695. else
  696. state = _optimum[posPrev].State;
  697. state.UpdateChar();
  698. }
  699. else
  700. state = _optimum[posPrev].State;
  701. if (posPrev == cur - 1)
  702. {
  703. if (curOptimum.IsShortRep())
  704. state.UpdateShortRep();
  705. else
  706. state.UpdateChar();
  707. }
  708. else
  709. {
  710. UInt32 pos;
  711. if (curOptimum.Prev1IsChar && curOptimum.Prev2)
  712. {
  713. posPrev = curOptimum.PosPrev2;
  714. pos = curOptimum.BackPrev2;
  715. state.UpdateRep();
  716. }
  717. else
  718. {
  719. pos = curOptimum.BackPrev;
  720. if (pos < kNumRepDistances)
  721. state.UpdateRep();
  722. else
  723. state.UpdateMatch();
  724. }
  725. const COptimal &prevOptimum = _optimum[posPrev];
  726. if (pos < kNumRepDistances)
  727. {
  728. reps[0] = prevOptimum.Backs[pos];
  729. UInt32 i;
  730. for(i = 1; i <= pos; i++)
  731. reps[i] = prevOptimum.Backs[i - 1];
  732. for(; i < kNumRepDistances; i++)
  733. reps[i] = prevOptimum.Backs[i];
  734. }
  735. else
  736. {
  737. reps[0] = (pos - kNumRepDistances);
  738. for(UInt32 i = 1; i < kNumRepDistances; i++)
  739. reps[i] = prevOptimum.Backs[i - 1];
  740. }
  741. }
  742. curOptimum.State = state;
  743. for(UInt32 i = 0; i < kNumRepDistances; i++)
  744. curOptimum.Backs[i] = reps[i];
  745. UInt32 curPrice = curOptimum.Price;
  746. const Byte *data = _matchFinder.GetPointerToCurrentPos(_matchFinderObj) - 1;
  747. const Byte currentByte = *data;
  748. const Byte matchByte = *(data - (reps[0] + 1));
  749. UInt32 posState = (position & _posStateMask);
  750. UInt32 curAnd1Price = curPrice +
  751. _isMatch[state.Index][posState].GetPrice0() +
  752. _literalEncoder.GetSubCoder(position, *(data - 1))->GetPrice(!state.IsCharState(), matchByte, currentByte);
  753. COptimal &nextOptimum = _optimum[cur + 1];
  754. bool nextIsChar = false;
  755. if (curAnd1Price < nextOptimum.Price)
  756. {
  757. nextOptimum.Price = curAnd1Price;
  758. nextOptimum.PosPrev = cur;
  759. nextOptimum.MakeAsChar();
  760. nextIsChar = true;
  761. }
  762. UInt32 matchPrice = curPrice + _isMatch[state.Index][posState].GetPrice1();
  763. UInt32 repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1();
  764. if(matchByte == currentByte &&
  765. !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0))
  766. {
  767. UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState);
  768. if(shortRepPrice <= nextOptimum.Price)
  769. {
  770. nextOptimum.Price = shortRepPrice;
  771. nextOptimum.PosPrev = cur;
  772. nextOptimum.MakeAsShortRep();
  773. nextIsChar = true;
  774. }
  775. }
  776. /*
  777. if(newLen == 2 && matchDistances[2] >= kDistLimit2) // test it maybe set 2000 ?
  778. continue;
  779. */
  780. numAvailableBytesFull = MyMin(kNumOpts - 1 - cur, numAvailableBytesFull);
  781. UInt32 numAvailableBytes = numAvailableBytesFull;
  782. if (numAvailableBytes < 2)
  783. continue;
  784. if (numAvailableBytes > _numFastBytes)
  785. numAvailableBytes = _numFastBytes;
  786. if (!nextIsChar && matchByte != currentByte) // speed optimization
  787. {
  788. // try Literal + rep0
  789. const Byte *data2 = data - (reps[0] + 1);
  790. UInt32 limit = MyMin(numAvailableBytesFull, _numFastBytes + 1);
  791. UInt32 temp;
  792. for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++);
  793. UInt32 lenTest2 = temp - 1;
  794. if (lenTest2 >= 2)
  795. {
  796. CState state2 = state;
  797. state2.UpdateChar();
  798. UInt32 posStateNext = (position + 1) & _posStateMask;
  799. UInt32 nextRepMatchPrice = curAnd1Price +
  800. _isMatch[state2.Index][posStateNext].GetPrice1() +
  801. _isRep[state2.Index].GetPrice1();
  802. // for (; lenTest2 >= 2; lenTest2--)
  803. {
  804. UInt32 offset = cur + 1 + lenTest2;
  805. while(lenEnd < offset)
  806. _optimum[++lenEnd].Price = kIfinityPrice;
  807. UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(
  808. 0, lenTest2, state2, posStateNext);
  809. COptimal &optimum = _optimum[offset];
  810. if (curAndLenPrice < optimum.Price)
  811. {
  812. optimum.Price = curAndLenPrice;
  813. optimum.PosPrev = cur + 1;
  814. optimum.BackPrev = 0;
  815. optimum.Prev1IsChar = true;
  816. optimum.Prev2 = false;
  817. }
  818. }
  819. }
  820. }
  821. UInt32 startLen = 2; // speed optimization
  822. for(UInt32 repIndex = 0; repIndex < kNumRepDistances; repIndex++)
  823. {
  824. // UInt32 repLen = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], newLen); // test it;
  825. const Byte *data2 = data - (reps[repIndex] + 1);
  826. if (data[0] != data2[0] || data[1] != data2[1])
  827. continue;
  828. UInt32 lenTest;
  829. for (lenTest = 2; lenTest < numAvailableBytes && data[lenTest] == data2[lenTest]; lenTest++);
  830. while(lenEnd < cur + lenTest)
  831. _optimum[++lenEnd].Price = kIfinityPrice;
  832. UInt32 lenTestTemp = lenTest;
  833. UInt32 price = repMatchPrice + GetPureRepPrice(repIndex, state, posState);
  834. do
  835. {
  836. UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(lenTest - 2, posState);
  837. COptimal &optimum = _optimum[cur + lenTest];
  838. if (curAndLenPrice < optimum.Price)
  839. {
  840. optimum.Price = curAndLenPrice;
  841. optimum.PosPrev = cur;
  842. optimum.BackPrev = repIndex;
  843. optimum.Prev1IsChar = false;
  844. }
  845. }
  846. while(--lenTest >= 2);
  847. lenTest = lenTestTemp;
  848. if (repIndex == 0)
  849. startLen = lenTest + 1;
  850. // if (_maxMode)
  851. {
  852. UInt32 lenTest2 = lenTest + 1;
  853. UInt32 limit = MyMin(numAvailableBytesFull, lenTest2 + _numFastBytes);
  854. for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);
  855. lenTest2 -= lenTest + 1;
  856. if (lenTest2 >= 2)
  857. {
  858. CState state2 = state;
  859. state2.UpdateRep();
  860. UInt32 posStateNext = (position + lenTest) & _posStateMask;
  861. UInt32 curAndLenCharPrice =
  862. price + _repMatchLenEncoder.GetPrice(lenTest - 2, posState) +
  863. _isMatch[state2.Index][posStateNext].GetPrice0() +
  864. _literalEncoder.GetSubCoder(position + lenTest, data[lenTest - 1])->GetPrice(
  865. true, data2[lenTest], data[lenTest]);
  866. state2.UpdateChar();
  867. posStateNext = (position + lenTest + 1) & _posStateMask;
  868. UInt32 nextRepMatchPrice = curAndLenCharPrice +
  869. _isMatch[state2.Index][posStateNext].GetPrice1() +
  870. _isRep[state2.Index].GetPrice1();
  871. // for(; lenTest2 >= 2; lenTest2--)
  872. {
  873. UInt32 offset = cur + lenTest + 1 + lenTest2;
  874. while(lenEnd < offset)
  875. _optimum[++lenEnd].Price = kIfinityPrice;
  876. UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(
  877. 0, lenTest2, state2, posStateNext);
  878. COptimal &optimum = _optimum[offset];
  879. if (curAndLenPrice < optimum.Price)
  880. {
  881. optimum.Price = curAndLenPrice;
  882. optimum.PosPrev = cur + lenTest + 1;
  883. optimum.BackPrev = 0;
  884. optimum.Prev1IsChar = true;
  885. optimum.Prev2 = true;
  886. optimum.PosPrev2 = cur;
  887. optimum.BackPrev2 = repIndex;
  888. }
  889. }
  890. }
  891. }
  892. }
  893. // for(UInt32 lenTest = 2; lenTest <= newLen; lenTest++)
  894. if (newLen > numAvailableBytes)
  895. {
  896. newLen = numAvailableBytes;
  897. for (numDistancePairs = 0; newLen > matchDistances[numDistancePairs]; numDistancePairs += 2);
  898. matchDistances[numDistancePairs] = newLen;
  899. numDistancePairs += 2;
  900. }
  901. if (newLen >= startLen)
  902. {
  903. UInt32 normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0();
  904. while(lenEnd < cur + newLen)
  905. _optimum[++lenEnd].Price = kIfinityPrice;
  906. UInt32 offs = 0;
  907. while(startLen > matchDistances[offs])
  908. offs += 2;
  909. UInt32 curBack = matchDistances[offs + 1];
  910. UInt32 posSlot = GetPosSlot2(curBack);
  911. for(UInt32 lenTest = /*2*/ startLen; ; lenTest++)
  912. {
  913. UInt32 curAndLenPrice = normalMatchPrice;
  914. UInt32 lenToPosState = GetLenToPosState(lenTest);
  915. if (curBack < kNumFullDistances)
  916. curAndLenPrice += _distancesPrices[lenToPosState][curBack];
  917. else
  918. curAndLenPrice += _posSlotPrices[lenToPosState][posSlot] + _alignPrices[curBack & kAlignMask];
  919. curAndLenPrice += _lenEncoder.GetPrice(lenTest - kMatchMinLen, posState);
  920. COptimal &optimum = _optimum[cur + lenTest];
  921. if (curAndLenPrice < optimum.Price)
  922. {
  923. optimum.Price = curAndLenPrice;
  924. optimum.PosPrev = cur;
  925. optimum.BackPrev = curBack + kNumRepDistances;
  926. optimum.Prev1IsChar = false;
  927. }
  928. if (/*_maxMode && */lenTest == matchDistances[offs])
  929. {
  930. // Try Match + Literal + Rep0
  931. const Byte *data2 = data - (curBack + 1);
  932. UInt32 lenTest2 = lenTest + 1;
  933. UInt32 limit = MyMin(numAvailableBytesFull, lenTest2 + _numFastBytes);
  934. for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);
  935. lenTest2 -= lenTest + 1;
  936. if (lenTest2 >= 2)
  937. {
  938. CState state2 = state;
  939. state2.UpdateMatch();
  940. UInt32 posStateNext = (position + lenTest) & _posStateMask;
  941. UInt32 curAndLenCharPrice = curAndLenPrice +
  942. _isMatch[state2.Index][posStateNext].GetPrice0() +
  943. _literalEncoder.GetSubCoder(position + lenTest, data[lenTest - 1])->GetPrice(
  944. true, data2[lenTest], data[lenTest]);
  945. state2.UpdateChar();
  946. posStateNext = (posStateNext + 1) & _posStateMask;
  947. UInt32 nextRepMatchPrice = curAndLenCharPrice +
  948. _isMatch[state2.Index][posStateNext].GetPrice1() +
  949. _isRep[state2.Index].GetPrice1();
  950. // for(; lenTest2 >= 2; lenTest2--)
  951. {
  952. UInt32 offset = cur + lenTest + 1 + lenTest2;
  953. while(lenEnd < offset)
  954. _optimum[++lenEnd].Price = kIfinityPrice;
  955. UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext);
  956. COptimal &optimum = _optimum[offset];
  957. if (curAndLenPrice < optimum.Price)
  958. {
  959. optimum.Price = curAndLenPrice;
  960. optimum.PosPrev = cur + lenTest + 1;
  961. optimum.BackPrev = 0;
  962. optimum.Prev1IsChar = true;
  963. optimum.Prev2 = true;
  964. optimum.PosPrev2 = cur;
  965. optimum.BackPrev2 = curBack + kNumRepDistances;
  966. }
  967. }
  968. }
  969. offs += 2;
  970. if (offs == numDistancePairs)
  971. break;
  972. curBack = matchDistances[offs + 1];
  973. if (curBack >= kNumFullDistances)
  974. posSlot = GetPosSlot2(curBack);
  975. }
  976. }
  977. }
  978. }
  979. }
  980. static inline bool ChangePair(UInt32 smallDist, UInt32 bigDist)
  981. {
  982. return ((bigDist >> 7) > smallDist);
  983. }
  984. UInt32 CEncoder::ReadMatchDistances(UInt32 &numDistancePairs)
  985. {
  986. UInt32 lenRes = 0;
  987. numDistancePairs = _matchFinder.GetMatches(_matchFinderObj, _matchDistances);
  988. #ifdef SHOW_STAT
  989. printf("\n i = %d numPairs = %d ", ttt, numDistancePairs / 2);
  990. if (ttt >= 61994)
  991. ttt = ttt;
  992. ttt++;
  993. for (UInt32 i = 0; i < numDistancePairs; i += 2)
  994. printf("%2d %6d | ", _matchDistances[i], _matchDistances[i + 1]);
  995. #endif
  996. if (numDistancePairs > 0)
  997. {
  998. lenRes = _matchDistances[numDistancePairs - 2];
  999. if (lenRes == _numFastBytes)
  1000. {
  1001. UInt32 numAvail = _matchFinder.GetNumAvailableBytes(_matchFinderObj) + 1;
  1002. const Byte *pby = _matchFinder.GetPointerToCurrentPos(_matchFinderObj) - 1;
  1003. UInt32 distance = _matchDistances[numDistancePairs - 1] + 1;
  1004. if (numAvail > kMatchMaxLen)
  1005. numAvail = kMatchMaxLen;
  1006. const Byte *pby2 = pby - distance;
  1007. for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++);
  1008. }
  1009. }
  1010. _additionalOffset++;
  1011. return lenRes;
  1012. }
  1013. UInt32 CEncoder::GetOptimumFast(UInt32 &backRes)
  1014. {
  1015. UInt32 numAvailableBytes = _matchFinder.GetNumAvailableBytes(_matchFinderObj);
  1016. UInt32 lenMain, numDistancePairs;
  1017. if (!_longestMatchWasFound)
  1018. {
  1019. lenMain = ReadMatchDistances(numDistancePairs);
  1020. }
  1021. else
  1022. {
  1023. lenMain = _longestMatchLength;
  1024. numDistancePairs = _numDistancePairs;
  1025. _longestMatchWasFound = false;
  1026. }
  1027. const Byte *data = _matchFinder.GetPointerToCurrentPos(_matchFinderObj) - 1;
  1028. if (numAvailableBytes > kMatchMaxLen)
  1029. numAvailableBytes = kMatchMaxLen;
  1030. if (numAvailableBytes < 2)
  1031. {
  1032. backRes = (UInt32)(-1);
  1033. return 1;
  1034. }
  1035. UInt32 repLens[kNumRepDistances];
  1036. UInt32 repMaxIndex = 0;
  1037. for(UInt32 i = 0; i < kNumRepDistances; i++)
  1038. {
  1039. const Byte *data2 = data - (_repDistances[i] + 1);
  1040. if (data[0] != data2[0] || data[1] != data2[1])
  1041. {
  1042. repLens[i] = 0;
  1043. continue;
  1044. }
  1045. UInt32 len;
  1046. for (len = 2; len < numAvailableBytes && data[len] == data2[len]; len++);
  1047. if(len >= _numFastBytes)
  1048. {
  1049. backRes = i;
  1050. MovePos(len - 1);
  1051. return len;
  1052. }
  1053. repLens[i] = len;
  1054. if (len > repLens[repMaxIndex])
  1055. repMaxIndex = i;
  1056. }
  1057. UInt32 *matchDistances = _matchDistances;
  1058. if(lenMain >= _numFastBytes)
  1059. {
  1060. backRes = matchDistances[numDistancePairs - 1] + kNumRepDistances;
  1061. MovePos(lenMain - 1);
  1062. return lenMain;
  1063. }
  1064. UInt32 backMain = 0; // for GCC
  1065. if (lenMain >= 2)
  1066. {
  1067. backMain = matchDistances[numDistancePairs - 1];
  1068. while (numDistancePairs > 2 && lenMain == matchDistances[numDistancePairs - 4] + 1)
  1069. {
  1070. if (!ChangePair(matchDistances[numDistancePairs - 3], backMain))
  1071. break;
  1072. numDistancePairs -= 2;
  1073. lenMain = matchDistances[numDistancePairs - 2];
  1074. backMain = matchDistances[numDistancePairs - 1];
  1075. }
  1076. if (lenMain == 2 && backMain >= 0x80)
  1077. lenMain = 1;
  1078. }
  1079. if (repLens[repMaxIndex] >= 2)
  1080. {
  1081. if (repLens[repMaxIndex] + 1 >= lenMain ||
  1082. repLens[repMaxIndex] + 2 >= lenMain && (backMain > (1 << 9)) ||
  1083. repLens[repMaxIndex] + 3 >= lenMain && (backMain > (1 << 15)))
  1084. {
  1085. backRes = repMaxIndex;
  1086. UInt32 lenRes = repLens[repMaxIndex];
  1087. MovePos(lenRes - 1);
  1088. return lenRes;
  1089. }
  1090. }
  1091. if (lenMain >= 2 && numAvailableBytes > 2)
  1092. {
  1093. numAvailableBytes = _matchFinder.GetNumAvailableBytes(_matchFinderObj);
  1094. _longestMatchLength = ReadMatchDistances(_numDistancePairs);
  1095. if (_longestMatchLength >= 2)
  1096. {
  1097. UInt32 newDistance = matchDistances[_numDistancePairs - 1];
  1098. if (_longestMatchLength >= lenMain && newDistance < backMain ||
  1099. _longestMatchLength == lenMain + 1 && !ChangePair(backMain, newDistance) ||
  1100. _longestMatchLength > lenMain + 1 ||
  1101. _longestMatchLength + 1 >= lenMain && lenMain >= 3 && ChangePair(newDistance, backMain))
  1102. {
  1103. _longestMatchWasFound = true;
  1104. backRes = UInt32(-1);
  1105. return 1;
  1106. }
  1107. }
  1108. data = _matchFinder.GetPointerToCurrentPos(_matchFinderObj) - 1;
  1109. for(UInt32 i = 0; i < kNumRepDistances; i++)
  1110. {
  1111. const Byte *data2 = data - (_repDistances[i] + 1);
  1112. if (data[1] != data2[1] || data[2] != data2[2])
  1113. {
  1114. repLens[i] = 0;
  1115. continue;
  1116. }
  1117. UInt32 len;
  1118. for (len = 2; len < numAvailableBytes && data[len] == data2[len]; len++);
  1119. if (len + 1 >= lenMain)
  1120. {
  1121. _longestMatchWasFound = true;
  1122. backRes = UInt32(-1);
  1123. return 1;
  1124. }
  1125. }
  1126. backRes = backMain + kNumRepDistances;
  1127. MovePos(lenMain - 2);
  1128. return lenMain;
  1129. }
  1130. backRes = UInt32(-1);
  1131. return 1;
  1132. }
  1133. HRESULT CEncoder::Flush(UInt32 nowPos)
  1134. {
  1135. // ReleaseMFStream();
  1136. if (_matchFinderBase.result != SZ_OK)
  1137. return _matchFinderBase.result;
  1138. WriteEndMarker(nowPos & _posStateMask);
  1139. _rangeEncoder.FlushData();
  1140. return _rangeEncoder.FlushStream();
  1141. }
  1142. void CEncoder::WriteEndMarker(UInt32 posState)
  1143. {
  1144. // This function for writing End Mark for stream version of LZMA.
  1145. // In current version this feature is not used.
  1146. if (!_writeEndMark)
  1147. return;
  1148. _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 1);
  1149. _isRep[_state.Index].Encode(&_rangeEncoder, 0);
  1150. _state.UpdateMatch();
  1151. UInt32 len = kMatchMinLen; // kMatchMaxLen;
  1152. _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState, !_fastMode);
  1153. UInt32 posSlot = (1 << kNumPosSlotBits) - 1;
  1154. UInt32 lenToPosState = GetLenToPosState(len);
  1155. _posSlotEncoder[lenToPosState].Encode(&_rangeEncoder, posSlot);
  1156. UInt32 footerBits = 30;
  1157. UInt32 posReduced = (UInt32(1) << footerBits) - 1;
  1158. _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits);
  1159. _posAlignEncoder.ReverseEncode(&_rangeEncoder, posReduced & kAlignMask);
  1160. }
  1161. HRESULT CEncoder::CodeReal(ISequentialInStream *inStream,
  1162. ISequentialOutStream *outStream,
  1163. const UInt64 *inSize, const UInt64 *outSize,
  1164. ICompressProgressInfo *progress)
  1165. {
  1166. // _needReleaseMFStream = false;
  1167. #ifdef COMPRESS_MF_MT
  1168. #ifdef USE_ALLOCA
  1169. alloca(0x300);
  1170. #endif
  1171. #endif
  1172. CCoderReleaser coderReleaser(this);
  1173. RINOK(SetStreams(inStream, outStream, inSize, outSize));
  1174. for (;;)
  1175. {
  1176. UInt64 processedInSize;
  1177. UInt64 processedOutSize;
  1178. Int32 finished;
  1179. RINOK(CodeOneBlock(&processedInSize, &processedOutSize, &finished));
  1180. if (finished != 0)
  1181. break;
  1182. if (progress != 0)
  1183. {
  1184. RINOK(progress->SetRatioInfo(&processedInSize, &processedOutSize));
  1185. }
  1186. }
  1187. return S_OK;
  1188. }
  1189. HRESULT CEncoder::SetStreams(ISequentialInStream *inStream,
  1190. ISequentialOutStream *outStream,
  1191. const UInt64 * /* inSize */, const UInt64 * /* outSize */)
  1192. {
  1193. _inStream = inStream;
  1194. _finished = false;
  1195. RINOK(Create());
  1196. RINOK(SetOutStream(outStream));
  1197. RINOK(Init());
  1198. if (!_fastMode)
  1199. {
  1200. FillDistancesPrices();
  1201. FillAlignPrices();
  1202. }
  1203. _lenEncoder.SetTableSize(_numFastBytes + 1 - kMatchMinLen);
  1204. _lenEncoder.UpdateTables(1 << _posStateBits);
  1205. _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - kMatchMinLen);
  1206. _repMatchLenEncoder.UpdateTables(1 << _posStateBits);
  1207. nowPos64 = 0;
  1208. return S_OK;
  1209. }
  1210. static HRes MyRead(void *object, void *data, UInt32 size, UInt32 *processedSize)
  1211. {
  1212. return (HRes)((CSeqInStream *)object)->RealStream->Read(data, size, processedSize);
  1213. }
  1214. HRESULT CEncoder::CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished)
  1215. {
  1216. if (_inStream != 0)
  1217. {
  1218. _seqInStream.RealStream = _inStream;
  1219. _seqInStream.SeqInStream.Read = MyRead;
  1220. _matchFinderBase.stream = &_seqInStream.SeqInStream;
  1221. _matchFinder.Init(_matchFinderObj);
  1222. _needReleaseMFStream = true;
  1223. _inStream = 0;
  1224. }
  1225. *finished = 1;
  1226. if (_finished)
  1227. return _matchFinderBase.result;
  1228. _finished = true;
  1229. if (nowPos64 == 0)
  1230. {
  1231. if (_matchFinder.GetNumAvailableBytes(_matchFinderObj) == 0)
  1232. return Flush((UInt32)nowPos64);
  1233. UInt32 len, numDistancePairs;
  1234. len = ReadMatchDistances(numDistancePairs);
  1235. UInt32 posState = UInt32(nowPos64) & _posStateMask;
  1236. _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0);
  1237. _state.UpdateChar();
  1238. Byte curByte = _matchFinder.GetIndexByte(_matchFinderObj, 0 - _additionalOffset);
  1239. _literalEncoder.GetSubCoder(UInt32(nowPos64), _previousByte)->Encode(&_rangeEncoder, curByte);
  1240. _previousByte = curByte;
  1241. _additionalOffset--;
  1242. nowPos64++;
  1243. }
  1244. UInt32 nowPos32 = (UInt32)nowPos64;
  1245. UInt32 progressPosValuePrev = nowPos32;
  1246. if (_matchFinder.GetNumAvailableBytes(_matchFinderObj) == 0)
  1247. return Flush(nowPos32);
  1248. for (;;)
  1249. {
  1250. #ifdef _NO_EXCEPTIONS
  1251. if (_rangeEncoder.Stream.ErrorCode != S_OK)
  1252. return _rangeEncoder.Stream.ErrorCode;
  1253. #endif
  1254. UInt32 pos, len;
  1255. if (_fastMode)
  1256. len = GetOptimumFast(pos);
  1257. else
  1258. len = GetOptimum(nowPos32, pos);
  1259. UInt32 posState = nowPos32 & _posStateMask;
  1260. if(len == 1 && pos == 0xFFFFFFFF)
  1261. {
  1262. _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0);
  1263. Byte curByte = _matchFinder.GetIndexByte(_matchFinderObj, 0 - _additionalOffset);
  1264. CLiteralEncoder2 *subCoder = _literalEncoder.GetSubCoder(nowPos32, _previousByte);
  1265. if(_state.IsCharState())
  1266. subCoder->Encode(&_rangeEncoder, curByte);
  1267. else
  1268. {
  1269. Byte matchByte = _matchFinder.GetIndexByte(_matchFinderObj, 0 - _repDistances[0] - 1 - _additionalOffset);
  1270. subCoder->EncodeMatched(&_rangeEncoder, matchByte, curByte);
  1271. }
  1272. _state.UpdateChar();
  1273. _previousByte = curByte;
  1274. }
  1275. else
  1276. {
  1277. _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 1);
  1278. if(pos < kNumRepDistances)
  1279. {
  1280. _isRep[_state.Index].Encode(&_rangeEncoder, 1);
  1281. if(pos == 0)
  1282. {
  1283. _isRepG0[_state.Index].Encode(&_rangeEncoder, 0);
  1284. _isRep0Long[_state.Index][posState].Encode(&_rangeEncoder, ((len == 1) ? 0 : 1));
  1285. }
  1286. else
  1287. {
  1288. UInt32 distance = _repDistances[pos];
  1289. _isRepG0[_state.Index].Encode(&_rangeEncoder, 1);
  1290. if (pos == 1)
  1291. _isRepG1[_state.Index].Encode(&_rangeEncoder, 0);
  1292. else
  1293. {
  1294. _isRepG1[_state.Index].Encode(&_rangeEncoder, 1);
  1295. _isRepG2[_state.Index].Encode(&_rangeEncoder, pos - 2);
  1296. if (pos == 3)
  1297. _repDistances[3] = _repDistances[2];
  1298. _repDistances[2] = _repDistances[1];
  1299. }
  1300. _repDistances[1] = _repDistances[0];
  1301. _repDistances[0] = distance;
  1302. }
  1303. if (len == 1)
  1304. _state.UpdateShortRep();
  1305. else
  1306. {
  1307. _repMatchLenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState, !_fastMode);
  1308. _state.UpdateRep();
  1309. }
  1310. }
  1311. else
  1312. {
  1313. _isRep[_state.Index].Encode(&_rangeEncoder, 0);
  1314. _state.UpdateMatch();
  1315. _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState, !_fastMode);
  1316. pos -= kNumRepDistances;
  1317. UInt32 posSlot = GetPosSlot(pos);
  1318. _posSlotEncoder[GetLenToPosState(len)].Encode(&_rangeEncoder, posSlot);
  1319. if (posSlot >= kStartPosModelIndex)
  1320. {
  1321. UInt32 footerBits = ((posSlot >> 1) - 1);
  1322. UInt32 base = ((2 | (posSlot & 1)) << footerBits);
  1323. UInt32 posReduced = pos - base;
  1324. if (posSlot < kEndPosModelIndex)
  1325. NRangeCoder::ReverseBitTreeEncode(_posEncoders + base - posSlot - 1,
  1326. &_rangeEncoder, footerBits, posReduced);
  1327. else
  1328. {
  1329. _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits);
  1330. _posAlignEncoder.ReverseEncode(&_rangeEncoder, posReduced & kAlignMask);
  1331. _alignPriceCount++;
  1332. }
  1333. }
  1334. _repDistances[3] = _repDistances[2];
  1335. _repDistances[2] = _repDistances[1];
  1336. _repDistances[1] = _repDistances[0];
  1337. _repDistances[0] = pos;
  1338. _matchPriceCount++;
  1339. }
  1340. _previousByte = _matchFinder.GetIndexByte(_matchFinderObj, len - 1 - _additionalOffset);
  1341. }
  1342. _additionalOffset -= len;
  1343. nowPos32 += len;
  1344. if (_additionalOffset == 0)
  1345. {
  1346. if (!_fastMode)
  1347. {
  1348. if (_matchPriceCount >= (1 << 7))
  1349. FillDistancesPrices();
  1350. if (_alignPriceCount >= kAlignTableSize)
  1351. FillAlignPrices();
  1352. }
  1353. if (_matchFinder.GetNumAvailableBytes(_matchFinderObj) == 0)
  1354. return Flush(nowPos32);
  1355. if (nowPos32 - progressPosValuePrev >= (1 << 14))
  1356. {
  1357. nowPos64 += nowPos32 - progressPosValuePrev;
  1358. *inSize = nowPos64;
  1359. *outSize = _rangeEncoder.GetProcessedSize();
  1360. _finished = false;
  1361. *finished = 0;
  1362. return _matchFinderBase.result;
  1363. }
  1364. }
  1365. }
  1366. }
  1367. STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream,
  1368. ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
  1369. ICompressProgressInfo *progress)
  1370. {
  1371. #ifndef _NO_EXCEPTIONS
  1372. try
  1373. {
  1374. #endif
  1375. return CodeReal(inStream, outStream, inSize, outSize, progress);
  1376. #ifndef _NO_EXCEPTIONS
  1377. }
  1378. catch(const COutBufferException &e) { return e.ErrorCode; }
  1379. catch(...) { return E_FAIL; }
  1380. #endif
  1381. }
  1382. void CEncoder::FillDistancesPrices()
  1383. {
  1384. UInt32 tempPrices[kNumFullDistances];
  1385. for (UInt32 i = kStartPosModelIndex; i < kNumFullDistances; i++)
  1386. {
  1387. UInt32 posSlot = GetPosSlot(i);
  1388. UInt32 footerBits = ((posSlot >> 1) - 1);
  1389. UInt32 base = ((2 | (posSlot & 1)) << footerBits);
  1390. tempPrices[i] = NRangeCoder::ReverseBitTreeGetPrice(_posEncoders +
  1391. base - posSlot - 1, footerBits, i - base);
  1392. }
  1393. for (UInt32 lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++)
  1394. {
  1395. UInt32 posSlot;
  1396. NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumPosSlotBits> &encoder = _posSlotEncoder[lenToPosState];
  1397. UInt32 *posSlotPrices = _posSlotPrices[lenToPosState];
  1398. for (posSlot = 0; posSlot < _distTableSize; posSlot++)
  1399. posSlotPrices[posSlot] = encoder.GetPrice(posSlot);
  1400. for (posSlot = kEndPosModelIndex; posSlot < _distTableSize; posSlot++)
  1401. posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << NRangeCoder::kNumBitPriceShiftBits);
  1402. UInt32 *distancesPrices = _distancesPrices[lenToPosState];
  1403. UInt32 i;
  1404. for (i = 0; i < kStartPosModelIndex; i++)
  1405. distancesPrices[i] = posSlotPrices[i];
  1406. for (; i < kNumFullDistances; i++)
  1407. distancesPrices[i] = posSlotPrices[GetPosSlot(i)] + tempPrices[i];
  1408. }
  1409. _matchPriceCount = 0;
  1410. }
  1411. void CEncoder::FillAlignPrices()
  1412. {
  1413. for (UInt32 i = 0; i < kAlignTableSize; i++)
  1414. _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i);
  1415. _alignPriceCount = 0;
  1416. }
  1417. }}