1 /* LzFind.c -- Match finder for LZ algorithms
2 2017-06-10 : Igor Pavlov : Public domain */
11 #define kEmptyHashValue 0
12 #define kMaxValForNormalize ((UInt32)0xFFFFFFFF)
13 #define kNormalizeStepMin (1 << 10) /* it must be power of 2 */
14 #define kNormalizeMask (~(UInt32)(kNormalizeStepMin - 1))
15 #define kMaxHistorySize ((UInt32)7 << 29)
17 #define kStartMaxLen 3
19 static void LzInWindow_Free(CMatchFinder
*p
, ISzAllocPtr alloc
)
23 ISzAlloc_Free(alloc
, p
->bufferBase
);
28 /* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */
30 static int LzInWindow_Create(CMatchFinder
*p
, UInt32 keepSizeReserv
, ISzAllocPtr alloc
)
32 UInt32 blockSize
= p
->keepSizeBefore
+ p
->keepSizeAfter
+ keepSizeReserv
;
35 p
->blockSize
= blockSize
;
38 if (!p
->bufferBase
|| p
->blockSize
!= blockSize
)
40 LzInWindow_Free(p
, alloc
);
41 p
->blockSize
= blockSize
;
42 p
->bufferBase
= (Byte
*)ISzAlloc_Alloc(alloc
, (size_t)blockSize
);
44 return (p
->bufferBase
!= NULL
);
47 Byte
*MatchFinder_GetPointerToCurrentPos(CMatchFinder
*p
) { return p
->buffer
; }
49 UInt32
MatchFinder_GetNumAvailableBytes(CMatchFinder
*p
) { return p
->streamPos
- p
->pos
; }
51 void MatchFinder_ReduceOffsets(CMatchFinder
*p
, UInt32 subValue
)
53 p
->posLimit
-= subValue
;
55 p
->streamPos
-= subValue
;
58 static void MatchFinder_ReadBlock(CMatchFinder
*p
)
60 if (p
->streamEndWasReached
|| p
->result
!= SZ_OK
)
63 /* We use (p->streamPos - p->pos) value. (p->streamPos < p->pos) is allowed. */
67 UInt32 curSize
= 0xFFFFFFFF - (p
->streamPos
- p
->pos
);
68 if (curSize
> p
->directInputRem
)
69 curSize
= (UInt32
)p
->directInputRem
;
70 p
->directInputRem
-= curSize
;
71 p
->streamPos
+= curSize
;
72 if (p
->directInputRem
== 0)
73 p
->streamEndWasReached
= 1;
79 Byte
*dest
= p
->buffer
+ (p
->streamPos
- p
->pos
);
80 size_t size
= (p
->bufferBase
+ p
->blockSize
- dest
);
84 p
->result
= ISeqInStream_Read(p
->stream
, dest
, &size
);
85 if (p
->result
!= SZ_OK
)
89 p
->streamEndWasReached
= 1;
92 p
->streamPos
+= (UInt32
)size
;
93 if (p
->streamPos
- p
->pos
> p
->keepSizeAfter
)
98 void MatchFinder_MoveBlock(CMatchFinder
*p
)
100 memmove(p
->bufferBase
,
101 p
->buffer
- p
->keepSizeBefore
,
102 (size_t)(p
->streamPos
- p
->pos
) + p
->keepSizeBefore
);
103 p
->buffer
= p
->bufferBase
+ p
->keepSizeBefore
;
106 int MatchFinder_NeedMove(CMatchFinder
*p
)
110 /* if (p->streamEndWasReached) return 0; */
111 return ((size_t)(p
->bufferBase
+ p
->blockSize
- p
->buffer
) <= p
->keepSizeAfter
);
114 void MatchFinder_ReadIfRequired(CMatchFinder
*p
)
116 if (p
->streamEndWasReached
)
118 if (p
->keepSizeAfter
>= p
->streamPos
- p
->pos
)
119 MatchFinder_ReadBlock(p
);
122 static void MatchFinder_CheckAndMoveAndRead(CMatchFinder
*p
)
124 if (MatchFinder_NeedMove(p
))
125 MatchFinder_MoveBlock(p
);
126 MatchFinder_ReadBlock(p
);
129 static void MatchFinder_SetDefaultSettings(CMatchFinder
*p
)
137 #define kCrcPoly 0xEDB88320
139 void MatchFinder_Construct(CMatchFinder
*p
)
142 p
->bufferBase
= NULL
;
145 p
->expectedDataSize
= (UInt64
)(Int64
)-1;
146 MatchFinder_SetDefaultSettings(p
);
148 for (i
= 0; i
< 256; i
++)
152 for (j
= 0; j
< 8; j
++)
153 r
= (r
>> 1) ^ (kCrcPoly
& ((UInt32
)0 - (r
& 1)));
158 static void MatchFinder_FreeThisClassMemory(CMatchFinder
*p
, ISzAllocPtr alloc
)
160 ISzAlloc_Free(alloc
, p
->hash
);
164 void MatchFinder_Free(CMatchFinder
*p
, ISzAllocPtr alloc
)
166 MatchFinder_FreeThisClassMemory(p
, alloc
);
167 LzInWindow_Free(p
, alloc
);
170 static CLzRef
* AllocRefs(size_t num
, ISzAllocPtr alloc
)
172 size_t sizeInBytes
= (size_t)num
* sizeof(CLzRef
);
173 if (sizeInBytes
/ sizeof(CLzRef
) != num
)
175 return (CLzRef
*)ISzAlloc_Alloc(alloc
, sizeInBytes
);
178 int MatchFinder_Create(CMatchFinder
*p
, UInt32 historySize
,
179 UInt32 keepAddBufferBefore
, UInt32 matchMaxLen
, UInt32 keepAddBufferAfter
,
184 if (historySize
> kMaxHistorySize
)
186 MatchFinder_Free(p
, alloc
);
190 sizeReserv
= historySize
>> 1;
191 if (historySize
>= ((UInt32
)3 << 30)) sizeReserv
= historySize
>> 3;
192 else if (historySize
>= ((UInt32
)2 << 30)) sizeReserv
= historySize
>> 2;
194 sizeReserv
+= (keepAddBufferBefore
+ matchMaxLen
+ keepAddBufferAfter
) / 2 + (1 << 19);
196 p
->keepSizeBefore
= historySize
+ keepAddBufferBefore
+ 1;
197 p
->keepSizeAfter
= matchMaxLen
+ keepAddBufferAfter
;
199 /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */
201 if (LzInWindow_Create(p
, sizeReserv
, alloc
))
203 UInt32 newCyclicBufferSize
= historySize
+ 1;
205 p
->matchMaxLen
= matchMaxLen
;
207 p
->fixedHashSize
= 0;
208 if (p
->numHashBytes
== 2)
213 if (hs
> p
->expectedDataSize
)
214 hs
= (UInt32
)p
->expectedDataSize
;
222 hs
|= 0xFFFF; /* don't change it! It's required for Deflate */
225 if (p
->numHashBytes
== 3)
229 /* if (bigHash) mode, GetHeads4b() in LzFindMt.c needs (hs >= ((1 << 24) - 1))) */
234 if (p
->numHashBytes
> 2) p
->fixedHashSize
+= kHash2Size
;
235 if (p
->numHashBytes
> 3) p
->fixedHashSize
+= kHash3Size
;
236 if (p
->numHashBytes
> 4) p
->fixedHashSize
+= kHash4Size
;
237 hs
+= p
->fixedHashSize
;
243 p
->historySize
= historySize
;
245 p
->cyclicBufferSize
= newCyclicBufferSize
;
247 numSons
= newCyclicBufferSize
;
250 newSize
= hs
+ numSons
;
252 if (p
->hash
&& p
->numRefs
== newSize
)
255 MatchFinder_FreeThisClassMemory(p
, alloc
);
256 p
->numRefs
= newSize
;
257 p
->hash
= AllocRefs(newSize
, alloc
);
261 p
->son
= p
->hash
+ p
->hashSizeSum
;
267 MatchFinder_Free(p
, alloc
);
271 static void MatchFinder_SetLimits(CMatchFinder
*p
)
273 UInt32 limit
= kMaxValForNormalize
- p
->pos
;
274 UInt32 limit2
= p
->cyclicBufferSize
- p
->cyclicBufferPos
;
278 limit2
= p
->streamPos
- p
->pos
;
280 if (limit2
<= p
->keepSizeAfter
)
286 limit2
-= p
->keepSizeAfter
;
292 UInt32 lenLimit
= p
->streamPos
- p
->pos
;
293 if (lenLimit
> p
->matchMaxLen
)
294 lenLimit
= p
->matchMaxLen
;
295 p
->lenLimit
= lenLimit
;
297 p
->posLimit
= p
->pos
+ limit
;
301 void MatchFinder_Init_LowHash(CMatchFinder
*p
)
304 CLzRef
*items
= p
->hash
;
305 size_t numItems
= p
->fixedHashSize
;
306 for (i
= 0; i
< numItems
; i
++)
307 items
[i
] = kEmptyHashValue
;
311 void MatchFinder_Init_HighHash(CMatchFinder
*p
)
314 CLzRef
*items
= p
->hash
+ p
->fixedHashSize
;
315 size_t numItems
= (size_t)p
->hashMask
+ 1;
316 for (i
= 0; i
< numItems
; i
++)
317 items
[i
] = kEmptyHashValue
;
321 void MatchFinder_Init_3(CMatchFinder
*p
, int readData
)
323 p
->cyclicBufferPos
= 0;
324 p
->buffer
= p
->bufferBase
;
326 p
->streamPos
= p
->cyclicBufferSize
;
328 p
->streamEndWasReached
= 0;
331 MatchFinder_ReadBlock(p
);
333 MatchFinder_SetLimits(p
);
337 void MatchFinder_Init(CMatchFinder
*p
)
339 MatchFinder_Init_HighHash(p
);
340 MatchFinder_Init_LowHash(p
);
341 MatchFinder_Init_3(p
, True
);
345 static UInt32
MatchFinder_GetSubValue(CMatchFinder
*p
)
347 return (p
->pos
- p
->historySize
- 1) & kNormalizeMask
;
350 void MatchFinder_Normalize3(UInt32 subValue
, CLzRef
*items
, size_t numItems
)
353 for (i
= 0; i
< numItems
; i
++)
355 UInt32 value
= items
[i
];
356 if (value
<= subValue
)
357 value
= kEmptyHashValue
;
364 static void MatchFinder_Normalize(CMatchFinder
*p
)
366 UInt32 subValue
= MatchFinder_GetSubValue(p
);
367 MatchFinder_Normalize3(subValue
, p
->hash
, p
->numRefs
);
368 MatchFinder_ReduceOffsets(p
, subValue
);
371 static void MatchFinder_CheckLimits(CMatchFinder
*p
)
373 if (p
->pos
== kMaxValForNormalize
)
374 MatchFinder_Normalize(p
);
375 if (!p
->streamEndWasReached
&& p
->keepSizeAfter
== p
->streamPos
- p
->pos
)
376 MatchFinder_CheckAndMoveAndRead(p
);
377 if (p
->cyclicBufferPos
== p
->cyclicBufferSize
)
378 p
->cyclicBufferPos
= 0;
379 MatchFinder_SetLimits(p
);
382 static UInt32
* Hc_GetMatchesSpec(UInt32 lenLimit
, UInt32 curMatch
, UInt32 pos
, const Byte
*cur
, CLzRef
*son
,
383 UInt32 _cyclicBufferPos
, UInt32 _cyclicBufferSize
, UInt32 cutValue
,
384 UInt32
*distances
, UInt32 maxLen
)
386 son
[_cyclicBufferPos
] = curMatch
;
389 UInt32 delta
= pos
- curMatch
;
390 if (cutValue
-- == 0 || delta
>= _cyclicBufferSize
)
393 const Byte
*pb
= cur
- delta
;
394 curMatch
= son
[_cyclicBufferPos
- delta
+ ((delta
> _cyclicBufferPos
) ? _cyclicBufferSize
: 0)];
395 if (pb
[maxLen
] == cur
[maxLen
] && *pb
== *cur
)
398 while (++len
!= lenLimit
)
399 if (pb
[len
] != cur
[len
])
403 *distances
++ = maxLen
= len
;
404 *distances
++ = delta
- 1;
413 UInt32
* GetMatchesSpec1(UInt32 lenLimit
, UInt32 curMatch
, UInt32 pos
, const Byte
*cur
, CLzRef
*son
,
414 UInt32 _cyclicBufferPos
, UInt32 _cyclicBufferSize
, UInt32 cutValue
,
415 UInt32
*distances
, UInt32 maxLen
)
417 CLzRef
*ptr0
= son
+ (_cyclicBufferPos
<< 1) + 1;
418 CLzRef
*ptr1
= son
+ (_cyclicBufferPos
<< 1);
419 UInt32 len0
= 0, len1
= 0;
422 UInt32 delta
= pos
- curMatch
;
423 if (cutValue
-- == 0 || delta
>= _cyclicBufferSize
)
425 *ptr0
= *ptr1
= kEmptyHashValue
;
429 CLzRef
*pair
= son
+ ((_cyclicBufferPos
- delta
+ ((delta
> _cyclicBufferPos
) ? _cyclicBufferSize
: 0)) << 1);
430 const Byte
*pb
= cur
- delta
;
431 UInt32 len
= (len0
< len1
? len0
: len1
);
432 if (pb
[len
] == cur
[len
])
434 if (++len
!= lenLimit
&& pb
[len
] == cur
[len
])
435 while (++len
!= lenLimit
)
436 if (pb
[len
] != cur
[len
])
440 *distances
++ = maxLen
= len
;
441 *distances
++ = delta
- 1;
450 if (pb
[len
] < cur
[len
])
468 static void SkipMatchesSpec(UInt32 lenLimit
, UInt32 curMatch
, UInt32 pos
, const Byte
*cur
, CLzRef
*son
,
469 UInt32 _cyclicBufferPos
, UInt32 _cyclicBufferSize
, UInt32 cutValue
)
471 CLzRef
*ptr0
= son
+ (_cyclicBufferPos
<< 1) + 1;
472 CLzRef
*ptr1
= son
+ (_cyclicBufferPos
<< 1);
473 UInt32 len0
= 0, len1
= 0;
476 UInt32 delta
= pos
- curMatch
;
477 if (cutValue
-- == 0 || delta
>= _cyclicBufferSize
)
479 *ptr0
= *ptr1
= kEmptyHashValue
;
483 CLzRef
*pair
= son
+ ((_cyclicBufferPos
- delta
+ ((delta
> _cyclicBufferPos
) ? _cyclicBufferSize
: 0)) << 1);
484 const Byte
*pb
= cur
- delta
;
485 UInt32 len
= (len0
< len1
? len0
: len1
);
486 if (pb
[len
] == cur
[len
])
488 while (++len
!= lenLimit
)
489 if (pb
[len
] != cur
[len
])
500 if (pb
[len
] < cur
[len
])
519 ++p->cyclicBufferPos; \
521 if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p);
523 #define MOVE_POS_RET MOVE_POS return offset;
525 static void MatchFinder_MovePos(CMatchFinder
*p
) { MOVE_POS
; }
527 #define GET_MATCHES_HEADER2(minLen, ret_op) \
528 UInt32 lenLimit; UInt32 hv; const Byte *cur; UInt32 curMatch; \
529 lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \
532 #define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0)
533 #define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue)
535 #define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue
537 #define GET_MATCHES_FOOTER(offset, maxLen) \
538 offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \
539 distances + offset, maxLen) - distances); MOVE_POS_RET;
541 #define SKIP_FOOTER \
542 SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;
544 #define UPDATE_maxLen { \
545 ptrdiff_t diff = (ptrdiff_t)0 - d2; \
546 const Byte *c = cur + maxLen; \
547 const Byte *lim = cur + lenLimit; \
548 for (; c != lim; c++) if (*(c + diff) != *c) break; \
549 maxLen = (UInt32)(c - cur); }
551 static UInt32
Bt2_MatchFinder_GetMatches(CMatchFinder
*p
, UInt32
*distances
)
554 GET_MATCHES_HEADER(2)
556 curMatch
= p
->hash
[hv
];
557 p
->hash
[hv
] = p
->pos
;
559 GET_MATCHES_FOOTER(offset
, 1)
562 UInt32
Bt3Zip_MatchFinder_GetMatches(CMatchFinder
*p
, UInt32
*distances
)
565 GET_MATCHES_HEADER(3)
567 curMatch
= p
->hash
[hv
];
568 p
->hash
[hv
] = p
->pos
;
570 GET_MATCHES_FOOTER(offset
, 2)
573 static UInt32
Bt3_MatchFinder_GetMatches(CMatchFinder
*p
, UInt32
*distances
)
575 UInt32 h2
, d2
, maxLen
, offset
, pos
;
577 GET_MATCHES_HEADER(3)
586 curMatch
= (hash
+ kFix3HashSize
)[hv
];
589 (hash
+ kFix3HashSize
)[hv
] = pos
;
594 if (d2
< p
->cyclicBufferSize
&& *(cur
- d2
) == *cur
)
597 distances
[0] = maxLen
;
598 distances
[1] = d2
- 1;
600 if (maxLen
== lenLimit
)
602 SkipMatchesSpec(lenLimit
, curMatch
, MF_PARAMS(p
));
607 GET_MATCHES_FOOTER(offset
, maxLen
)
610 static UInt32
Bt4_MatchFinder_GetMatches(CMatchFinder
*p
, UInt32
*distances
)
612 UInt32 h2
, h3
, d2
, d3
, maxLen
, offset
, pos
;
614 GET_MATCHES_HEADER(4)
621 d2
= pos
- hash
[ h2
];
622 d3
= pos
- (hash
+ kFix3HashSize
)[h3
];
624 curMatch
= (hash
+ kFix4HashSize
)[hv
];
627 (hash
+ kFix3HashSize
)[h3
] = pos
;
628 (hash
+ kFix4HashSize
)[hv
] = pos
;
633 if (d2
< p
->cyclicBufferSize
&& *(cur
- d2
) == *cur
)
635 distances
[0] = maxLen
= 2;
636 distances
[1] = d2
- 1;
640 if (d2
!= d3
&& d3
< p
->cyclicBufferSize
&& *(cur
- d3
) == *cur
)
643 distances
[(size_t)offset
+ 1] = d3
- 1;
651 distances
[(size_t)offset
- 2] = maxLen
;
652 if (maxLen
== lenLimit
)
654 SkipMatchesSpec(lenLimit
, curMatch
, MF_PARAMS(p
));
662 GET_MATCHES_FOOTER(offset
, maxLen
)
666 static UInt32 Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
668 UInt32 h2, h3, h4, d2, d3, d4, maxLen, offset, pos;
670 GET_MATCHES_HEADER(5)
677 d2 = pos - hash[ h2];
678 d3 = pos - (hash + kFix3HashSize)[h3];
679 d4 = pos - (hash + kFix4HashSize)[h4];
681 curMatch = (hash + kFix5HashSize)[hv];
684 (hash + kFix3HashSize)[h3] = pos;
685 (hash + kFix4HashSize)[h4] = pos;
686 (hash + kFix5HashSize)[hv] = pos;
691 if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
693 distances[0] = maxLen = 2;
694 distances[1] = d2 - 1;
696 if (*(cur - d2 + 2) == cur[2])
697 distances[0] = maxLen = 3;
698 else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
700 distances[2] = maxLen = 3;
701 distances[3] = d3 - 1;
706 else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
708 distances[0] = maxLen = 3;
709 distances[1] = d3 - 1;
714 if (d2 != d4 && d4 < p->cyclicBufferSize
715 && *(cur - d4) == *cur
716 && *(cur - d4 + 3) == *(cur + 3))
719 distances[(size_t)offset + 1] = d4 - 1;
727 distances[(size_t)offset - 2] = maxLen;
728 if (maxLen == lenLimit)
730 SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
738 GET_MATCHES_FOOTER(offset, maxLen)
742 static UInt32
Hc4_MatchFinder_GetMatches(CMatchFinder
*p
, UInt32
*distances
)
744 UInt32 h2
, h3
, d2
, d3
, maxLen
, offset
, pos
;
746 GET_MATCHES_HEADER(4)
753 d2
= pos
- hash
[ h2
];
754 d3
= pos
- (hash
+ kFix3HashSize
)[h3
];
756 curMatch
= (hash
+ kFix4HashSize
)[hv
];
759 (hash
+ kFix3HashSize
)[h3
] = pos
;
760 (hash
+ kFix4HashSize
)[hv
] = pos
;
765 if (d2
< p
->cyclicBufferSize
&& *(cur
- d2
) == *cur
)
767 distances
[0] = maxLen
= 2;
768 distances
[1] = d2
- 1;
772 if (d2
!= d3
&& d3
< p
->cyclicBufferSize
&& *(cur
- d3
) == *cur
)
775 distances
[(size_t)offset
+ 1] = d3
- 1;
783 distances
[(size_t)offset
- 2] = maxLen
;
784 if (maxLen
== lenLimit
)
786 p
->son
[p
->cyclicBufferPos
] = curMatch
;
794 offset
= (UInt32
)(Hc_GetMatchesSpec(lenLimit
, curMatch
, MF_PARAMS(p
),
795 distances
+ offset
, maxLen
) - (distances
));
800 static UInt32 Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
802 UInt32 h2, h3, h4, d2, d3, d4, maxLen, offset, pos
804 GET_MATCHES_HEADER(5)
811 d2 = pos - hash[ h2];
812 d3 = pos - (hash + kFix3HashSize)[h3];
813 d4 = pos - (hash + kFix4HashSize)[h4];
815 curMatch = (hash + kFix5HashSize)[hv];
818 (hash + kFix3HashSize)[h3] = pos;
819 (hash + kFix4HashSize)[h4] = pos;
820 (hash + kFix5HashSize)[hv] = pos;
825 if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
827 distances[0] = maxLen = 2;
828 distances[1] = d2 - 1;
830 if (*(cur - d2 + 2) == cur[2])
831 distances[0] = maxLen = 3;
832 else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
834 distances[2] = maxLen = 3;
835 distances[3] = d3 - 1;
840 else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
842 distances[0] = maxLen = 3;
843 distances[1] = d3 - 1;
848 if (d2 != d4 && d4 < p->cyclicBufferSize
849 && *(cur - d4) == *cur
850 && *(cur - d4 + 3) == *(cur + 3))
853 distances[(size_t)offset + 1] = d4 - 1;
861 distances[(size_t)offset - 2] = maxLen;
862 if (maxLen == lenLimit)
864 p->son[p->cyclicBufferPos] = curMatch;
872 offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
873 distances + offset, maxLen) - (distances));
878 UInt32
Hc3Zip_MatchFinder_GetMatches(CMatchFinder
*p
, UInt32
*distances
)
881 GET_MATCHES_HEADER(3)
883 curMatch
= p
->hash
[hv
];
884 p
->hash
[hv
] = p
->pos
;
885 offset
= (UInt32
)(Hc_GetMatchesSpec(lenLimit
, curMatch
, MF_PARAMS(p
),
886 distances
, 2) - (distances
));
890 static void Bt2_MatchFinder_Skip(CMatchFinder
*p
, UInt32 num
)
896 curMatch
= p
->hash
[hv
];
897 p
->hash
[hv
] = p
->pos
;
903 void Bt3Zip_MatchFinder_Skip(CMatchFinder
*p
, UInt32 num
)
909 curMatch
= p
->hash
[hv
];
910 p
->hash
[hv
] = p
->pos
;
916 static void Bt3_MatchFinder_Skip(CMatchFinder
*p
, UInt32 num
)
925 curMatch
= (hash
+ kFix3HashSize
)[hv
];
927 (hash
+ kFix3HashSize
)[hv
] = p
->pos
;
933 static void Bt4_MatchFinder_Skip(CMatchFinder
*p
, UInt32 num
)
942 curMatch
= (hash
+ kFix4HashSize
)[hv
];
944 (hash
+ kFix3HashSize
)[h3
] =
945 (hash
+ kFix4HashSize
)[hv
] = p
->pos
;
952 static void Bt5_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
961 curMatch = (hash + kFix5HashSize)[hv];
963 (hash + kFix3HashSize)[h3] =
964 (hash + kFix4HashSize)[h4] =
965 (hash + kFix5HashSize)[hv] = p->pos;
972 static void Hc4_MatchFinder_Skip(CMatchFinder
*p
, UInt32 num
)
981 curMatch
= (hash
+ kFix4HashSize
)[hv
];
983 (hash
+ kFix3HashSize
)[h3
] =
984 (hash
+ kFix4HashSize
)[hv
] = p
->pos
;
985 p
->son
[p
->cyclicBufferPos
] = curMatch
;
992 static void Hc5_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
1001 curMatch = hash + kFix5HashSize)[hv];
1003 (hash + kFix3HashSize)[h3] =
1004 (hash + kFix4HashSize)[h4] =
1005 (hash + kFix5HashSize)[hv] = p->pos;
1006 p->son[p->cyclicBufferPos] = curMatch;
1013 void Hc3Zip_MatchFinder_Skip(CMatchFinder
*p
, UInt32 num
)
1019 curMatch
= p
->hash
[hv
];
1020 p
->hash
[hv
] = p
->pos
;
1021 p
->son
[p
->cyclicBufferPos
] = curMatch
;
1027 void MatchFinder_CreateVTable(CMatchFinder
*p
, IMatchFinder
*vTable
)
1029 vTable
->Init
= (Mf_Init_Func
)MatchFinder_Init
;
1030 vTable
->GetNumAvailableBytes
= (Mf_GetNumAvailableBytes_Func
)MatchFinder_GetNumAvailableBytes
;
1031 vTable
->GetPointerToCurrentPos
= (Mf_GetPointerToCurrentPos_Func
)MatchFinder_GetPointerToCurrentPos
;
1034 /* if (p->numHashBytes <= 4) */
1036 vTable
->GetMatches
= (Mf_GetMatches_Func
)Hc4_MatchFinder_GetMatches
;
1037 vTable
->Skip
= (Mf_Skip_Func
)Hc4_MatchFinder_Skip
;
1042 vTable->GetMatches = (Mf_GetMatches_Func)Hc5_MatchFinder_GetMatches;
1043 vTable->Skip = (Mf_Skip_Func)Hc5_MatchFinder_Skip;
1047 else if (p
->numHashBytes
== 2)
1049 vTable
->GetMatches
= (Mf_GetMatches_Func
)Bt2_MatchFinder_GetMatches
;
1050 vTable
->Skip
= (Mf_Skip_Func
)Bt2_MatchFinder_Skip
;
1052 else if (p
->numHashBytes
== 3)
1054 vTable
->GetMatches
= (Mf_GetMatches_Func
)Bt3_MatchFinder_GetMatches
;
1055 vTable
->Skip
= (Mf_Skip_Func
)Bt3_MatchFinder_Skip
;
1057 else /* if (p->numHashBytes == 4) */
1059 vTable
->GetMatches
= (Mf_GetMatches_Func
)Bt4_MatchFinder_GetMatches
;
1060 vTable
->Skip
= (Mf_Skip_Func
)Bt4_MatchFinder_Skip
;
1065 vTable->GetMatches = (Mf_GetMatches_Func)Bt5_MatchFinder_GetMatches;
1066 vTable->Skip = (Mf_Skip_Func)Bt5_MatchFinder_Skip;