1 /* LzFindMt.c -- multithreaded Match finder for LZ algorithms
2 2008-10-04 : Igor Pavlov : Public domain */
8 void MtSync_Construct(CMtSync
*p
)
10 p
->wasCreated
= False
;
11 p
->csWasInitialized
= False
;
12 p
->csWasEntered
= False
;
13 Thread_Construct(&p
->thread
);
14 Event_Construct(&p
->canStart
);
15 Event_Construct(&p
->wasStarted
);
16 Event_Construct(&p
->wasStopped
);
17 Semaphore_Construct(&p
->freeSemaphore
);
18 Semaphore_Construct(&p
->filledSemaphore
);
21 void MtSync_GetNextBlock(CMtSync
*p
)
25 p
->numProcessedBlocks
= 1;
27 p
->stopWriting
= False
;
29 Event_Reset(&p
->wasStarted
);
30 Event_Reset(&p
->wasStopped
);
32 Event_Set(&p
->canStart
);
33 Event_Wait(&p
->wasStarted
);
37 CriticalSection_Leave(&p
->cs
);
38 p
->csWasEntered
= False
;
39 p
->numProcessedBlocks
++;
40 Semaphore_Release1(&p
->freeSemaphore
);
42 Semaphore_Wait(&p
->filledSemaphore
);
43 CriticalSection_Enter(&p
->cs
);
44 p
->csWasEntered
= True
;
47 /* MtSync_StopWriting must be called if Writing was started */
49 void MtSync_StopWriting(CMtSync
*p
)
51 UInt32 myNumBlocks
= p
->numProcessedBlocks
;
52 if (!Thread_WasCreated(&p
->thread
) || p
->needStart
)
54 p
->stopWriting
= True
;
57 CriticalSection_Leave(&p
->cs
);
58 p
->csWasEntered
= False
;
60 Semaphore_Release1(&p
->freeSemaphore
);
62 Event_Wait(&p
->wasStopped
);
64 while (myNumBlocks
++ != p
->numProcessedBlocks
)
66 Semaphore_Wait(&p
->filledSemaphore
);
67 Semaphore_Release1(&p
->freeSemaphore
);
72 void MtSync_Destruct(CMtSync
*p
)
74 if (Thread_WasCreated(&p
->thread
))
76 MtSync_StopWriting(p
);
79 Event_Set(&p
->canStart
);
80 Thread_Wait(&p
->thread
);
81 Thread_Close(&p
->thread
);
83 if (p
->csWasInitialized
)
85 CriticalSection_Delete(&p
->cs
);
86 p
->csWasInitialized
= False
;
89 Event_Close(&p
->canStart
);
90 Event_Close(&p
->wasStarted
);
91 Event_Close(&p
->wasStopped
);
92 Semaphore_Close(&p
->freeSemaphore
);
93 Semaphore_Close(&p
->filledSemaphore
);
95 p
->wasCreated
= False
;
98 #define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; }
100 static SRes
MtSync_Create2(CMtSync
*p
, unsigned (MY_STD_CALL
*startAddress
)(void *), void *obj
, UInt32 numBlocks
)
105 RINOK_THREAD(CriticalSection_Init(&p
->cs
));
106 p
->csWasInitialized
= True
;
108 RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p
->canStart
));
109 RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p
->wasStarted
));
110 RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p
->wasStopped
));
112 RINOK_THREAD(Semaphore_Create(&p
->freeSemaphore
, numBlocks
, numBlocks
));
113 RINOK_THREAD(Semaphore_Create(&p
->filledSemaphore
, 0, numBlocks
));
117 RINOK_THREAD(Thread_Create(&p
->thread
, startAddress
, obj
));
118 p
->wasCreated
= True
;
122 static SRes
MtSync_Create(CMtSync
*p
, unsigned (MY_STD_CALL
*startAddress
)(void *), void *obj
, UInt32 numBlocks
)
124 SRes res
= MtSync_Create2(p
, startAddress
, obj
, numBlocks
);
130 void MtSync_Init(CMtSync
*p
) { p
->needStart
= True
; }
132 #define kMtMaxValForNormalize 0xFFFFFFFF
134 #define DEF_GetHeads2(name, v, action) \
135 static void GetHeads ## name(const Byte *p, UInt32 pos, \
136 UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc) \
137 { action; for (; numHeads != 0; numHeads--) { \
138 const UInt32 value = (v); p++; *heads++ = pos - hash[value]; hash[value] = pos++; } }
140 #define DEF_GetHeads(name, v) DEF_GetHeads2(name, v, ;)
142 DEF_GetHeads2(2, (p
[0] | ((UInt32
)p
[1] << 8)), hashMask
= hashMask
; crc
= crc
; )
143 DEF_GetHeads(3, (crc
[p
[0]] ^ p
[1] ^ ((UInt32
)p
[2] << 8)) & hashMask
)
144 DEF_GetHeads(4, (crc
[p
[0]] ^ p
[1] ^ ((UInt32
)p
[2] << 8) ^ (crc
[p
[3]] << 5)) & hashMask
)
145 DEF_GetHeads(4b
, (crc
[p
[0]] ^ p
[1] ^ ((UInt32
)p
[2] << 8) ^ ((UInt32
)p
[3] << 16)) & hashMask
)
146 DEF_GetHeads(5, (crc
[p
[0]] ^ p
[1] ^ ((UInt32
)p
[2] << 8) ^ (crc
[p
[3]] << 5) ^ (crc
[p
[4]] << 3)) & hashMask
)
148 void HashThreadFunc(CMatchFinderMt
*mt
)
150 CMtSync
*p
= &mt
->hashSync
;
153 UInt32 numProcessedBlocks
= 0;
154 Event_Wait(&p
->canStart
);
155 Event_Set(&p
->wasStarted
);
162 p
->numProcessedBlocks
= numProcessedBlocks
;
163 Event_Set(&p
->wasStopped
);
168 CMatchFinder
*mf
= mt
->MatchFinder
;
169 if (MatchFinder_NeedMove(mf
))
171 CriticalSection_Enter(&mt
->btSync
.cs
);
172 CriticalSection_Enter(&mt
->hashSync
.cs
);
174 const Byte
*beforePtr
= MatchFinder_GetPointerToCurrentPos(mf
);
175 const Byte
*afterPtr
;
176 MatchFinder_MoveBlock(mf
);
177 afterPtr
= MatchFinder_GetPointerToCurrentPos(mf
);
178 mt
->pointerToCurPos
-= beforePtr
- afterPtr
;
179 mt
->buffer
-= beforePtr
- afterPtr
;
181 CriticalSection_Leave(&mt
->btSync
.cs
);
182 CriticalSection_Leave(&mt
->hashSync
.cs
);
186 Semaphore_Wait(&p
->freeSemaphore
);
188 MatchFinder_ReadIfRequired(mf
);
189 if (mf
->pos
> (kMtMaxValForNormalize
- kMtHashBlockSize
))
191 UInt32 subValue
= (mf
->pos
- mf
->historySize
- 1);
192 MatchFinder_ReduceOffsets(mf
, subValue
);
193 MatchFinder_Normalize3(subValue
, mf
->hash
+ mf
->fixedHashSize
, mf
->hashMask
+ 1);
196 UInt32
*heads
= mt
->hashBuf
+ ((numProcessedBlocks
++) & kMtHashNumBlocksMask
) * kMtHashBlockSize
;
197 UInt32 num
= mf
->streamPos
- mf
->pos
;
200 if (num
>= mf
->numHashBytes
)
202 num
= num
- mf
->numHashBytes
+ 1;
203 if (num
> kMtHashBlockSize
- 2)
204 num
= kMtHashBlockSize
- 2;
205 mt
->GetHeadsFunc(mf
->buffer
, mf
->pos
, mf
->hash
+ mf
->fixedHashSize
, mf
->hashMask
, heads
+ 2, num
, mf
->crc
);
213 Semaphore_Release1(&p
->filledSemaphore
);
218 void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt
*p
)
220 MtSync_GetNextBlock(&p
->hashSync
);
221 p
->hashBufPosLimit
= p
->hashBufPos
= ((p
->hashSync
.numProcessedBlocks
- 1) & kMtHashNumBlocksMask
) * kMtHashBlockSize
;
222 p
->hashBufPosLimit
+= p
->hashBuf
[p
->hashBufPos
++];
223 p
->hashNumAvail
= p
->hashBuf
[p
->hashBufPos
++];
226 #define kEmptyHashValue 0
228 /* #define MFMT_GM_INLINE */
230 #ifdef MFMT_GM_INLINE
232 #define NO_INLINE MY_FAST_CALL
234 Int32 NO_INLINE
GetMatchesSpecN(UInt32 lenLimit
, UInt32 pos
, const Byte
*cur
, CLzRef
*son
,
235 UInt32 _cyclicBufferPos
, UInt32 _cyclicBufferSize
, UInt32 _cutValue
,
236 UInt32
*_distances
, UInt32 _maxLen
, const UInt32
*hash
, Int32 limit
, UInt32 size
, UInt32
*posRes
)
240 UInt32
*distances
= _distances
+ 1;
241 UInt32 curMatch
= pos
- *hash
++;
243 CLzRef
*ptr0
= son
+ (_cyclicBufferPos
<< 1) + 1;
244 CLzRef
*ptr1
= son
+ (_cyclicBufferPos
<< 1);
245 UInt32 len0
= 0, len1
= 0;
246 UInt32 cutValue
= _cutValue
;
247 UInt32 maxLen
= _maxLen
;
250 UInt32 delta
= pos
- curMatch
;
251 if (cutValue
-- == 0 || delta
>= _cyclicBufferSize
)
253 *ptr0
= *ptr1
= kEmptyHashValue
;
257 CLzRef
*pair
= son
+ ((_cyclicBufferPos
- delta
+ ((delta
> _cyclicBufferPos
) ? _cyclicBufferSize
: 0)) << 1);
258 const Byte
*pb
= cur
- delta
;
259 UInt32 len
= (len0
< len1
? len0
: len1
);
260 if (pb
[len
] == cur
[len
])
262 if (++len
!= lenLimit
&& pb
[len
] == cur
[len
])
263 while (++len
!= lenLimit
)
264 if (pb
[len
] != cur
[len
])
268 *distances
++ = maxLen
= len
;
269 *distances
++ = delta
- 1;
278 if (pb
[len
] < cur
[len
])
298 UInt32 num
= (UInt32
)(distances
- _distances
);
299 *_distances
= num
- 1;
304 while (limit
> 0 && --size
!= 0);
311 void BtGetMatches(CMatchFinderMt
*p
, UInt32
*distances
)
313 UInt32 numProcessed
= 0;
315 UInt32 limit
= kMtBtBlockSize
- (p
->matchMaxLen
* 2);
316 distances
[1] = p
->hashNumAvail
;
317 while (curPos
< limit
)
319 if (p
->hashBufPos
== p
->hashBufPosLimit
)
321 MatchFinderMt_GetNextBlock_Hash(p
);
322 distances
[1] = numProcessed
+ p
->hashNumAvail
;
323 if (p
->hashNumAvail
>= p
->numHashBytes
)
325 for (; p
->hashNumAvail
!= 0; p
->hashNumAvail
--)
326 distances
[curPos
++] = 0;
330 UInt32 size
= p
->hashBufPosLimit
- p
->hashBufPos
;
331 UInt32 lenLimit
= p
->matchMaxLen
;
333 UInt32 cyclicBufferPos
= p
->cyclicBufferPos
;
334 if (lenLimit
>= p
->hashNumAvail
)
335 lenLimit
= p
->hashNumAvail
;
337 UInt32 size2
= p
->hashNumAvail
- lenLimit
+ 1;
340 size2
= p
->cyclicBufferSize
- cyclicBufferPos
;
344 #ifndef MFMT_GM_INLINE
345 while (curPos
< limit
&& size
-- != 0)
347 UInt32
*startDistances
= distances
+ curPos
;
348 UInt32 num
= (UInt32
)(GetMatchesSpec1(lenLimit
, pos
- p
->hashBuf
[p
->hashBufPos
++],
349 pos
, p
->buffer
, p
->son
, cyclicBufferPos
, p
->cyclicBufferSize
, p
->cutValue
,
350 startDistances
+ 1, p
->numHashBytes
- 1) - startDistances
);
351 *startDistances
= num
- 1;
360 curPos
= limit
- GetMatchesSpecN(lenLimit
, pos
, p
->buffer
, p
->son
, cyclicBufferPos
, p
->cyclicBufferSize
, p
->cutValue
,
361 distances
+ curPos
, p
->numHashBytes
- 1, p
->hashBuf
+ p
->hashBufPos
, (Int32
)(limit
- curPos
) , size
, &posRes
);
362 p
->hashBufPos
+= posRes
- pos
;
363 cyclicBufferPos
+= posRes
- pos
;
364 p
->buffer
+= posRes
- pos
;
369 numProcessed
+= pos
- p
->pos
;
370 p
->hashNumAvail
-= pos
- p
->pos
;
372 if (cyclicBufferPos
== p
->cyclicBufferSize
)
374 p
->cyclicBufferPos
= cyclicBufferPos
;
377 distances
[0] = curPos
;
380 void BtFillBlock(CMatchFinderMt
*p
, UInt32 globalBlockIndex
)
382 CMtSync
*sync
= &p
->hashSync
;
383 if (!sync
->needStart
)
385 CriticalSection_Enter(&sync
->cs
);
386 sync
->csWasEntered
= True
;
389 BtGetMatches(p
, p
->btBuf
+ (globalBlockIndex
& kMtBtNumBlocksMask
) * kMtBtBlockSize
);
391 if (p
->pos
> kMtMaxValForNormalize
- kMtBtBlockSize
)
393 UInt32 subValue
= p
->pos
- p
->cyclicBufferSize
;
394 MatchFinder_Normalize3(subValue
, p
->son
, p
->cyclicBufferSize
* 2);
398 if (!sync
->needStart
)
400 CriticalSection_Leave(&sync
->cs
);
401 sync
->csWasEntered
= False
;
405 void BtThreadFunc(CMatchFinderMt
*mt
)
407 CMtSync
*p
= &mt
->btSync
;
410 UInt32 blockIndex
= 0;
411 Event_Wait(&p
->canStart
);
412 Event_Set(&p
->wasStarted
);
419 p
->numProcessedBlocks
= blockIndex
;
420 MtSync_StopWriting(&mt
->hashSync
);
421 Event_Set(&p
->wasStopped
);
424 Semaphore_Wait(&p
->freeSemaphore
);
425 BtFillBlock(mt
, blockIndex
++);
426 Semaphore_Release1(&p
->filledSemaphore
);
431 void MatchFinderMt_Construct(CMatchFinderMt
*p
)
434 MtSync_Construct(&p
->hashSync
);
435 MtSync_Construct(&p
->btSync
);
438 void MatchFinderMt_FreeMem(CMatchFinderMt
*p
, ISzAlloc
*alloc
)
440 alloc
->Free(alloc
, p
->hashBuf
);
444 void MatchFinderMt_Destruct(CMatchFinderMt
*p
, ISzAlloc
*alloc
)
446 MtSync_Destruct(&p
->hashSync
);
447 MtSync_Destruct(&p
->btSync
);
448 MatchFinderMt_FreeMem(p
, alloc
);
451 #define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks)
452 #define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks)
454 static unsigned MY_STD_CALL
HashThreadFunc2(void *p
) { HashThreadFunc((CMatchFinderMt
*)p
); return 0; }
455 static unsigned MY_STD_CALL
BtThreadFunc2(void *p
)
457 Byte allocaDummy
[0x180];
459 for (i
= 0; i
< 16; i
++)
460 allocaDummy
[i
] = (Byte
)i
;
461 BtThreadFunc((CMatchFinderMt
*)p
);
465 SRes
MatchFinderMt_Create(CMatchFinderMt
*p
, UInt32 historySize
, UInt32 keepAddBufferBefore
,
466 UInt32 matchMaxLen
, UInt32 keepAddBufferAfter
, ISzAlloc
*alloc
)
468 CMatchFinder
*mf
= p
->MatchFinder
;
469 p
->historySize
= historySize
;
470 if (kMtBtBlockSize
<= matchMaxLen
* 4)
471 return SZ_ERROR_PARAM
;
474 p
->hashBuf
= (UInt32
*)alloc
->Alloc(alloc
, (kHashBufferSize
+ kBtBufferSize
) * sizeof(UInt32
));
477 p
->btBuf
= p
->hashBuf
+ kHashBufferSize
;
479 keepAddBufferBefore
+= (kHashBufferSize
+ kBtBufferSize
);
480 keepAddBufferAfter
+= kMtHashBlockSize
;
481 if (!MatchFinder_Create(mf
, historySize
, keepAddBufferBefore
, matchMaxLen
, keepAddBufferAfter
, alloc
))
484 RINOK(MtSync_Create(&p
->hashSync
, HashThreadFunc2
, p
, kMtHashNumBlocks
));
485 RINOK(MtSync_Create(&p
->btSync
, BtThreadFunc2
, p
, kMtBtNumBlocks
));
489 /* Call it after ReleaseStream / SetStream */
490 void MatchFinderMt_Init(CMatchFinderMt
*p
)
492 CMatchFinder
*mf
= p
->MatchFinder
;
493 p
->btBufPos
= p
->btBufPosLimit
= 0;
494 p
->hashBufPos
= p
->hashBufPosLimit
= 0;
495 MatchFinder_Init(mf
);
496 p
->pointerToCurPos
= MatchFinder_GetPointerToCurrentPos(mf
);
497 p
->btNumAvailBytes
= 0;
498 p
->lzPos
= p
->historySize
+ 1;
501 p
->fixedHashSize
= mf
->fixedHashSize
;
505 p
->matchMaxLen
= mf
->matchMaxLen
;
506 p
->numHashBytes
= mf
->numHashBytes
;
508 p
->buffer
= mf
->buffer
;
509 p
->cyclicBufferPos
= mf
->cyclicBufferPos
;
510 p
->cyclicBufferSize
= mf
->cyclicBufferSize
;
511 p
->cutValue
= mf
->cutValue
;
514 /* ReleaseStream is required to finish multithreading */
515 void MatchFinderMt_ReleaseStream(CMatchFinderMt
*p
)
517 MtSync_StopWriting(&p
->btSync
);
518 /* p->MatchFinder->ReleaseStream(); */
521 void MatchFinderMt_Normalize(CMatchFinderMt
*p
)
523 MatchFinder_Normalize3(p
->lzPos
- p
->historySize
- 1, p
->hash
, p
->fixedHashSize
);
524 p
->lzPos
= p
->historySize
+ 1;
527 void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt
*p
)
530 MtSync_GetNextBlock(&p
->btSync
);
531 blockIndex
= ((p
->btSync
.numProcessedBlocks
- 1) & kMtBtNumBlocksMask
);
532 p
->btBufPosLimit
= p
->btBufPos
= blockIndex
* kMtBtBlockSize
;
533 p
->btBufPosLimit
+= p
->btBuf
[p
->btBufPos
++];
534 p
->btNumAvailBytes
= p
->btBuf
[p
->btBufPos
++];
535 if (p
->lzPos
>= kMtMaxValForNormalize
- kMtBtBlockSize
)
536 MatchFinderMt_Normalize(p
);
539 const Byte
* MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt
*p
)
541 return p
->pointerToCurPos
;
544 #define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p);
546 UInt32
MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt
*p
)
548 GET_NEXT_BLOCK_IF_REQUIRED
;
549 return p
->btNumAvailBytes
;
552 Byte
MatchFinderMt_GetIndexByte(CMatchFinderMt
*p
, Int32 index
)
554 return p
->pointerToCurPos
[index
];
557 UInt32
* MixMatches2(CMatchFinderMt
*p
, UInt32 matchMinPos
, UInt32
*distances
)
559 UInt32 hash2Value
, curMatch2
;
560 UInt32
*hash
= p
->hash
;
561 const Byte
*cur
= p
->pointerToCurPos
;
562 UInt32 lzPos
= p
->lzPos
;
565 curMatch2
= hash
[hash2Value
];
566 hash
[hash2Value
] = lzPos
;
568 if (curMatch2
>= matchMinPos
)
569 if (cur
[(ptrdiff_t)curMatch2
- lzPos
] == cur
[0])
572 *distances
++ = lzPos
- curMatch2
- 1;
577 UInt32
* MixMatches3(CMatchFinderMt
*p
, UInt32 matchMinPos
, UInt32
*distances
)
579 UInt32 hash2Value
, hash3Value
, curMatch2
, curMatch3
;
580 UInt32
*hash
= p
->hash
;
581 const Byte
*cur
= p
->pointerToCurPos
;
582 UInt32 lzPos
= p
->lzPos
;
585 curMatch2
= hash
[ hash2Value
];
586 curMatch3
= hash
[kFix3HashSize
+ hash3Value
];
589 hash
[kFix3HashSize
+ hash3Value
] =
592 if (curMatch2
>= matchMinPos
&& cur
[(ptrdiff_t)curMatch2
- lzPos
] == cur
[0])
594 distances
[1] = lzPos
- curMatch2
- 1;
595 if (cur
[(ptrdiff_t)curMatch2
- lzPos
+ 2] == cur
[2])
598 return distances
+ 2;
603 if (curMatch3
>= matchMinPos
&& cur
[(ptrdiff_t)curMatch3
- lzPos
] == cur
[0])
606 *distances
++ = lzPos
- curMatch3
- 1;
612 UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
614 UInt32 hash2Value, hash3Value, hash4Value, curMatch2, curMatch3, curMatch4;
615 UInt32 *hash = p->hash;
616 const Byte *cur = p->pointerToCurPos;
617 UInt32 lzPos = p->lzPos;
620 curMatch2 = hash[ hash2Value];
621 curMatch3 = hash[kFix3HashSize + hash3Value];
622 curMatch4 = hash[kFix4HashSize + hash4Value];
625 hash[kFix3HashSize + hash3Value] =
626 hash[kFix4HashSize + hash4Value] =
629 if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
631 distances[1] = lzPos - curMatch2 - 1;
632 if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2])
634 distances[0] = (cur[(ptrdiff_t)curMatch2 - lzPos + 3] == cur[3]) ? 4 : 3;
635 return distances + 2;
640 if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0])
642 distances[1] = lzPos - curMatch3 - 1;
643 if (cur[(ptrdiff_t)curMatch3 - lzPos + 3] == cur[3])
646 return distances + 2;
652 if (curMatch4 >= matchMinPos)
654 cur[(ptrdiff_t)curMatch4 - lzPos] == cur[0] &&
655 cur[(ptrdiff_t)curMatch4 - lzPos + 3] == cur[3]
659 *distances++ = lzPos - curMatch4 - 1;
665 #define INCREASE_LZ_POS p->lzPos++; p->pointerToCurPos++;
667 UInt32
MatchFinderMt2_GetMatches(CMatchFinderMt
*p
, UInt32
*distances
)
669 const UInt32
*btBuf
= p
->btBuf
+ p
->btBufPos
;
670 UInt32 len
= *btBuf
++;
671 p
->btBufPos
+= 1 + len
;
672 p
->btNumAvailBytes
--;
675 for (i
= 0; i
< len
; i
+= 2)
677 *distances
++ = *btBuf
++;
678 *distances
++ = *btBuf
++;
685 UInt32
MatchFinderMt_GetMatches(CMatchFinderMt
*p
, UInt32
*distances
)
687 const UInt32
*btBuf
= p
->btBuf
+ p
->btBufPos
;
688 UInt32 len
= *btBuf
++;
689 p
->btBufPos
+= 1 + len
;
693 if (p
->btNumAvailBytes
-- >= 4)
694 len
= (UInt32
)(p
->MixMatchesFunc(p
, p
->lzPos
- p
->historySize
, distances
) - (distances
));
698 /* Condition: there are matches in btBuf with length < p->numHashBytes */
700 p
->btNumAvailBytes
--;
701 distances2
= p
->MixMatchesFunc(p
, p
->lzPos
- btBuf
[1], distances
);
704 *distances2
++ = *btBuf
++;
705 *distances2
++ = *btBuf
++;
707 while ((len
-= 2) != 0);
708 len
= (UInt32
)(distances2
- (distances
));
714 #define SKIP_HEADER2 do { GET_NEXT_BLOCK_IF_REQUIRED
715 #define SKIP_HEADER(n) SKIP_HEADER2 if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash;
716 #define SKIP_FOOTER } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while (--num != 0);
718 void MatchFinderMt0_Skip(CMatchFinderMt
*p
, UInt32 num
)
720 SKIP_HEADER2
{ p
->btNumAvailBytes
--;
724 void MatchFinderMt2_Skip(CMatchFinderMt
*p
, UInt32 num
)
729 hash
[hash2Value
] = p
->lzPos
;
733 void MatchFinderMt3_Skip(CMatchFinderMt
*p
, UInt32 num
)
736 UInt32 hash2Value
, hash3Value
;
738 hash
[kFix3HashSize
+ hash3Value
] =
745 void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num)
748 UInt32 hash2Value, hash3Value, hash4Value;
750 hash[kFix4HashSize + hash4Value] =
751 hash[kFix3HashSize + hash3Value] =
758 void MatchFinderMt_CreateVTable(CMatchFinderMt
*p
, IMatchFinder
*vTable
)
760 vTable
->Init
= (Mf_Init_Func
)MatchFinderMt_Init
;
761 vTable
->GetIndexByte
= (Mf_GetIndexByte_Func
)MatchFinderMt_GetIndexByte
;
762 vTable
->GetNumAvailableBytes
= (Mf_GetNumAvailableBytes_Func
)MatchFinderMt_GetNumAvailableBytes
;
763 vTable
->GetPointerToCurrentPos
= (Mf_GetPointerToCurrentPos_Func
)MatchFinderMt_GetPointerToCurrentPos
;
764 vTable
->GetMatches
= (Mf_GetMatches_Func
)MatchFinderMt_GetMatches
;
765 switch(p
->MatchFinder
->numHashBytes
)
768 p
->GetHeadsFunc
= GetHeads2
;
769 p
->MixMatchesFunc
= (Mf_Mix_Matches
)0;
770 vTable
->Skip
= (Mf_Skip_Func
)MatchFinderMt0_Skip
;
771 vTable
->GetMatches
= (Mf_GetMatches_Func
)MatchFinderMt2_GetMatches
;
774 p
->GetHeadsFunc
= GetHeads3
;
775 p
->MixMatchesFunc
= (Mf_Mix_Matches
)MixMatches2
;
776 vTable
->Skip
= (Mf_Skip_Func
)MatchFinderMt2_Skip
;
780 p
->GetHeadsFunc
= p
->MatchFinder
->bigHash
? GetHeads4b
: GetHeads4
;
781 /* p->GetHeadsFunc = GetHeads4; */
782 p
->MixMatchesFunc
= (Mf_Mix_Matches
)MixMatches3
;
783 vTable
->Skip
= (Mf_Skip_Func
)MatchFinderMt3_Skip
;
787 p->GetHeadsFunc = GetHeads5;
788 p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches4;
789 vTable->Skip = (Mf_Skip_Func)MatchFinderMt4_Skip;