1 /* LzFindMt.c -- multithreaded Match finder for LZ algorithms
2 2017-06-10 : Igor Pavlov : Public domain */
10 static void MtSync_Construct(CMtSync
*p
)
12 p
->wasCreated
= False
;
13 p
->csWasInitialized
= False
;
14 p
->csWasEntered
= False
;
15 Thread_Construct(&p
->thread
);
16 Event_Construct(&p
->canStart
);
17 Event_Construct(&p
->wasStarted
);
18 Event_Construct(&p
->wasStopped
);
19 Semaphore_Construct(&p
->freeSemaphore
);
20 Semaphore_Construct(&p
->filledSemaphore
);
23 static void MtSync_GetNextBlock(CMtSync
*p
)
27 p
->numProcessedBlocks
= 1;
29 p
->stopWriting
= False
;
31 Event_Reset(&p
->wasStarted
);
32 Event_Reset(&p
->wasStopped
);
34 Event_Set(&p
->canStart
);
35 Event_Wait(&p
->wasStarted
);
37 // if (mt) MatchFinder_Init_LowHash(mt->MatchFinder);
41 CriticalSection_Leave(&p
->cs
);
42 p
->csWasEntered
= False
;
43 p
->numProcessedBlocks
++;
44 Semaphore_Release1(&p
->freeSemaphore
);
46 Semaphore_Wait(&p
->filledSemaphore
);
47 CriticalSection_Enter(&p
->cs
);
48 p
->csWasEntered
= True
;
51 /* MtSync_StopWriting must be called if Writing was started */
53 static void MtSync_StopWriting(CMtSync
*p
)
55 UInt32 myNumBlocks
= p
->numProcessedBlocks
;
56 if (!Thread_WasCreated(&p
->thread
) || p
->needStart
)
58 p
->stopWriting
= True
;
61 CriticalSection_Leave(&p
->cs
);
62 p
->csWasEntered
= False
;
64 Semaphore_Release1(&p
->freeSemaphore
);
66 Event_Wait(&p
->wasStopped
);
68 while (myNumBlocks
++ != p
->numProcessedBlocks
)
70 Semaphore_Wait(&p
->filledSemaphore
);
71 Semaphore_Release1(&p
->freeSemaphore
);
76 static void MtSync_Destruct(CMtSync
*p
)
78 if (Thread_WasCreated(&p
->thread
))
80 MtSync_StopWriting(p
);
83 Event_Set(&p
->canStart
);
84 Thread_Wait(&p
->thread
);
85 Thread_Close(&p
->thread
);
87 if (p
->csWasInitialized
)
89 CriticalSection_Delete(&p
->cs
);
90 p
->csWasInitialized
= False
;
93 Event_Close(&p
->canStart
);
94 Event_Close(&p
->wasStarted
);
95 Event_Close(&p
->wasStopped
);
96 Semaphore_Close(&p
->freeSemaphore
);
97 Semaphore_Close(&p
->filledSemaphore
);
99 p
->wasCreated
= False
;
102 #define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; }
104 static SRes
MtSync_Create2(CMtSync
*p
, THREAD_FUNC_TYPE startAddress
, void *obj
, UInt32 numBlocks
)
109 RINOK_THREAD(CriticalSection_Init(&p
->cs
));
110 p
->csWasInitialized
= True
;
112 RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p
->canStart
));
113 RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p
->wasStarted
));
114 RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p
->wasStopped
));
116 RINOK_THREAD(Semaphore_Create(&p
->freeSemaphore
, numBlocks
, numBlocks
));
117 RINOK_THREAD(Semaphore_Create(&p
->filledSemaphore
, 0, numBlocks
));
121 RINOK_THREAD(Thread_Create(&p
->thread
, startAddress
, obj
));
122 p
->wasCreated
= True
;
126 static SRes
MtSync_Create(CMtSync
*p
, THREAD_FUNC_TYPE startAddress
, void *obj
, UInt32 numBlocks
)
128 SRes res
= MtSync_Create2(p
, startAddress
, obj
, numBlocks
);
134 void MtSync_Init(CMtSync
*p
) { p
->needStart
= True
; }
136 #define kMtMaxValForNormalize 0xFFFFFFFF
138 #define DEF_GetHeads2(name, v, action) \
139 static void GetHeads ## name(const Byte *p, UInt32 pos, \
140 UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc) \
141 { action; for (; numHeads != 0; numHeads--) { \
142 const UInt32 value = (v); p++; *heads++ = pos - hash[value]; hash[value] = pos++; } }
144 #define DEF_GetHeads(name, v) DEF_GetHeads2(name, v, ;)
146 DEF_GetHeads2(2, (p
[0] | ((UInt32
)p
[1] << 8)), UNUSED_VAR(hashMask
); UNUSED_VAR(crc
); )
147 DEF_GetHeads(3, (crc
[p
[0]] ^ p
[1] ^ ((UInt32
)p
[2] << 8)) & hashMask
)
148 DEF_GetHeads(4, (crc
[p
[0]] ^ p
[1] ^ ((UInt32
)p
[2] << 8) ^ (crc
[p
[3]] << 5)) & hashMask
)
149 DEF_GetHeads(4b
, (crc
[p
[0]] ^ p
[1] ^ ((UInt32
)p
[2] << 8) ^ ((UInt32
)p
[3] << 16)) & hashMask
)
150 /* DEF_GetHeads(5, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5) ^ (crc[p[4]] << 3)) & hashMask) */
152 static void HashThreadFunc(CMatchFinderMt
*mt
)
154 CMtSync
*p
= &mt
->hashSync
;
157 UInt32 numProcessedBlocks
= 0;
158 Event_Wait(&p
->canStart
);
159 Event_Set(&p
->wasStarted
);
161 MatchFinder_Init_HighHash(mt
->MatchFinder
);
169 p
->numProcessedBlocks
= numProcessedBlocks
;
170 Event_Set(&p
->wasStopped
);
175 CMatchFinder
*mf
= mt
->MatchFinder
;
176 if (MatchFinder_NeedMove(mf
))
178 CriticalSection_Enter(&mt
->btSync
.cs
);
179 CriticalSection_Enter(&mt
->hashSync
.cs
);
181 const Byte
*beforePtr
= Inline_MatchFinder_GetPointerToCurrentPos(mf
);
183 MatchFinder_MoveBlock(mf
);
184 offset
= beforePtr
- Inline_MatchFinder_GetPointerToCurrentPos(mf
);
185 mt
->pointerToCurPos
-= offset
;
186 mt
->buffer
-= offset
;
188 CriticalSection_Leave(&mt
->btSync
.cs
);
189 CriticalSection_Leave(&mt
->hashSync
.cs
);
193 Semaphore_Wait(&p
->freeSemaphore
);
195 MatchFinder_ReadIfRequired(mf
);
196 if (mf
->pos
> (kMtMaxValForNormalize
- kMtHashBlockSize
))
198 UInt32 subValue
= (mf
->pos
- mf
->historySize
- 1);
199 MatchFinder_ReduceOffsets(mf
, subValue
);
200 MatchFinder_Normalize3(subValue
, mf
->hash
+ mf
->fixedHashSize
, (size_t)mf
->hashMask
+ 1);
203 UInt32
*heads
= mt
->hashBuf
+ ((numProcessedBlocks
++) & kMtHashNumBlocksMask
) * kMtHashBlockSize
;
204 UInt32 num
= mf
->streamPos
- mf
->pos
;
207 if (num
>= mf
->numHashBytes
)
209 num
= num
- mf
->numHashBytes
+ 1;
210 if (num
> kMtHashBlockSize
- 2)
211 num
= kMtHashBlockSize
- 2;
212 mt
->GetHeadsFunc(mf
->buffer
, mf
->pos
, mf
->hash
+ mf
->fixedHashSize
, mf
->hashMask
, heads
+ 2, num
, mf
->crc
);
220 Semaphore_Release1(&p
->filledSemaphore
);
225 static void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt
*p
)
227 MtSync_GetNextBlock(&p
->hashSync
);
228 p
->hashBufPosLimit
= p
->hashBufPos
= ((p
->hashSync
.numProcessedBlocks
- 1) & kMtHashNumBlocksMask
) * kMtHashBlockSize
;
229 p
->hashBufPosLimit
+= p
->hashBuf
[p
->hashBufPos
++];
230 p
->hashNumAvail
= p
->hashBuf
[p
->hashBufPos
++];
233 #define kEmptyHashValue 0
235 /* #define MFMT_GM_INLINE */
237 #ifdef MFMT_GM_INLINE
239 #define NO_INLINE MY_FAST_CALL
241 static Int32 NO_INLINE
GetMatchesSpecN(UInt32 lenLimit
, UInt32 pos
, const Byte
*cur
, CLzRef
*son
,
242 UInt32 _cyclicBufferPos
, UInt32 _cyclicBufferSize
, UInt32 _cutValue
,
243 UInt32
*_distances
, UInt32 _maxLen
, const UInt32
*hash
, Int32 limit
, UInt32 size
, UInt32
*posRes
)
247 UInt32
*distances
= _distances
+ 1;
248 UInt32 curMatch
= pos
- *hash
++;
250 CLzRef
*ptr0
= son
+ (_cyclicBufferPos
<< 1) + 1;
251 CLzRef
*ptr1
= son
+ (_cyclicBufferPos
<< 1);
252 UInt32 len0
= 0, len1
= 0;
253 UInt32 cutValue
= _cutValue
;
254 UInt32 maxLen
= _maxLen
;
257 UInt32 delta
= pos
- curMatch
;
258 if (cutValue
-- == 0 || delta
>= _cyclicBufferSize
)
260 *ptr0
= *ptr1
= kEmptyHashValue
;
264 CLzRef
*pair
= son
+ ((_cyclicBufferPos
- delta
+ ((delta
> _cyclicBufferPos
) ? _cyclicBufferSize
: 0)) << 1);
265 const Byte
*pb
= cur
- delta
;
266 UInt32 len
= (len0
< len1
? len0
: len1
);
267 if (pb
[len
] == cur
[len
])
269 if (++len
!= lenLimit
&& pb
[len
] == cur
[len
])
270 while (++len
!= lenLimit
)
271 if (pb
[len
] != cur
[len
])
275 *distances
++ = maxLen
= len
;
276 *distances
++ = delta
- 1;
285 if (pb
[len
] < cur
[len
])
305 UInt32 num
= (UInt32
)(distances
- _distances
);
306 *_distances
= num
- 1;
311 while (limit
> 0 && --size
!= 0);
318 static void BtGetMatches(CMatchFinderMt
*p
, UInt32
*distances
)
320 UInt32 numProcessed
= 0;
322 UInt32 limit
= kMtBtBlockSize
- (p
->matchMaxLen
* 2);
324 distances
[1] = p
->hashNumAvail
;
326 while (curPos
< limit
)
328 if (p
->hashBufPos
== p
->hashBufPosLimit
)
330 MatchFinderMt_GetNextBlock_Hash(p
);
331 distances
[1] = numProcessed
+ p
->hashNumAvail
;
332 if (p
->hashNumAvail
>= p
->numHashBytes
)
334 distances
[0] = curPos
+ p
->hashNumAvail
;
336 for (; p
->hashNumAvail
!= 0; p
->hashNumAvail
--)
341 UInt32 size
= p
->hashBufPosLimit
- p
->hashBufPos
;
342 UInt32 lenLimit
= p
->matchMaxLen
;
344 UInt32 cyclicBufferPos
= p
->cyclicBufferPos
;
345 if (lenLimit
>= p
->hashNumAvail
)
346 lenLimit
= p
->hashNumAvail
;
348 UInt32 size2
= p
->hashNumAvail
- lenLimit
+ 1;
351 size2
= p
->cyclicBufferSize
- cyclicBufferPos
;
356 #ifndef MFMT_GM_INLINE
357 while (curPos
< limit
&& size
-- != 0)
359 UInt32
*startDistances
= distances
+ curPos
;
360 UInt32 num
= (UInt32
)(GetMatchesSpec1(lenLimit
, pos
- p
->hashBuf
[p
->hashBufPos
++],
361 pos
, p
->buffer
, p
->son
, cyclicBufferPos
, p
->cyclicBufferSize
, p
->cutValue
,
362 startDistances
+ 1, p
->numHashBytes
- 1) - startDistances
);
363 *startDistances
= num
- 1;
372 curPos
= limit
- GetMatchesSpecN(lenLimit
, pos
, p
->buffer
, p
->son
, cyclicBufferPos
, p
->cyclicBufferSize
, p
->cutValue
,
373 distances
+ curPos
, p
->numHashBytes
- 1, p
->hashBuf
+ p
->hashBufPos
, (Int32
)(limit
- curPos
), size
, &posRes
);
374 p
->hashBufPos
+= posRes
- pos
;
375 cyclicBufferPos
+= posRes
- pos
;
376 p
->buffer
+= posRes
- pos
;
381 numProcessed
+= pos
- p
->pos
;
382 p
->hashNumAvail
-= pos
- p
->pos
;
384 if (cyclicBufferPos
== p
->cyclicBufferSize
)
386 p
->cyclicBufferPos
= cyclicBufferPos
;
390 distances
[0] = curPos
;
393 static void BtFillBlock(CMatchFinderMt
*p
, UInt32 globalBlockIndex
)
395 CMtSync
*sync
= &p
->hashSync
;
396 if (!sync
->needStart
)
398 CriticalSection_Enter(&sync
->cs
);
399 sync
->csWasEntered
= True
;
402 BtGetMatches(p
, p
->btBuf
+ (globalBlockIndex
& kMtBtNumBlocksMask
) * kMtBtBlockSize
);
404 if (p
->pos
> kMtMaxValForNormalize
- kMtBtBlockSize
)
406 UInt32 subValue
= p
->pos
- p
->cyclicBufferSize
;
407 MatchFinder_Normalize3(subValue
, p
->son
, (size_t)p
->cyclicBufferSize
* 2);
411 if (!sync
->needStart
)
413 CriticalSection_Leave(&sync
->cs
);
414 sync
->csWasEntered
= False
;
418 void BtThreadFunc(CMatchFinderMt
*mt
)
420 CMtSync
*p
= &mt
->btSync
;
423 UInt32 blockIndex
= 0;
424 Event_Wait(&p
->canStart
);
425 Event_Set(&p
->wasStarted
);
432 p
->numProcessedBlocks
= blockIndex
;
433 MtSync_StopWriting(&mt
->hashSync
);
434 Event_Set(&p
->wasStopped
);
437 Semaphore_Wait(&p
->freeSemaphore
);
438 BtFillBlock(mt
, blockIndex
++);
439 Semaphore_Release1(&p
->filledSemaphore
);
444 void MatchFinderMt_Construct(CMatchFinderMt
*p
)
447 MtSync_Construct(&p
->hashSync
);
448 MtSync_Construct(&p
->btSync
);
451 static void MatchFinderMt_FreeMem(CMatchFinderMt
*p
, ISzAllocPtr alloc
)
453 ISzAlloc_Free(alloc
, p
->hashBuf
);
457 void MatchFinderMt_Destruct(CMatchFinderMt
*p
, ISzAllocPtr alloc
)
459 MtSync_Destruct(&p
->hashSync
);
460 MtSync_Destruct(&p
->btSync
);
461 MatchFinderMt_FreeMem(p
, alloc
);
464 #define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks)
465 #define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks)
467 static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE
HashThreadFunc2(void *p
) { HashThreadFunc((CMatchFinderMt
*)p
); return 0; }
468 static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE
BtThreadFunc2(void *p
)
470 Byte allocaDummy
[0x180];
472 for (i
= 0; i
< 16; i
++)
473 allocaDummy
[i
] = (Byte
)0;
474 if (allocaDummy
[0] == 0)
475 BtThreadFunc((CMatchFinderMt
*)p
);
479 SRes
MatchFinderMt_Create(CMatchFinderMt
*p
, UInt32 historySize
, UInt32 keepAddBufferBefore
,
480 UInt32 matchMaxLen
, UInt32 keepAddBufferAfter
, ISzAllocPtr alloc
)
482 CMatchFinder
*mf
= p
->MatchFinder
;
483 p
->historySize
= historySize
;
484 if (kMtBtBlockSize
<= matchMaxLen
* 4)
485 return SZ_ERROR_PARAM
;
488 p
->hashBuf
= (UInt32
*)ISzAlloc_Alloc(alloc
, (kHashBufferSize
+ kBtBufferSize
) * sizeof(UInt32
));
491 p
->btBuf
= p
->hashBuf
+ kHashBufferSize
;
493 keepAddBufferBefore
+= (kHashBufferSize
+ kBtBufferSize
);
494 keepAddBufferAfter
+= kMtHashBlockSize
;
495 if (!MatchFinder_Create(mf
, historySize
, keepAddBufferBefore
, matchMaxLen
, keepAddBufferAfter
, alloc
))
498 RINOK(MtSync_Create(&p
->hashSync
, HashThreadFunc2
, p
, kMtHashNumBlocks
));
499 RINOK(MtSync_Create(&p
->btSync
, BtThreadFunc2
, p
, kMtBtNumBlocks
));
503 /* Call it after ReleaseStream / SetStream */
504 static void MatchFinderMt_Init(CMatchFinderMt
*p
)
506 CMatchFinder
*mf
= p
->MatchFinder
;
509 p
->btBufPosLimit
= 0;
511 p
->hashBufPosLimit
= 0;
513 /* Init without data reading. We don't want to read data in this thread */
514 MatchFinder_Init_3(mf
, False
);
515 MatchFinder_Init_LowHash(mf
);
517 p
->pointerToCurPos
= Inline_MatchFinder_GetPointerToCurrentPos(mf
);
518 p
->btNumAvailBytes
= 0;
519 p
->lzPos
= p
->historySize
+ 1;
522 p
->fixedHashSize
= mf
->fixedHashSize
;
526 p
->matchMaxLen
= mf
->matchMaxLen
;
527 p
->numHashBytes
= mf
->numHashBytes
;
529 p
->buffer
= mf
->buffer
;
530 p
->cyclicBufferPos
= mf
->cyclicBufferPos
;
531 p
->cyclicBufferSize
= mf
->cyclicBufferSize
;
532 p
->cutValue
= mf
->cutValue
;
535 /* ReleaseStream is required to finish multithreading */
536 void MatchFinderMt_ReleaseStream(CMatchFinderMt
*p
)
538 MtSync_StopWriting(&p
->btSync
);
539 /* p->MatchFinder->ReleaseStream(); */
542 static void MatchFinderMt_Normalize(CMatchFinderMt
*p
)
544 MatchFinder_Normalize3(p
->lzPos
- p
->historySize
- 1, p
->hash
, p
->fixedHashSize
);
545 p
->lzPos
= p
->historySize
+ 1;
548 static void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt
*p
)
551 MtSync_GetNextBlock(&p
->btSync
);
552 blockIndex
= ((p
->btSync
.numProcessedBlocks
- 1) & kMtBtNumBlocksMask
);
553 p
->btBufPosLimit
= p
->btBufPos
= blockIndex
* kMtBtBlockSize
;
554 p
->btBufPosLimit
+= p
->btBuf
[p
->btBufPos
++];
555 p
->btNumAvailBytes
= p
->btBuf
[p
->btBufPos
++];
556 if (p
->lzPos
>= kMtMaxValForNormalize
- kMtBtBlockSize
)
557 MatchFinderMt_Normalize(p
);
560 static const Byte
* MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt
*p
)
562 return p
->pointerToCurPos
;
565 #define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p);
567 static UInt32
MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt
*p
)
569 GET_NEXT_BLOCK_IF_REQUIRED
;
570 return p
->btNumAvailBytes
;
573 static UInt32
* MixMatches2(CMatchFinderMt
*p
, UInt32 matchMinPos
, UInt32
*distances
)
575 UInt32 h2
, curMatch2
;
576 UInt32
*hash
= p
->hash
;
577 const Byte
*cur
= p
->pointerToCurPos
;
578 UInt32 lzPos
= p
->lzPos
;
581 curMatch2
= hash
[h2
];
584 if (curMatch2
>= matchMinPos
)
585 if (cur
[(ptrdiff_t)curMatch2
- lzPos
] == cur
[0])
588 *distances
++ = lzPos
- curMatch2
- 1;
594 static UInt32
* MixMatches3(CMatchFinderMt
*p
, UInt32 matchMinPos
, UInt32
*distances
)
596 UInt32 h2
, h3
, curMatch2
, curMatch3
;
597 UInt32
*hash
= p
->hash
;
598 const Byte
*cur
= p
->pointerToCurPos
;
599 UInt32 lzPos
= p
->lzPos
;
602 curMatch2
= hash
[ h2
];
603 curMatch3
= (hash
+ kFix3HashSize
)[h3
];
606 (hash
+ kFix3HashSize
)[h3
] = lzPos
;
608 if (curMatch2
>= matchMinPos
&& cur
[(ptrdiff_t)curMatch2
- lzPos
] == cur
[0])
610 distances
[1] = lzPos
- curMatch2
- 1;
611 if (cur
[(ptrdiff_t)curMatch2
- lzPos
+ 2] == cur
[2])
614 return distances
+ 2;
620 if (curMatch3
>= matchMinPos
&& cur
[(ptrdiff_t)curMatch3
- lzPos
] == cur
[0])
623 *distances
++ = lzPos
- curMatch3
- 1;
630 static UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
632 UInt32 h2, h3, h4, curMatch2, curMatch3, curMatch4;
633 UInt32 *hash = p->hash;
634 const Byte *cur = p->pointerToCurPos;
635 UInt32 lzPos = p->lzPos;
638 curMatch2 = hash[ h2];
639 curMatch3 = (hash + kFix3HashSize)[h3];
640 curMatch4 = (hash + kFix4HashSize)[h4];
643 (hash + kFix3HashSize)[h3] = lzPos;
644 (hash + kFix4HashSize)[h4] = lzPos;
646 if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
648 distances[1] = lzPos - curMatch2 - 1;
649 if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2])
651 distances[0] = (cur[(ptrdiff_t)curMatch2 - lzPos + 3] == cur[3]) ? 4 : 3;
652 return distances + 2;
658 if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0])
660 distances[1] = lzPos - curMatch3 - 1;
661 if (cur[(ptrdiff_t)curMatch3 - lzPos + 3] == cur[3])
664 return distances + 2;
670 if (curMatch4 >= matchMinPos)
672 cur[(ptrdiff_t)curMatch4 - lzPos] == cur[0] &&
673 cur[(ptrdiff_t)curMatch4 - lzPos + 3] == cur[3]
677 *distances++ = lzPos - curMatch4 - 1;
684 #define INCREASE_LZ_POS p->lzPos++; p->pointerToCurPos++;
686 static UInt32
MatchFinderMt2_GetMatches(CMatchFinderMt
*p
, UInt32
*distances
)
688 const UInt32
*btBuf
= p
->btBuf
+ p
->btBufPos
;
689 UInt32 len
= *btBuf
++;
690 p
->btBufPos
+= 1 + len
;
691 p
->btNumAvailBytes
--;
694 for (i
= 0; i
< len
; i
+= 2)
696 UInt32 v0
= btBuf
[0];
697 UInt32 v1
= btBuf
[1];
708 static UInt32
MatchFinderMt_GetMatches(CMatchFinderMt
*p
, UInt32
*distances
)
710 const UInt32
*btBuf
= p
->btBuf
+ p
->btBufPos
;
711 UInt32 len
= *btBuf
++;
712 p
->btBufPos
+= 1 + len
;
716 /* change for bt5 ! */
717 if (p
->btNumAvailBytes
-- >= 4)
718 len
= (UInt32
)(p
->MixMatchesFunc(p
, p
->lzPos
- p
->historySize
, distances
) - (distances
));
722 /* Condition: there are matches in btBuf with length < p->numHashBytes */
724 p
->btNumAvailBytes
--;
725 distances2
= p
->MixMatchesFunc(p
, p
->lzPos
- btBuf
[1], distances
);
728 UInt32 v0
= btBuf
[0];
729 UInt32 v1
= btBuf
[1];
735 while ((len
-= 2) != 0);
736 len
= (UInt32
)(distances2
- (distances
));
742 #define SKIP_HEADER2_MT do { GET_NEXT_BLOCK_IF_REQUIRED
743 #define SKIP_HEADER_MT(n) SKIP_HEADER2_MT if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash;
744 #define SKIP_FOOTER_MT } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while (--num != 0);
746 static void MatchFinderMt0_Skip(CMatchFinderMt
*p
, UInt32 num
)
748 SKIP_HEADER2_MT
{ p
->btNumAvailBytes
--;
752 static void MatchFinderMt2_Skip(CMatchFinderMt
*p
, UInt32 num
)
761 static void MatchFinderMt3_Skip(CMatchFinderMt
*p
, UInt32 num
)
766 (hash
+ kFix3HashSize
)[h3
] =
773 static void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num)
778 (hash + kFix4HashSize)[h4] =
779 (hash + kFix3HashSize)[h3] =
786 void MatchFinderMt_CreateVTable(CMatchFinderMt
*p
, IMatchFinder
*vTable
)
788 vTable
->Init
= (Mf_Init_Func
)MatchFinderMt_Init
;
789 vTable
->GetNumAvailableBytes
= (Mf_GetNumAvailableBytes_Func
)MatchFinderMt_GetNumAvailableBytes
;
790 vTable
->GetPointerToCurrentPos
= (Mf_GetPointerToCurrentPos_Func
)MatchFinderMt_GetPointerToCurrentPos
;
791 vTable
->GetMatches
= (Mf_GetMatches_Func
)MatchFinderMt_GetMatches
;
793 switch (p
->MatchFinder
->numHashBytes
)
796 p
->GetHeadsFunc
= GetHeads2
;
797 p
->MixMatchesFunc
= (Mf_Mix_Matches
)NULL
;
798 vTable
->Skip
= (Mf_Skip_Func
)MatchFinderMt0_Skip
;
799 vTable
->GetMatches
= (Mf_GetMatches_Func
)MatchFinderMt2_GetMatches
;
802 p
->GetHeadsFunc
= GetHeads3
;
803 p
->MixMatchesFunc
= (Mf_Mix_Matches
)MixMatches2
;
804 vTable
->Skip
= (Mf_Skip_Func
)MatchFinderMt2_Skip
;
808 p
->GetHeadsFunc
= p
->MatchFinder
->bigHash
? GetHeads4b
: GetHeads4
;
809 p
->MixMatchesFunc
= (Mf_Mix_Matches
)MixMatches3
;
810 vTable
->Skip
= (Mf_Skip_Func
)MatchFinderMt3_Skip
;
814 p->GetHeadsFunc = GetHeads5;
815 p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches4;
816 vTable->Skip = (Mf_Skip_Func)MatchFinderMt4_Skip;