MatchFinderMt.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806
  1. /* MatchFinderMt.c */
  2. #ifdef _WIN32
  3. #define USE_ALLOCA
  4. #endif
  5. #ifdef USE_ALLOCA
  6. #ifdef _WIN32
  7. #include <malloc.h>
  8. #else
  9. #include <stdlib.h>
  10. #endif
  11. #endif
  12. #include "../../7zCrc.h"
  13. #include "LzHash.h"
  14. #include "MatchFinderMt.h"
  15. void MtSync_Construct(CMtSync *p)
  16. {
  17. p->wasCreated = False;
  18. p->csWasInitialized = False;
  19. p->csWasEntered = False;
  20. Thread_Construct(&p->thread);
  21. Event_Construct(&p->canStart);
  22. Event_Construct(&p->wasStarted);
  23. Event_Construct(&p->wasStopped);
  24. Semaphore_Construct(&p->freeSemaphore);
  25. Semaphore_Construct(&p->filledSemaphore);
  26. }
  27. void MtSync_GetNextBlock(CMtSync *p)
  28. {
  29. if (p->needStart)
  30. {
  31. p->numProcessedBlocks = 1;
  32. p->needStart = False;
  33. p->stopWriting = False;
  34. p->exit = False;
  35. Event_Reset(&p->wasStarted);
  36. Event_Reset(&p->wasStopped);
  37. Event_Set(&p->canStart);
  38. Event_Wait(&p->wasStarted);
  39. }
  40. else
  41. {
  42. CriticalSection_Leave(&p->cs);
  43. p->csWasEntered = False;
  44. p->numProcessedBlocks++;
  45. Semaphore_Release1(&p->freeSemaphore);
  46. }
  47. Semaphore_Wait(&p->filledSemaphore);
  48. CriticalSection_Enter(&p->cs);
  49. p->csWasEntered = True;
  50. }
  51. /* MtSync_StopWriting must be called if Writing was started */
  52. void MtSync_StopWriting(CMtSync *p)
  53. {
  54. UInt32 myNumBlocks = p->numProcessedBlocks;
  55. if (!Thread_WasCreated(&p->thread) || p->needStart)
  56. return;
  57. p->stopWriting = True;
  58. if (p->csWasEntered)
  59. {
  60. CriticalSection_Leave(&p->cs);
  61. p->csWasEntered = False;
  62. }
  63. Semaphore_Release1(&p->freeSemaphore);
  64. Event_Wait(&p->wasStopped);
  65. while (myNumBlocks++ != p->numProcessedBlocks)
  66. {
  67. Semaphore_Wait(&p->filledSemaphore);
  68. Semaphore_Release1(&p->freeSemaphore);
  69. }
  70. p->needStart = True;
  71. }
  72. void MtSync_Destruct(CMtSync *p)
  73. {
  74. if (Thread_WasCreated(&p->thread))
  75. {
  76. MtSync_StopWriting(p);
  77. p->exit = True;
  78. if (p->needStart)
  79. Event_Set(&p->canStart);
  80. Thread_Wait(&p->thread);
  81. Thread_Close(&p->thread);
  82. }
  83. if (p->csWasInitialized)
  84. {
  85. CriticalSection_Delete(&p->cs);
  86. p->csWasInitialized = False;
  87. }
  88. Event_Close(&p->canStart);
  89. Event_Close(&p->wasStarted);
  90. Event_Close(&p->wasStopped);
  91. Semaphore_Close(&p->freeSemaphore);
  92. Semaphore_Close(&p->filledSemaphore);
  93. p->wasCreated = False;
  94. }
  95. HRes MtSync_Create2(CMtSync *p, unsigned (StdCall *startAddress)(void *), void *obj, UInt32 numBlocks)
  96. {
  97. if (p->wasCreated)
  98. return SZ_OK;
  99. RINOK(CriticalSection_Init(&p->cs));
  100. p->csWasInitialized = True;
  101. RINOK(AutoResetEvent_CreateNotSignaled(&p->canStart));
  102. RINOK(AutoResetEvent_CreateNotSignaled(&p->wasStarted));
  103. RINOK(AutoResetEvent_CreateNotSignaled(&p->wasStopped));
  104. RINOK(Semaphore_Create(&p->freeSemaphore, numBlocks, numBlocks));
  105. RINOK(Semaphore_Create(&p->filledSemaphore, 0, numBlocks));
  106. p->needStart = True;
  107. RINOK(Thread_Create(&p->thread, startAddress, obj));
  108. p->wasCreated = True;
  109. return SZ_OK;
  110. }
  111. HRes MtSync_Create(CMtSync *p, unsigned (StdCall *startAddress)(void *), void *obj, UInt32 numBlocks)
  112. {
  113. HRes res = MtSync_Create2(p, startAddress, obj, numBlocks);
  114. if (res != SZ_OK)
  115. MtSync_Destruct(p);
  116. return res;
  117. }
  118. void MtSync_Init(CMtSync *p) { p->needStart = True; }
  119. #define kMtMaxValForNormalize 0xFFFFFFFF
  120. #define DEF_GetHeads(name, v) \
  121. static void GetHeads ## name(const Byte *p, UInt32 pos, \
  122. UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads) { \
  123. for (; numHeads != 0; numHeads--) { \
  124. const UInt32 value = (v); p++; *heads++ = pos - hash[value]; hash[value] = pos++; } }
  125. DEF_GetHeads(2, (p[0] | ((UInt32)p[1] << 8)) & hashMask)
  126. DEF_GetHeads(3, (g_CrcTable[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask)
  127. DEF_GetHeads(4, (g_CrcTable[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (g_CrcTable[p[3]] << 5)) & hashMask)
  128. DEF_GetHeads(4b, (g_CrcTable[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ ((UInt32)p[3] << 16)) & hashMask)
  129. DEF_GetHeads(5, (g_CrcTable[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (g_CrcTable[p[3]] << 5) ^ (g_CrcTable[p[4]] << 3)) & hashMask)
  130. void HashThreadFunc(CMatchFinderMt *mt)
  131. {
  132. CMtSync *p = &mt->hashSync;
  133. for (;;)
  134. {
  135. UInt32 numProcessedBlocks = 0;
  136. Event_Wait(&p->canStart);
  137. Event_Set(&p->wasStarted);
  138. for (;;)
  139. {
  140. if (p->exit)
  141. return;
  142. if (p->stopWriting)
  143. {
  144. p->numProcessedBlocks = numProcessedBlocks;
  145. Event_Set(&p->wasStopped);
  146. break;
  147. }
  148. {
  149. CMatchFinder *mf = mt->MatchFinder;
  150. if (MatchFinder_NeedMove(mf))
  151. {
  152. CriticalSection_Enter(&mt->btSync.cs);
  153. CriticalSection_Enter(&mt->hashSync.cs);
  154. {
  155. const Byte *beforePtr = MatchFinder_GetPointerToCurrentPos(mf);
  156. const Byte *afterPtr;
  157. MatchFinder_MoveBlock(mf);
  158. afterPtr = MatchFinder_GetPointerToCurrentPos(mf);
  159. mt->pointerToCurPos -= beforePtr - afterPtr;
  160. mt->buffer -= beforePtr - afterPtr;
  161. }
  162. CriticalSection_Leave(&mt->btSync.cs);
  163. CriticalSection_Leave(&mt->hashSync.cs);
  164. continue;
  165. }
  166. Semaphore_Wait(&p->freeSemaphore);
  167. MatchFinder_ReadIfRequired(mf);
  168. if (mf->pos > (kMtMaxValForNormalize - kMtHashBlockSize))
  169. {
  170. UInt32 subValue = (mf->pos - mf->historySize - 1);
  171. MatchFinder_ReduceOffsets(mf, subValue);
  172. MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, mf->hashMask + 1);
  173. }
  174. {
  175. UInt32 *heads = mt->hashBuf + ((numProcessedBlocks++) & kMtHashNumBlocksMask) * kMtHashBlockSize;
  176. UInt32 num = mf->streamPos - mf->pos;
  177. heads[0] = 2;
  178. heads[1] = num;
  179. if (num >= mf->numHashBytes)
  180. {
  181. num = num - mf->numHashBytes + 1;
  182. if (num > kMtHashBlockSize - 2)
  183. num = kMtHashBlockSize - 2;
  184. mt->GetHeadsFunc(mf->buffer, mf->pos, mf->hash + mf->fixedHashSize, mf->hashMask, heads + 2, num);
  185. heads[0] += num;
  186. }
  187. mf->pos += num;
  188. mf->buffer += num;
  189. }
  190. }
  191. Semaphore_Release1(&p->filledSemaphore);
  192. }
  193. }
  194. }
  195. void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p)
  196. {
  197. MtSync_GetNextBlock(&p->hashSync);
  198. p->hashBufPosLimit = p->hashBufPos = ((p->hashSync.numProcessedBlocks - 1) & kMtHashNumBlocksMask) * kMtHashBlockSize;
  199. p->hashBufPosLimit += p->hashBuf[p->hashBufPos++];
  200. p->hashNumAvail = p->hashBuf[p->hashBufPos++];
  201. }
  202. #define kEmptyHashValue 0
  203. /* #define MFMT_GM_INLINE */
  204. #ifdef MFMT_GM_INLINE
  205. #if _MSC_VER >= 1300
  206. #define NO_INLINE __declspec(noinline) __fastcall
  207. #else
  208. #ifdef _MSC_VER
  209. #define NO_INLINE __fastcall
  210. #endif
  211. #endif
  212. Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son,
  213. UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
  214. UInt32 *_distances, UInt32 _maxLen, const UInt32 *hash, Int32 limit, UInt32 size, UInt32 *posRes)
  215. {
  216. do
  217. {
  218. UInt32 *distances = _distances + 1;
  219. UInt32 curMatch = pos - *hash++;
  220. CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
  221. CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
  222. UInt32 len0 = 0, len1 = 0;
  223. UInt32 cutValue = _cutValue;
  224. UInt32 maxLen = _maxLen;
  225. for (;;)
  226. {
  227. UInt32 delta = pos - curMatch;
  228. if (cutValue-- == 0 || delta >= _cyclicBufferSize)
  229. {
  230. *ptr0 = *ptr1 = kEmptyHashValue;
  231. break;
  232. }
  233. {
  234. CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
  235. const Byte *pb = cur - delta;
  236. UInt32 len = (len0 < len1 ? len0 : len1);
  237. if (pb[len] == cur[len])
  238. {
  239. if (++len != lenLimit && pb[len] == cur[len])
  240. while(++len != lenLimit)
  241. if (pb[len] != cur[len])
  242. break;
  243. if (maxLen < len)
  244. {
  245. *distances++ = maxLen = len;
  246. *distances++ = delta - 1;
  247. if (len == lenLimit)
  248. {
  249. *ptr1 = pair[0];
  250. *ptr0 = pair[1];
  251. break;
  252. }
  253. }
  254. }
  255. if (pb[len] < cur[len])
  256. {
  257. *ptr1 = curMatch;
  258. ptr1 = pair + 1;
  259. curMatch = *ptr1;
  260. len1 = len;
  261. }
  262. else
  263. {
  264. *ptr0 = curMatch;
  265. ptr0 = pair;
  266. curMatch = *ptr0;
  267. len0 = len;
  268. }
  269. }
  270. }
  271. pos++;
  272. _cyclicBufferPos++;
  273. cur++;
  274. {
  275. UInt32 num = (UInt32)(distances - _distances);
  276. *_distances = num - 1;
  277. _distances += num;
  278. limit -= num;
  279. }
  280. }
  281. while (limit > 0 && --size != 0);
  282. *posRes = pos;
  283. return limit;
  284. }
  285. #endif
  286. void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
  287. {
  288. UInt32 numProcessed = 0;
  289. UInt32 curPos = 2;
  290. UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2);
  291. distances[1] = p->hashNumAvail;
  292. while (curPos < limit)
  293. {
  294. if (p->hashBufPos == p->hashBufPosLimit)
  295. {
  296. MatchFinderMt_GetNextBlock_Hash(p);
  297. distances[1] = numProcessed + p->hashNumAvail;
  298. if (p->hashNumAvail >= p->numHashBytes)
  299. continue;
  300. for (; p->hashNumAvail != 0; p->hashNumAvail--)
  301. distances[curPos++] = 0;
  302. break;
  303. }
  304. {
  305. UInt32 size = p->hashBufPosLimit - p->hashBufPos;
  306. UInt32 lenLimit = p->matchMaxLen;
  307. UInt32 pos = p->pos;
  308. UInt32 cyclicBufferPos = p->cyclicBufferPos;
  309. if (lenLimit >= p->hashNumAvail)
  310. lenLimit = p->hashNumAvail;
  311. {
  312. UInt32 size2 = p->hashNumAvail - lenLimit + 1;
  313. if (size2 < size)
  314. size = size2;
  315. size2 = p->cyclicBufferSize - cyclicBufferPos;
  316. if (size2 < size)
  317. size = size2;
  318. }
  319. #ifndef MFMT_GM_INLINE
  320. while (curPos < limit && size-- != 0)
  321. {
  322. UInt32 *startDistances = distances + curPos;
  323. UInt32 num = (UInt32)(GetMatchesSpec1(lenLimit, pos - p->hashBuf[p->hashBufPos++],
  324. pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,
  325. startDistances + 1, p->numHashBytes - 1) - startDistances);
  326. *startDistances = num - 1;
  327. curPos += num;
  328. cyclicBufferPos++;
  329. pos++;
  330. p->buffer++;
  331. }
  332. #else
  333. {
  334. UInt32 posRes;
  335. curPos = limit - GetMatchesSpecN(lenLimit, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,
  336. distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos, (Int32)(limit - curPos) , size, &posRes);
  337. p->hashBufPos += posRes - pos;
  338. cyclicBufferPos += posRes - pos;
  339. p->buffer += posRes - pos;
  340. pos = posRes;
  341. }
  342. #endif
  343. numProcessed += pos - p->pos;
  344. p->hashNumAvail -= pos - p->pos;
  345. p->pos = pos;
  346. if (cyclicBufferPos == p->cyclicBufferSize)
  347. cyclicBufferPos = 0;
  348. p->cyclicBufferPos = cyclicBufferPos;
  349. }
  350. }
  351. distances[0] = curPos;
  352. }
  353. void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex)
  354. {
  355. CMtSync *sync = &p->hashSync;
  356. if (!sync->needStart)
  357. {
  358. CriticalSection_Enter(&sync->cs);
  359. sync->csWasEntered = True;
  360. }
  361. BtGetMatches(p, p->btBuf + (globalBlockIndex & kMtBtNumBlocksMask) * kMtBtBlockSize);
  362. if (p->pos > kMtMaxValForNormalize - kMtBtBlockSize)
  363. {
  364. UInt32 subValue = p->pos - p->cyclicBufferSize;
  365. MatchFinder_Normalize3(subValue, p->son, p->cyclicBufferSize * 2);
  366. p->pos -= subValue;
  367. }
  368. if (!sync->needStart)
  369. {
  370. CriticalSection_Leave(&sync->cs);
  371. sync->csWasEntered = False;
  372. }
  373. }
  374. void BtThreadFunc(CMatchFinderMt *mt)
  375. {
  376. CMtSync *p = &mt->btSync;
  377. for (;;)
  378. {
  379. UInt32 blockIndex = 0;
  380. Event_Wait(&p->canStart);
  381. Event_Set(&p->wasStarted);
  382. for (;;)
  383. {
  384. if (p->exit)
  385. return;
  386. if (p->stopWriting)
  387. {
  388. p->numProcessedBlocks = blockIndex;
  389. MtSync_StopWriting(&mt->hashSync);
  390. Event_Set(&p->wasStopped);
  391. break;
  392. }
  393. Semaphore_Wait(&p->freeSemaphore);
  394. BtFillBlock(mt, blockIndex++);
  395. Semaphore_Release1(&p->filledSemaphore);
  396. }
  397. }
  398. }
  399. void MatchFinderMt_Construct(CMatchFinderMt *p)
  400. {
  401. p->hashBuf = 0;
  402. MtSync_Construct(&p->hashSync);
  403. MtSync_Construct(&p->btSync);
  404. }
  405. void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAlloc *alloc)
  406. {
  407. alloc->Free(p->hashBuf);
  408. p->hashBuf = 0;
  409. }
  410. void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc)
  411. {
  412. MtSync_Destruct(&p->hashSync);
  413. MtSync_Destruct(&p->btSync);
  414. MatchFinderMt_FreeMem(p, alloc);
  415. }
  416. #define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks)
  417. #define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks)
  418. static unsigned StdCall HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; }
  419. static unsigned StdCall BtThreadFunc2(void *p)
  420. {
  421. #ifdef USE_ALLOCA
  422. alloca(0x180);
  423. #endif
  424. BtThreadFunc((CMatchFinderMt *)p);
  425. return 0;
  426. }
  427. HRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore,
  428. UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc)
  429. {
  430. CMatchFinder *mf = p->MatchFinder;
  431. p->historySize = historySize;
  432. if (kMtBtBlockSize <= matchMaxLen * 4)
  433. return E_INVALIDARG;
  434. if (p->hashBuf == 0)
  435. {
  436. p->hashBuf = (UInt32 *)alloc->Alloc((kHashBufferSize + kBtBufferSize) * sizeof(UInt32));
  437. if (p->hashBuf == 0)
  438. return SZE_OUTOFMEMORY;
  439. p->btBuf = p->hashBuf + kHashBufferSize;
  440. }
  441. keepAddBufferBefore += (kHashBufferSize + kBtBufferSize);
  442. keepAddBufferAfter += kMtHashBlockSize;
  443. if (!MatchFinder_Create(mf, historySize, keepAddBufferBefore, matchMaxLen, keepAddBufferAfter, alloc))
  444. return SZE_OUTOFMEMORY;
  445. RINOK(MtSync_Create(&p->hashSync, HashThreadFunc2, p, kMtHashNumBlocks));
  446. RINOK(MtSync_Create(&p->btSync, BtThreadFunc2, p, kMtBtNumBlocks));
  447. return SZ_OK;
  448. }
  449. /* Call it after ReleaseStream / SetStream */
  450. void MatchFinderMt_Init(CMatchFinderMt *p)
  451. {
  452. CMatchFinder *mf = p->MatchFinder;
  453. p->btBufPos = p->btBufPosLimit = 0;
  454. p->hashBufPos = p->hashBufPosLimit = 0;
  455. MatchFinder_Init(mf);
  456. p->pointerToCurPos = MatchFinder_GetPointerToCurrentPos(mf);
  457. p->btNumAvailBytes = 0;
  458. p->lzPos = p->historySize + 1;
  459. p->hash = mf->hash;
  460. p->fixedHashSize = mf->fixedHashSize;
  461. p->son = mf->son;
  462. p->matchMaxLen = mf->matchMaxLen;
  463. p->numHashBytes = mf->numHashBytes;
  464. p->pos = mf->pos;
  465. p->buffer = mf->buffer;
  466. p->cyclicBufferPos = mf->cyclicBufferPos;
  467. p->cyclicBufferSize = mf->cyclicBufferSize;
  468. p->cutValue = mf->cutValue;
  469. }
  470. /* ReleaseStream is required to finish multithreading */
  471. void MatchFinderMt_ReleaseStream(CMatchFinderMt *p)
  472. {
  473. MtSync_StopWriting(&p->btSync);
  474. /* p->MatchFinder->ReleaseStream(); */
  475. }
  476. void MatchFinderMt_Normalize(CMatchFinderMt *p)
  477. {
  478. MatchFinder_Normalize3(p->lzPos - p->historySize - 1, p->hash, p->fixedHashSize);
  479. p->lzPos = p->historySize + 1;
  480. }
  481. void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p)
  482. {
  483. UInt32 blockIndex;
  484. MtSync_GetNextBlock(&p->btSync);
  485. blockIndex = ((p->btSync.numProcessedBlocks - 1) & kMtBtNumBlocksMask);
  486. p->btBufPosLimit = p->btBufPos = blockIndex * kMtBtBlockSize;
  487. p->btBufPosLimit += p->btBuf[p->btBufPos++];
  488. p->btNumAvailBytes = p->btBuf[p->btBufPos++];
  489. if (p->lzPos >= kMtMaxValForNormalize - kMtBtBlockSize)
  490. MatchFinderMt_Normalize(p);
  491. }
  492. const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p)
  493. {
  494. return p->pointerToCurPos;
  495. }
  496. #define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p);
  497. UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p)
  498. {
  499. GET_NEXT_BLOCK_IF_REQUIRED;
  500. return p->btNumAvailBytes;
  501. }
  502. Byte MatchFinderMt_GetIndexByte(CMatchFinderMt *p, Int32 index)
  503. {
  504. return p->pointerToCurPos[index];
  505. }
  506. UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
  507. {
  508. UInt32 hash2Value, curMatch2;
  509. UInt32 *hash = p->hash;
  510. const Byte *cur = p->pointerToCurPos;
  511. UInt32 lzPos = p->lzPos;
  512. MT_HASH2_CALC
  513. curMatch2 = hash[hash2Value];
  514. hash[hash2Value] = lzPos;
  515. if (curMatch2 >= matchMinPos)
  516. if (cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
  517. {
  518. *distances++ = 2;
  519. *distances++ = lzPos - curMatch2 - 1;
  520. }
  521. return distances;
  522. }
  523. UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
  524. {
  525. UInt32 hash2Value, hash3Value, curMatch2, curMatch3;
  526. UInt32 *hash = p->hash;
  527. const Byte *cur = p->pointerToCurPos;
  528. UInt32 lzPos = p->lzPos;
  529. MT_HASH3_CALC
  530. curMatch2 = hash[ hash2Value];
  531. curMatch3 = hash[kFix3HashSize + hash3Value];
  532. hash[ hash2Value] =
  533. hash[kFix3HashSize + hash3Value] =
  534. lzPos;
  535. if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
  536. {
  537. distances[1] = lzPos - curMatch2 - 1;
  538. if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2])
  539. {
  540. distances[0] = 3;
  541. return distances + 2;
  542. }
  543. distances[0] = 2;
  544. distances += 2;
  545. }
  546. if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0])
  547. {
  548. *distances++ = 3;
  549. *distances++ = lzPos - curMatch3 - 1;
  550. }
  551. return distances;
  552. }
  553. /*
  554. UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
  555. {
  556. UInt32 hash2Value, hash3Value, hash4Value, curMatch2, curMatch3, curMatch4;
  557. UInt32 *hash = p->hash;
  558. const Byte *cur = p->pointerToCurPos;
  559. UInt32 lzPos = p->lzPos;
  560. MT_HASH4_CALC
  561. curMatch2 = hash[ hash2Value];
  562. curMatch3 = hash[kFix3HashSize + hash3Value];
  563. curMatch4 = hash[kFix4HashSize + hash4Value];
  564. hash[ hash2Value] =
  565. hash[kFix3HashSize + hash3Value] =
  566. hash[kFix4HashSize + hash4Value] =
  567. lzPos;
  568. if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
  569. {
  570. distances[1] = lzPos - curMatch2 - 1;
  571. if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2])
  572. {
  573. distances[0] = (cur[(ptrdiff_t)curMatch2 - lzPos + 3] == cur[3]) ? 4 : 3;
  574. return distances + 2;
  575. }
  576. distances[0] = 2;
  577. distances += 2;
  578. }
  579. if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0])
  580. {
  581. distances[1] = lzPos - curMatch3 - 1;
  582. if (cur[(ptrdiff_t)curMatch3 - lzPos + 3] == cur[3])
  583. {
  584. distances[0] = 4;
  585. return distances + 2;
  586. }
  587. distances[0] = 3;
  588. distances += 2;
  589. }
  590. if (curMatch4 >= matchMinPos)
  591. if (
  592. cur[(ptrdiff_t)curMatch4 - lzPos] == cur[0] &&
  593. cur[(ptrdiff_t)curMatch4 - lzPos + 3] == cur[3]
  594. )
  595. {
  596. *distances++ = 4;
  597. *distances++ = lzPos - curMatch4 - 1;
  598. }
  599. return distances;
  600. }
  601. */
  602. #define INCREASE_LZ_POS p->lzPos++; p->pointerToCurPos++;
  603. UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances)
  604. {
  605. const UInt32 *btBuf = p->btBuf + p->btBufPos;
  606. UInt32 len = *btBuf++;
  607. p->btBufPos += 1 + len;
  608. p->btNumAvailBytes--;
  609. {
  610. UInt32 i;
  611. for (i = 0; i < len; i += 2)
  612. {
  613. *distances++ = *btBuf++;
  614. *distances++ = *btBuf++;
  615. }
  616. }
  617. INCREASE_LZ_POS
  618. return len;
  619. }
  620. UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances)
  621. {
  622. const UInt32 *btBuf = p->btBuf + p->btBufPos;
  623. UInt32 len = *btBuf++;
  624. p->btBufPos += 1 + len;
  625. if (len == 0)
  626. {
  627. if (p->btNumAvailBytes-- >= 4)
  628. len = (UInt32)(p->MixMatchesFunc(p, p->lzPos - p->historySize, distances) - (distances));
  629. }
  630. else
  631. {
  632. /* Condition: there are matches in btBuf with length < p->numHashBytes */
  633. UInt32 *distances2;
  634. p->btNumAvailBytes--;
  635. distances2 = p->MixMatchesFunc(p, p->lzPos - btBuf[1], distances);
  636. do
  637. {
  638. *distances2++ = *btBuf++;
  639. *distances2++ = *btBuf++;
  640. }
  641. while ((len -= 2) != 0);
  642. len = (UInt32)(distances2 - (distances));
  643. }
  644. INCREASE_LZ_POS
  645. return len;
  646. }
  647. #define SKIP_HEADER2 do { GET_NEXT_BLOCK_IF_REQUIRED
  648. #define SKIP_HEADER(n) SKIP_HEADER2 if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash;
  649. #define SKIP_FOOTER } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while(--num != 0);
  650. void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num)
  651. {
  652. SKIP_HEADER2 { p->btNumAvailBytes--;
  653. SKIP_FOOTER
  654. }
  655. void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num)
  656. {
  657. SKIP_HEADER(2)
  658. UInt32 hash2Value;
  659. MT_HASH2_CALC
  660. hash[hash2Value] = p->lzPos;
  661. SKIP_FOOTER
  662. }
  663. void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num)
  664. {
  665. SKIP_HEADER(3)
  666. UInt32 hash2Value, hash3Value;
  667. MT_HASH3_CALC
  668. hash[kFix3HashSize + hash3Value] =
  669. hash[ hash2Value] =
  670. p->lzPos;
  671. SKIP_FOOTER
  672. }
  673. /*
  674. void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num)
  675. {
  676. SKIP_HEADER(4)
  677. UInt32 hash2Value, hash3Value, hash4Value;
  678. MT_HASH4_CALC
  679. hash[kFix4HashSize + hash4Value] =
  680. hash[kFix3HashSize + hash3Value] =
  681. hash[ hash2Value] =
  682. p->lzPos;
  683. SKIP_FOOTER
  684. }
  685. */
  686. void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable)
  687. {
  688. vTable->Init = (Mf_Init_Func)MatchFinderMt_Init;
  689. vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinderMt_GetIndexByte;
  690. vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinderMt_GetNumAvailableBytes;
  691. vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinderMt_GetPointerToCurrentPos;
  692. vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches;
  693. switch(p->MatchFinder->numHashBytes)
  694. {
  695. case 2:
  696. p->GetHeadsFunc = GetHeads2;
  697. p->MixMatchesFunc = (Mf_Mix_Matches)0;
  698. vTable->Skip = (Mf_Skip_Func)MatchFinderMt0_Skip;
  699. vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt2_GetMatches;
  700. break;
  701. case 3:
  702. p->GetHeadsFunc = GetHeads3;
  703. p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches2;
  704. vTable->Skip = (Mf_Skip_Func)MatchFinderMt2_Skip;
  705. break;
  706. default:
  707. /* case 4: */
  708. p->GetHeadsFunc = p->MatchFinder->bigHash ? GetHeads4b : GetHeads4;
  709. /* p->GetHeadsFunc = GetHeads4; */
  710. p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches3;
  711. vTable->Skip = (Mf_Skip_Func)MatchFinderMt3_Skip;
  712. break;
  713. /*
  714. default:
  715. p->GetHeadsFunc = GetHeads5;
  716. p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches4;
  717. vTable->Skip = (Mf_Skip_Func)MatchFinderMt4_Skip;
  718. break;
  719. */
  720. }
  721. }