1 /* LzFind.c -- Match finder for LZ algorithms
2 2017-06-10 : Igor Pavlov : Public domain */
13 #define kEmptyHashValue 0
14 #define kMaxValForNormalize ((UInt32)0xFFFFFFFF)
15 #define kNormalizeStepMin (1 << 10) /* it must be power of 2 */
16 #define kNormalizeMask (~(UInt32)(kNormalizeStepMin - 1))
17 #define kMaxHistorySize ((UInt32)7 << 29)
19 #define kStartMaxLen 3
21 static void LzInWindow_Free(CMatchFinder
*p
, ISzAllocPtr alloc
)
25 ISzAlloc_Free(alloc
, p
->bufferBase
);
30 /* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */
32 static int LzInWindow_Create(CMatchFinder
*p
, UInt32 keepSizeReserv
, ISzAllocPtr alloc
)
34 UInt32 blockSize
= p
->keepSizeBefore
+ p
->keepSizeAfter
+ keepSizeReserv
;
37 p
->blockSize
= blockSize
;
40 if (!p
->bufferBase
|| p
->blockSize
!= blockSize
)
42 LzInWindow_Free(p
, alloc
);
43 p
->blockSize
= blockSize
;
44 p
->bufferBase
= (Byte
*)ISzAlloc_Alloc(alloc
, (size_t)blockSize
);
46 return (p
->bufferBase
!= NULL
);
49 Byte
*MatchFinder_GetPointerToCurrentPos(CMatchFinder
*p
) { return p
->buffer
; }
51 UInt32
MatchFinder_GetNumAvailableBytes(CMatchFinder
*p
) { return p
->streamPos
- p
->pos
; }
53 void MatchFinder_ReduceOffsets(CMatchFinder
*p
, UInt32 subValue
)
55 p
->posLimit
-= subValue
;
57 p
->streamPos
-= subValue
;
60 static void MatchFinder_ReadBlock(CMatchFinder
*p
)
62 if (p
->streamEndWasReached
|| p
->result
!= SZ_OK
)
65 /* We use (p->streamPos - p->pos) value. (p->streamPos < p->pos) is allowed. */
69 UInt32 curSize
= 0xFFFFFFFF - (p
->streamPos
- p
->pos
);
70 if (curSize
> p
->directInputRem
)
71 curSize
= (UInt32
)p
->directInputRem
;
72 p
->directInputRem
-= curSize
;
73 p
->streamPos
+= curSize
;
74 if (p
->directInputRem
== 0)
75 p
->streamEndWasReached
= 1;
81 Byte
*dest
= p
->buffer
+ (p
->streamPos
- p
->pos
);
82 size_t size
= (p
->bufferBase
+ p
->blockSize
- dest
);
86 p
->result
= ISeqInStream_Read(p
->stream
, dest
, &size
);
87 if (p
->result
!= SZ_OK
)
91 p
->streamEndWasReached
= 1;
94 p
->streamPos
+= (UInt32
)size
;
95 if (p
->streamPos
- p
->pos
> p
->keepSizeAfter
)
100 void MatchFinder_MoveBlock(CMatchFinder
*p
)
102 memmove(p
->bufferBase
,
103 p
->buffer
- p
->keepSizeBefore
,
104 (size_t)(p
->streamPos
- p
->pos
) + p
->keepSizeBefore
);
105 p
->buffer
= p
->bufferBase
+ p
->keepSizeBefore
;
108 int MatchFinder_NeedMove(CMatchFinder
*p
)
112 /* if (p->streamEndWasReached) return 0; */
113 return ((size_t)(p
->bufferBase
+ p
->blockSize
- p
->buffer
) <= p
->keepSizeAfter
);
116 void MatchFinder_ReadIfRequired(CMatchFinder
*p
)
118 if (p
->streamEndWasReached
)
120 if (p
->keepSizeAfter
>= p
->streamPos
- p
->pos
)
121 MatchFinder_ReadBlock(p
);
124 static void MatchFinder_CheckAndMoveAndRead(CMatchFinder
*p
)
126 if (MatchFinder_NeedMove(p
))
127 MatchFinder_MoveBlock(p
);
128 MatchFinder_ReadBlock(p
);
131 static void MatchFinder_SetDefaultSettings(CMatchFinder
*p
)
139 #define kCrcPoly 0xEDB88320
141 void MatchFinder_Construct(CMatchFinder
*p
)
144 p
->bufferBase
= NULL
;
147 p
->expectedDataSize
= (UInt64
)(Int64
)-1;
148 MatchFinder_SetDefaultSettings(p
);
150 for (i
= 0; i
< 256; i
++)
154 for (j
= 0; j
< 8; j
++)
155 r
= (r
>> 1) ^ (kCrcPoly
& ((UInt32
)0 - (r
& 1)));
160 static void MatchFinder_FreeThisClassMemory(CMatchFinder
*p
, ISzAllocPtr alloc
)
162 ISzAlloc_Free(alloc
, p
->hash
);
166 void MatchFinder_Free(CMatchFinder
*p
, ISzAllocPtr alloc
)
168 MatchFinder_FreeThisClassMemory(p
, alloc
);
169 LzInWindow_Free(p
, alloc
);
172 static CLzRef
* AllocRefs(size_t num
, ISzAllocPtr alloc
)
174 size_t sizeInBytes
= (size_t)num
* sizeof(CLzRef
);
175 if (sizeInBytes
/ sizeof(CLzRef
) != num
)
177 return (CLzRef
*)ISzAlloc_Alloc(alloc
, sizeInBytes
);
180 int MatchFinder_Create(CMatchFinder
*p
, UInt32 historySize
,
181 UInt32 keepAddBufferBefore
, UInt32 matchMaxLen
, UInt32 keepAddBufferAfter
,
186 if (historySize
> kMaxHistorySize
)
188 MatchFinder_Free(p
, alloc
);
192 sizeReserv
= historySize
>> 1;
193 if (historySize
>= ((UInt32
)3 << 30)) sizeReserv
= historySize
>> 3;
194 else if (historySize
>= ((UInt32
)2 << 30)) sizeReserv
= historySize
>> 2;
196 sizeReserv
+= (keepAddBufferBefore
+ matchMaxLen
+ keepAddBufferAfter
) / 2 + (1 << 19);
198 p
->keepSizeBefore
= historySize
+ keepAddBufferBefore
+ 1;
199 p
->keepSizeAfter
= matchMaxLen
+ keepAddBufferAfter
;
201 /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */
203 if (LzInWindow_Create(p
, sizeReserv
, alloc
))
205 UInt32 newCyclicBufferSize
= historySize
+ 1;
207 p
->matchMaxLen
= matchMaxLen
;
209 p
->fixedHashSize
= 0;
210 if (p
->numHashBytes
== 2)
215 if (hs
> p
->expectedDataSize
)
216 hs
= (UInt32
)p
->expectedDataSize
;
224 hs
|= 0xFFFF; /* don't change it! It's required for Deflate */
227 if (p
->numHashBytes
== 3)
231 /* if (bigHash) mode, GetHeads4b() in LzFindMt.c needs (hs >= ((1 << 24) - 1))) */
236 if (p
->numHashBytes
> 2) p
->fixedHashSize
+= kHash2Size
;
237 if (p
->numHashBytes
> 3) p
->fixedHashSize
+= kHash3Size
;
238 if (p
->numHashBytes
> 4) p
->fixedHashSize
+= kHash4Size
;
239 hs
+= p
->fixedHashSize
;
245 p
->historySize
= historySize
;
247 p
->cyclicBufferSize
= newCyclicBufferSize
;
249 numSons
= newCyclicBufferSize
;
252 newSize
= hs
+ numSons
;
254 if (p
->hash
&& p
->numRefs
== newSize
)
257 MatchFinder_FreeThisClassMemory(p
, alloc
);
258 p
->numRefs
= newSize
;
259 p
->hash
= AllocRefs(newSize
, alloc
);
263 p
->son
= p
->hash
+ p
->hashSizeSum
;
269 MatchFinder_Free(p
, alloc
);
273 static void MatchFinder_SetLimits(CMatchFinder
*p
)
275 UInt32 limit
= kMaxValForNormalize
- p
->pos
;
276 UInt32 limit2
= p
->cyclicBufferSize
- p
->cyclicBufferPos
;
280 limit2
= p
->streamPos
- p
->pos
;
282 if (limit2
<= p
->keepSizeAfter
)
288 limit2
-= p
->keepSizeAfter
;
294 UInt32 lenLimit
= p
->streamPos
- p
->pos
;
295 if (lenLimit
> p
->matchMaxLen
)
296 lenLimit
= p
->matchMaxLen
;
297 p
->lenLimit
= lenLimit
;
299 p
->posLimit
= p
->pos
+ limit
;
303 void MatchFinder_Init_LowHash(CMatchFinder
*p
)
306 CLzRef
*items
= p
->hash
;
307 size_t numItems
= p
->fixedHashSize
;
308 for (i
= 0; i
< numItems
; i
++)
309 items
[i
] = kEmptyHashValue
;
313 void MatchFinder_Init_HighHash(CMatchFinder
*p
)
316 CLzRef
*items
= p
->hash
+ p
->fixedHashSize
;
317 size_t numItems
= (size_t)p
->hashMask
+ 1;
318 for (i
= 0; i
< numItems
; i
++)
319 items
[i
] = kEmptyHashValue
;
323 void MatchFinder_Init_3(CMatchFinder
*p
, int readData
)
325 p
->cyclicBufferPos
= 0;
326 p
->buffer
= p
->bufferBase
;
328 p
->streamPos
= p
->cyclicBufferSize
;
330 p
->streamEndWasReached
= 0;
333 MatchFinder_ReadBlock(p
);
335 MatchFinder_SetLimits(p
);
339 void MatchFinder_Init(CMatchFinder
*p
)
341 MatchFinder_Init_HighHash(p
);
342 MatchFinder_Init_LowHash(p
);
343 MatchFinder_Init_3(p
, True
);
347 static UInt32
MatchFinder_GetSubValue(CMatchFinder
*p
)
349 return (p
->pos
- p
->historySize
- 1) & kNormalizeMask
;
352 void MatchFinder_Normalize3(UInt32 subValue
, CLzRef
*items
, size_t numItems
)
355 for (i
= 0; i
< numItems
; i
++)
357 UInt32 value
= items
[i
];
358 if (value
<= subValue
)
359 value
= kEmptyHashValue
;
366 static void MatchFinder_Normalize(CMatchFinder
*p
)
368 UInt32 subValue
= MatchFinder_GetSubValue(p
);
369 MatchFinder_Normalize3(subValue
, p
->hash
, p
->numRefs
);
370 MatchFinder_ReduceOffsets(p
, subValue
);
373 static void MatchFinder_CheckLimits(CMatchFinder
*p
)
375 if (p
->pos
== kMaxValForNormalize
)
376 MatchFinder_Normalize(p
);
377 if (!p
->streamEndWasReached
&& p
->keepSizeAfter
== p
->streamPos
- p
->pos
)
378 MatchFinder_CheckAndMoveAndRead(p
);
379 if (p
->cyclicBufferPos
== p
->cyclicBufferSize
)
380 p
->cyclicBufferPos
= 0;
381 MatchFinder_SetLimits(p
);
384 static UInt32
* Hc_GetMatchesSpec(UInt32 lenLimit
, UInt32 curMatch
, UInt32 pos
, const Byte
*cur
, CLzRef
*son
,
385 UInt32 _cyclicBufferPos
, UInt32 _cyclicBufferSize
, UInt32 cutValue
,
386 UInt32
*distances
, UInt32 maxLen
)
388 son
[_cyclicBufferPos
] = curMatch
;
391 UInt32 delta
= pos
- curMatch
;
392 if (cutValue
-- == 0 || delta
>= _cyclicBufferSize
)
395 const Byte
*pb
= cur
- delta
;
396 curMatch
= son
[_cyclicBufferPos
- delta
+ ((delta
> _cyclicBufferPos
) ? _cyclicBufferSize
: 0)];
397 if (pb
[maxLen
] == cur
[maxLen
] && *pb
== *cur
)
400 while (++len
!= lenLimit
)
401 if (pb
[len
] != cur
[len
])
405 *distances
++ = maxLen
= len
;
406 *distances
++ = delta
- 1;
415 UInt32
* GetMatchesSpec1(UInt32 lenLimit
, UInt32 curMatch
, UInt32 pos
, const Byte
*cur
, CLzRef
*son
,
416 UInt32 _cyclicBufferPos
, UInt32 _cyclicBufferSize
, UInt32 cutValue
,
417 UInt32
*distances
, UInt32 maxLen
)
419 CLzRef
*ptr0
= son
+ (_cyclicBufferPos
<< 1) + 1;
420 CLzRef
*ptr1
= son
+ (_cyclicBufferPos
<< 1);
421 UInt32 len0
= 0, len1
= 0;
424 UInt32 delta
= pos
- curMatch
;
425 if (cutValue
-- == 0 || delta
>= _cyclicBufferSize
)
427 *ptr0
= *ptr1
= kEmptyHashValue
;
431 CLzRef
*pair
= son
+ ((_cyclicBufferPos
- delta
+ ((delta
> _cyclicBufferPos
) ? _cyclicBufferSize
: 0)) << 1);
432 const Byte
*pb
= cur
- delta
;
433 UInt32 len
= (len0
< len1
? len0
: len1
);
434 if (pb
[len
] == cur
[len
])
436 if (++len
!= lenLimit
&& pb
[len
] == cur
[len
])
437 while (++len
!= lenLimit
)
438 if (pb
[len
] != cur
[len
])
442 *distances
++ = maxLen
= len
;
443 *distances
++ = delta
- 1;
452 if (pb
[len
] < cur
[len
])
470 static void SkipMatchesSpec(UInt32 lenLimit
, UInt32 curMatch
, UInt32 pos
, const Byte
*cur
, CLzRef
*son
,
471 UInt32 _cyclicBufferPos
, UInt32 _cyclicBufferSize
, UInt32 cutValue
)
473 CLzRef
*ptr0
= son
+ (_cyclicBufferPos
<< 1) + 1;
474 CLzRef
*ptr1
= son
+ (_cyclicBufferPos
<< 1);
475 UInt32 len0
= 0, len1
= 0;
478 UInt32 delta
= pos
- curMatch
;
479 if (cutValue
-- == 0 || delta
>= _cyclicBufferSize
)
481 *ptr0
= *ptr1
= kEmptyHashValue
;
485 CLzRef
*pair
= son
+ ((_cyclicBufferPos
- delta
+ ((delta
> _cyclicBufferPos
) ? _cyclicBufferSize
: 0)) << 1);
486 const Byte
*pb
= cur
- delta
;
487 UInt32 len
= (len0
< len1
? len0
: len1
);
488 if (pb
[len
] == cur
[len
])
490 while (++len
!= lenLimit
)
491 if (pb
[len
] != cur
[len
])
502 if (pb
[len
] < cur
[len
])
521 ++p->cyclicBufferPos; \
523 if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p);
525 #define MOVE_POS_RET MOVE_POS return offset;
527 static void MatchFinder_MovePos(CMatchFinder
*p
) { MOVE_POS
; }
529 #define GET_MATCHES_HEADER2(minLen, ret_op) \
530 UInt32 lenLimit; UInt32 hv; const Byte *cur; UInt32 curMatch; \
531 lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \
534 #define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0)
535 #define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue)
537 #define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue
539 #define GET_MATCHES_FOOTER(offset, maxLen) \
540 offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \
541 distances + offset, maxLen) - distances); MOVE_POS_RET;
543 #define SKIP_FOOTER \
544 SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;
546 #define UPDATE_maxLen { \
547 ptrdiff_t diff = (ptrdiff_t)0 - d2; \
548 const Byte *c = cur + maxLen; \
549 const Byte *lim = cur + lenLimit; \
550 for (; c != lim; c++) if (*(c + diff) != *c) break; \
551 maxLen = (UInt32)(c - cur); }
553 static UInt32
Bt2_MatchFinder_GetMatches(CMatchFinder
*p
, UInt32
*distances
)
556 GET_MATCHES_HEADER(2)
558 curMatch
= p
->hash
[hv
];
559 p
->hash
[hv
] = p
->pos
;
561 GET_MATCHES_FOOTER(offset
, 1)
564 UInt32
Bt3Zip_MatchFinder_GetMatches(CMatchFinder
*p
, UInt32
*distances
)
567 GET_MATCHES_HEADER(3)
569 curMatch
= p
->hash
[hv
];
570 p
->hash
[hv
] = p
->pos
;
572 GET_MATCHES_FOOTER(offset
, 2)
575 static UInt32
Bt3_MatchFinder_GetMatches(CMatchFinder
*p
, UInt32
*distances
)
577 UInt32 h2
, d2
, maxLen
, offset
, pos
;
579 GET_MATCHES_HEADER(3)
588 curMatch
= (hash
+ kFix3HashSize
)[hv
];
591 (hash
+ kFix3HashSize
)[hv
] = pos
;
596 if (d2
< p
->cyclicBufferSize
&& *(cur
- d2
) == *cur
)
599 distances
[0] = maxLen
;
600 distances
[1] = d2
- 1;
602 if (maxLen
== lenLimit
)
604 SkipMatchesSpec(lenLimit
, curMatch
, MF_PARAMS(p
));
609 GET_MATCHES_FOOTER(offset
, maxLen
)
612 static UInt32
Bt4_MatchFinder_GetMatches(CMatchFinder
*p
, UInt32
*distances
)
614 UInt32 h2
, h3
, d2
, d3
, maxLen
, offset
, pos
;
616 GET_MATCHES_HEADER(4)
623 d2
= pos
- hash
[ h2
];
624 d3
= pos
- (hash
+ kFix3HashSize
)[h3
];
626 curMatch
= (hash
+ kFix4HashSize
)[hv
];
629 (hash
+ kFix3HashSize
)[h3
] = pos
;
630 (hash
+ kFix4HashSize
)[hv
] = pos
;
635 if (d2
< p
->cyclicBufferSize
&& *(cur
- d2
) == *cur
)
637 distances
[0] = maxLen
= 2;
638 distances
[1] = d2
- 1;
642 if (d2
!= d3
&& d3
< p
->cyclicBufferSize
&& *(cur
- d3
) == *cur
)
645 distances
[(size_t)offset
+ 1] = d3
- 1;
653 distances
[(size_t)offset
- 2] = maxLen
;
654 if (maxLen
== lenLimit
)
656 SkipMatchesSpec(lenLimit
, curMatch
, MF_PARAMS(p
));
664 GET_MATCHES_FOOTER(offset
, maxLen
)
668 static UInt32 Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
670 UInt32 h2, h3, h4, d2, d3, d4, maxLen, offset, pos;
672 GET_MATCHES_HEADER(5)
679 d2 = pos - hash[ h2];
680 d3 = pos - (hash + kFix3HashSize)[h3];
681 d4 = pos - (hash + kFix4HashSize)[h4];
683 curMatch = (hash + kFix5HashSize)[hv];
686 (hash + kFix3HashSize)[h3] = pos;
687 (hash + kFix4HashSize)[h4] = pos;
688 (hash + kFix5HashSize)[hv] = pos;
693 if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
695 distances[0] = maxLen = 2;
696 distances[1] = d2 - 1;
698 if (*(cur - d2 + 2) == cur[2])
699 distances[0] = maxLen = 3;
700 else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
702 distances[2] = maxLen = 3;
703 distances[3] = d3 - 1;
708 else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
710 distances[0] = maxLen = 3;
711 distances[1] = d3 - 1;
716 if (d2 != d4 && d4 < p->cyclicBufferSize
717 && *(cur - d4) == *cur
718 && *(cur - d4 + 3) == *(cur + 3))
721 distances[(size_t)offset + 1] = d4 - 1;
729 distances[(size_t)offset - 2] = maxLen;
730 if (maxLen == lenLimit)
732 SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
740 GET_MATCHES_FOOTER(offset, maxLen)
744 static UInt32
Hc4_MatchFinder_GetMatches(CMatchFinder
*p
, UInt32
*distances
)
746 UInt32 h2
, h3
, d2
, d3
, maxLen
, offset
, pos
;
748 GET_MATCHES_HEADER(4)
755 d2
= pos
- hash
[ h2
];
756 d3
= pos
- (hash
+ kFix3HashSize
)[h3
];
758 curMatch
= (hash
+ kFix4HashSize
)[hv
];
761 (hash
+ kFix3HashSize
)[h3
] = pos
;
762 (hash
+ kFix4HashSize
)[hv
] = pos
;
767 if (d2
< p
->cyclicBufferSize
&& *(cur
- d2
) == *cur
)
769 distances
[0] = maxLen
= 2;
770 distances
[1] = d2
- 1;
774 if (d2
!= d3
&& d3
< p
->cyclicBufferSize
&& *(cur
- d3
) == *cur
)
777 distances
[(size_t)offset
+ 1] = d3
- 1;
785 distances
[(size_t)offset
- 2] = maxLen
;
786 if (maxLen
== lenLimit
)
788 p
->son
[p
->cyclicBufferPos
] = curMatch
;
796 offset
= (UInt32
)(Hc_GetMatchesSpec(lenLimit
, curMatch
, MF_PARAMS(p
),
797 distances
+ offset
, maxLen
) - (distances
));
802 static UInt32 Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
804 UInt32 h2, h3, h4, d2, d3, d4, maxLen, offset, pos
806 GET_MATCHES_HEADER(5)
813 d2 = pos - hash[ h2];
814 d3 = pos - (hash + kFix3HashSize)[h3];
815 d4 = pos - (hash + kFix4HashSize)[h4];
817 curMatch = (hash + kFix5HashSize)[hv];
820 (hash + kFix3HashSize)[h3] = pos;
821 (hash + kFix4HashSize)[h4] = pos;
822 (hash + kFix5HashSize)[hv] = pos;
827 if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
829 distances[0] = maxLen = 2;
830 distances[1] = d2 - 1;
832 if (*(cur - d2 + 2) == cur[2])
833 distances[0] = maxLen = 3;
834 else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
836 distances[2] = maxLen = 3;
837 distances[3] = d3 - 1;
842 else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
844 distances[0] = maxLen = 3;
845 distances[1] = d3 - 1;
850 if (d2 != d4 && d4 < p->cyclicBufferSize
851 && *(cur - d4) == *cur
852 && *(cur - d4 + 3) == *(cur + 3))
855 distances[(size_t)offset + 1] = d4 - 1;
863 distances[(size_t)offset - 2] = maxLen;
864 if (maxLen == lenLimit)
866 p->son[p->cyclicBufferPos] = curMatch;
874 offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
875 distances + offset, maxLen) - (distances));
880 UInt32
Hc3Zip_MatchFinder_GetMatches(CMatchFinder
*p
, UInt32
*distances
)
883 GET_MATCHES_HEADER(3)
885 curMatch
= p
->hash
[hv
];
886 p
->hash
[hv
] = p
->pos
;
887 offset
= (UInt32
)(Hc_GetMatchesSpec(lenLimit
, curMatch
, MF_PARAMS(p
),
888 distances
, 2) - (distances
));
892 static void Bt2_MatchFinder_Skip(CMatchFinder
*p
, UInt32 num
)
898 curMatch
= p
->hash
[hv
];
899 p
->hash
[hv
] = p
->pos
;
905 void Bt3Zip_MatchFinder_Skip(CMatchFinder
*p
, UInt32 num
)
911 curMatch
= p
->hash
[hv
];
912 p
->hash
[hv
] = p
->pos
;
918 static void Bt3_MatchFinder_Skip(CMatchFinder
*p
, UInt32 num
)
927 curMatch
= (hash
+ kFix3HashSize
)[hv
];
929 (hash
+ kFix3HashSize
)[hv
] = p
->pos
;
935 static void Bt4_MatchFinder_Skip(CMatchFinder
*p
, UInt32 num
)
944 curMatch
= (hash
+ kFix4HashSize
)[hv
];
946 (hash
+ kFix3HashSize
)[h3
] =
947 (hash
+ kFix4HashSize
)[hv
] = p
->pos
;
954 static void Bt5_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
963 curMatch = (hash + kFix5HashSize)[hv];
965 (hash + kFix3HashSize)[h3] =
966 (hash + kFix4HashSize)[h4] =
967 (hash + kFix5HashSize)[hv] = p->pos;
974 static void Hc4_MatchFinder_Skip(CMatchFinder
*p
, UInt32 num
)
983 curMatch
= (hash
+ kFix4HashSize
)[hv
];
985 (hash
+ kFix3HashSize
)[h3
] =
986 (hash
+ kFix4HashSize
)[hv
] = p
->pos
;
987 p
->son
[p
->cyclicBufferPos
] = curMatch
;
994 static void Hc5_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
1003 curMatch = hash + kFix5HashSize)[hv];
1005 (hash + kFix3HashSize)[h3] =
1006 (hash + kFix4HashSize)[h4] =
1007 (hash + kFix5HashSize)[hv] = p->pos;
1008 p->son[p->cyclicBufferPos] = curMatch;
1015 void Hc3Zip_MatchFinder_Skip(CMatchFinder
*p
, UInt32 num
)
1021 curMatch
= p
->hash
[hv
];
1022 p
->hash
[hv
] = p
->pos
;
1023 p
->son
[p
->cyclicBufferPos
] = curMatch
;
1029 void MatchFinder_CreateVTable(CMatchFinder
*p
, IMatchFinder
*vTable
)
1031 vTable
->Init
= (Mf_Init_Func
)MatchFinder_Init
;
1032 vTable
->GetNumAvailableBytes
= (Mf_GetNumAvailableBytes_Func
)MatchFinder_GetNumAvailableBytes
;
1033 vTable
->GetPointerToCurrentPos
= (Mf_GetPointerToCurrentPos_Func
)MatchFinder_GetPointerToCurrentPos
;
1036 /* if (p->numHashBytes <= 4) */
1038 vTable
->GetMatches
= (Mf_GetMatches_Func
)Hc4_MatchFinder_GetMatches
;
1039 vTable
->Skip
= (Mf_Skip_Func
)Hc4_MatchFinder_Skip
;
1044 vTable->GetMatches = (Mf_GetMatches_Func)Hc5_MatchFinder_GetMatches;
1045 vTable->Skip = (Mf_Skip_Func)Hc5_MatchFinder_Skip;
1049 else if (p
->numHashBytes
== 2)
1051 vTable
->GetMatches
= (Mf_GetMatches_Func
)Bt2_MatchFinder_GetMatches
;
1052 vTable
->Skip
= (Mf_Skip_Func
)Bt2_MatchFinder_Skip
;
1054 else if (p
->numHashBytes
== 3)
1056 vTable
->GetMatches
= (Mf_GetMatches_Func
)Bt3_MatchFinder_GetMatches
;
1057 vTable
->Skip
= (Mf_Skip_Func
)Bt3_MatchFinder_Skip
;
1059 else /* if (p->numHashBytes == 4) */
1061 vTable
->GetMatches
= (Mf_GetMatches_Func
)Bt4_MatchFinder_GetMatches
;
1062 vTable
->Skip
= (Mf_Skip_Func
)Bt4_MatchFinder_Skip
;
1067 vTable->GetMatches = (Mf_GetMatches_Func)Bt5_MatchFinder_GetMatches;
1068 vTable->Skip = (Mf_Skip_Func)Bt5_MatchFinder_Skip;