Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

794 lines
22 KiB

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