1 /* LzFind.c -- Match finder for LZ algorithms
2 2018-07-08 : 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
++)
152 UInt32 r
= (UInt32
)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
);
375 static void MatchFinder_CheckLimits(CMatchFinder
*p
)
377 if (p
->pos
== kMaxValForNormalize
)
378 MatchFinder_Normalize(p
);
379 if (!p
->streamEndWasReached
&& p
->keepSizeAfter
== p
->streamPos
- p
->pos
)
380 MatchFinder_CheckAndMoveAndRead(p
);
381 if (p
->cyclicBufferPos
== p
->cyclicBufferSize
)
382 p
->cyclicBufferPos
= 0;
383 MatchFinder_SetLimits(p
);
391 static UInt32
* Hc_GetMatchesSpec(unsigned lenLimit
, UInt32 curMatch
, UInt32 pos
, const Byte
*cur
, CLzRef
*son
,
392 UInt32 _cyclicBufferPos
, UInt32 _cyclicBufferSize
, UInt32 cutValue
,
393 UInt32
*distances
, unsigned maxLen
)
396 son[_cyclicBufferPos] = curMatch;
399 UInt32 delta = pos - curMatch;
400 if (cutValue-- == 0 || delta >= _cyclicBufferSize)
403 const Byte *pb = cur - delta;
404 curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];
405 if (pb[maxLen] == cur[maxLen] && *pb == *cur)
408 while (++len != lenLimit)
409 if (pb[len] != cur[len])
415 *distances++ = delta - 1;
424 const Byte
*lim
= cur
+ lenLimit
;
425 son
[_cyclicBufferPos
] = curMatch
;
428 UInt32 delta
= pos
- curMatch
;
429 if (delta
>= _cyclicBufferSize
)
433 curMatch
= son
[_cyclicBufferPos
- delta
+ ((delta
> _cyclicBufferPos
) ? _cyclicBufferSize
: 0)];
434 diff
= (ptrdiff_t)0 - delta
;
435 if (cur
[maxLen
] == cur
[maxLen
+ diff
])
438 while (*c
== c
[diff
])
442 distances
[0] = (UInt32
)(lim
- cur
);
443 distances
[1] = delta
- 1;
444 return distances
+ 2;
448 unsigned len
= (unsigned)(c
- cur
);
452 distances
[0] = (UInt32
)len
;
453 distances
[1] = delta
- 1;
467 UInt32
* GetMatchesSpec1(UInt32 lenLimit
, UInt32 curMatch
, UInt32 pos
, const Byte
*cur
, CLzRef
*son
,
468 UInt32 _cyclicBufferPos
, UInt32 _cyclicBufferSize
, UInt32 cutValue
,
469 UInt32
*distances
, UInt32 maxLen
)
471 CLzRef
*ptr0
= son
+ ((size_t)_cyclicBufferPos
<< 1) + 1;
472 CLzRef
*ptr1
= son
+ ((size_t)_cyclicBufferPos
<< 1);
473 unsigned len0
= 0, len1
= 0;
476 UInt32 delta
= pos
- curMatch
;
477 if (cutValue
-- == 0 || delta
>= _cyclicBufferSize
)
479 *ptr0
= *ptr1
= kEmptyHashValue
;
483 CLzRef
*pair
= son
+ ((size_t)(_cyclicBufferPos
- delta
+ ((delta
> _cyclicBufferPos
) ? _cyclicBufferSize
: 0)) << 1);
484 const Byte
*pb
= cur
- delta
;
485 unsigned len
= (len0
< len1
? len0
: len1
);
486 UInt32 pair0
= pair
[0];
487 if (pb
[len
] == cur
[len
])
489 if (++len
!= lenLimit
&& pb
[len
] == cur
[len
])
490 while (++len
!= lenLimit
)
491 if (pb
[len
] != cur
[len
])
495 maxLen
= (UInt32
)len
;
496 *distances
++ = (UInt32
)len
;
497 *distances
++ = delta
- 1;
506 if (pb
[len
] < cur
[len
])
524 static void SkipMatchesSpec(UInt32 lenLimit
, UInt32 curMatch
, UInt32 pos
, const Byte
*cur
, CLzRef
*son
,
525 UInt32 _cyclicBufferPos
, UInt32 _cyclicBufferSize
, UInt32 cutValue
)
527 CLzRef
*ptr0
= son
+ ((size_t)_cyclicBufferPos
<< 1) + 1;
528 CLzRef
*ptr1
= son
+ ((size_t)_cyclicBufferPos
<< 1);
529 unsigned len0
= 0, len1
= 0;
532 UInt32 delta
= pos
- curMatch
;
533 if (cutValue
-- == 0 || delta
>= _cyclicBufferSize
)
535 *ptr0
= *ptr1
= kEmptyHashValue
;
539 CLzRef
*pair
= son
+ ((size_t)(_cyclicBufferPos
- delta
+ ((delta
> _cyclicBufferPos
) ? _cyclicBufferSize
: 0)) << 1);
540 const Byte
*pb
= cur
- delta
;
541 unsigned len
= (len0
< len1
? len0
: len1
);
542 if (pb
[len
] == cur
[len
])
544 while (++len
!= lenLimit
)
545 if (pb
[len
] != cur
[len
])
556 if (pb
[len
] < cur
[len
])
575 ++p->cyclicBufferPos; \
577 if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p);
579 #define MOVE_POS_RET MOVE_POS return (UInt32)offset;
581 static void MatchFinder_MovePos(CMatchFinder
*p
) { MOVE_POS
; }
583 #define GET_MATCHES_HEADER2(minLen, ret_op) \
584 unsigned lenLimit; UInt32 hv; const Byte *cur; UInt32 curMatch; \
585 lenLimit = (unsigned)p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \
588 #define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0)
589 #define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue)
591 #define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue
593 #define GET_MATCHES_FOOTER(offset, maxLen) \
594 offset = (unsigned)(GetMatchesSpec1((UInt32)lenLimit, curMatch, MF_PARAMS(p), \
595 distances + offset, (UInt32)maxLen) - distances); MOVE_POS_RET;
597 #define SKIP_FOOTER \
598 SkipMatchesSpec((UInt32)lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;
600 #define UPDATE_maxLen { \
601 ptrdiff_t diff = (ptrdiff_t)0 - d2; \
602 const Byte *c = cur + maxLen; \
603 const Byte *lim = cur + lenLimit; \
604 for (; c != lim; c++) if (*(c + diff) != *c) break; \
605 maxLen = (unsigned)(c - cur); }
607 static UInt32
Bt2_MatchFinder_GetMatches(CMatchFinder
*p
, UInt32
*distances
)
610 GET_MATCHES_HEADER(2)
612 curMatch
= p
->hash
[hv
];
613 p
->hash
[hv
] = p
->pos
;
615 GET_MATCHES_FOOTER(offset
, 1)
618 UInt32
Bt3Zip_MatchFinder_GetMatches(CMatchFinder
*p
, UInt32
*distances
)
621 GET_MATCHES_HEADER(3)
623 curMatch
= p
->hash
[hv
];
624 p
->hash
[hv
] = p
->pos
;
626 GET_MATCHES_FOOTER(offset
, 2)
629 static UInt32
Bt3_MatchFinder_GetMatches(CMatchFinder
*p
, UInt32
*distances
)
632 unsigned maxLen
, offset
;
634 GET_MATCHES_HEADER(3)
643 curMatch
= (hash
+ kFix3HashSize
)[hv
];
646 (hash
+ kFix3HashSize
)[hv
] = pos
;
651 if (d2
< p
->cyclicBufferSize
&& *(cur
- d2
) == *cur
)
654 distances
[0] = (UInt32
)maxLen
;
655 distances
[1] = d2
- 1;
657 if (maxLen
== lenLimit
)
659 SkipMatchesSpec((UInt32
)lenLimit
, curMatch
, MF_PARAMS(p
));
664 GET_MATCHES_FOOTER(offset
, maxLen
)
667 static UInt32
Bt4_MatchFinder_GetMatches(CMatchFinder
*p
, UInt32
*distances
)
669 UInt32 h2
, h3
, d2
, d3
, pos
;
670 unsigned maxLen
, offset
;
672 GET_MATCHES_HEADER(4)
679 d2
= pos
- hash
[ h2
];
680 d3
= pos
- (hash
+ kFix3HashSize
)[h3
];
682 curMatch
= (hash
+ kFix4HashSize
)[hv
];
685 (hash
+ kFix3HashSize
)[h3
] = pos
;
686 (hash
+ kFix4HashSize
)[hv
] = pos
;
691 if (d2
< p
->cyclicBufferSize
&& *(cur
- d2
) == *cur
)
695 distances
[1] = d2
- 1;
699 if (d2
!= d3
&& d3
< p
->cyclicBufferSize
&& *(cur
- d3
) == *cur
)
702 distances
[(size_t)offset
+ 1] = d3
- 1;
710 distances
[(size_t)offset
- 2] = (UInt32
)maxLen
;
711 if (maxLen
== lenLimit
)
713 SkipMatchesSpec((UInt32
)lenLimit
, curMatch
, MF_PARAMS(p
));
721 GET_MATCHES_FOOTER(offset
, maxLen
)
725 static UInt32 Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
727 UInt32 h2, h3, h4, d2, d3, d4, maxLen, offset, pos;
729 GET_MATCHES_HEADER(5)
736 d2 = pos - hash[ h2];
737 d3 = pos - (hash + kFix3HashSize)[h3];
738 d4 = pos - (hash + kFix4HashSize)[h4];
740 curMatch = (hash + kFix5HashSize)[hv];
743 (hash + kFix3HashSize)[h3] = pos;
744 (hash + kFix4HashSize)[h4] = pos;
745 (hash + kFix5HashSize)[hv] = pos;
750 if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
752 distances[0] = maxLen = 2;
753 distances[1] = d2 - 1;
755 if (*(cur - d2 + 2) == cur[2])
756 distances[0] = maxLen = 3;
757 else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
759 distances[2] = maxLen = 3;
760 distances[3] = d3 - 1;
765 else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
767 distances[0] = maxLen = 3;
768 distances[1] = d3 - 1;
773 if (d2 != d4 && d4 < p->cyclicBufferSize
774 && *(cur - d4) == *cur
775 && *(cur - d4 + 3) == *(cur + 3))
778 distances[(size_t)offset + 1] = d4 - 1;
786 distances[(size_t)offset - 2] = maxLen;
787 if (maxLen == lenLimit)
789 SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
797 GET_MATCHES_FOOTER(offset, maxLen)
801 static UInt32
Hc4_MatchFinder_GetMatches(CMatchFinder
*p
, UInt32
*distances
)
803 UInt32 h2
, h3
, d2
, d3
, pos
;
804 unsigned maxLen
, offset
;
806 GET_MATCHES_HEADER(4)
813 d2
= pos
- hash
[ h2
];
814 d3
= pos
- (hash
+ kFix3HashSize
)[h3
];
816 curMatch
= (hash
+ kFix4HashSize
)[hv
];
819 (hash
+ kFix3HashSize
)[h3
] = pos
;
820 (hash
+ kFix4HashSize
)[hv
] = pos
;
825 if (d2
< p
->cyclicBufferSize
&& *(cur
- d2
) == *cur
)
829 distances
[1] = d2
- 1;
833 if (d2
!= d3
&& d3
< p
->cyclicBufferSize
&& *(cur
- d3
) == *cur
)
836 distances
[(size_t)offset
+ 1] = d3
- 1;
844 distances
[(size_t)offset
- 2] = (UInt32
)maxLen
;
845 if (maxLen
== lenLimit
)
847 p
->son
[p
->cyclicBufferPos
] = curMatch
;
855 offset
= (unsigned)(Hc_GetMatchesSpec(lenLimit
, curMatch
, MF_PARAMS(p
),
856 distances
+ offset
, maxLen
) - (distances
));
861 static UInt32 Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
863 UInt32 h2, h3, h4, d2, d3, d4, maxLen, offset, pos
865 GET_MATCHES_HEADER(5)
872 d2 = pos - hash[ h2];
873 d3 = pos - (hash + kFix3HashSize)[h3];
874 d4 = pos - (hash + kFix4HashSize)[h4];
876 curMatch = (hash + kFix5HashSize)[hv];
879 (hash + kFix3HashSize)[h3] = pos;
880 (hash + kFix4HashSize)[h4] = pos;
881 (hash + kFix5HashSize)[hv] = pos;
886 if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
888 distances[0] = maxLen = 2;
889 distances[1] = d2 - 1;
891 if (*(cur - d2 + 2) == cur[2])
892 distances[0] = maxLen = 3;
893 else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
895 distances[2] = maxLen = 3;
896 distances[3] = d3 - 1;
901 else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
903 distances[0] = maxLen = 3;
904 distances[1] = d3 - 1;
909 if (d2 != d4 && d4 < p->cyclicBufferSize
910 && *(cur - d4) == *cur
911 && *(cur - d4 + 3) == *(cur + 3))
914 distances[(size_t)offset + 1] = d4 - 1;
922 distances[(size_t)offset - 2] = maxLen;
923 if (maxLen == lenLimit)
925 p->son[p->cyclicBufferPos] = curMatch;
933 offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
934 distances + offset, maxLen) - (distances));
939 UInt32
Hc3Zip_MatchFinder_GetMatches(CMatchFinder
*p
, UInt32
*distances
)
942 GET_MATCHES_HEADER(3)
944 curMatch
= p
->hash
[hv
];
945 p
->hash
[hv
] = p
->pos
;
946 offset
= (unsigned)(Hc_GetMatchesSpec(lenLimit
, curMatch
, MF_PARAMS(p
),
947 distances
, 2) - (distances
));
951 static void Bt2_MatchFinder_Skip(CMatchFinder
*p
, UInt32 num
)
957 curMatch
= p
->hash
[hv
];
958 p
->hash
[hv
] = p
->pos
;
964 void Bt3Zip_MatchFinder_Skip(CMatchFinder
*p
, UInt32 num
)
970 curMatch
= p
->hash
[hv
];
971 p
->hash
[hv
] = p
->pos
;
977 static void Bt3_MatchFinder_Skip(CMatchFinder
*p
, UInt32 num
)
986 curMatch
= (hash
+ kFix3HashSize
)[hv
];
988 (hash
+ kFix3HashSize
)[hv
] = p
->pos
;
994 static void Bt4_MatchFinder_Skip(CMatchFinder
*p
, UInt32 num
)
1003 curMatch
= (hash
+ kFix4HashSize
)[hv
];
1005 (hash
+ kFix3HashSize
)[h3
] =
1006 (hash
+ kFix4HashSize
)[hv
] = p
->pos
;
1013 static void Bt5_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
1022 curMatch = (hash + kFix5HashSize)[hv];
1024 (hash + kFix3HashSize)[h3] =
1025 (hash + kFix4HashSize)[h4] =
1026 (hash + kFix5HashSize)[hv] = p->pos;
1033 static void Hc4_MatchFinder_Skip(CMatchFinder
*p
, UInt32 num
)
1042 curMatch
= (hash
+ kFix4HashSize
)[hv
];
1044 (hash
+ kFix3HashSize
)[h3
] =
1045 (hash
+ kFix4HashSize
)[hv
] = p
->pos
;
1046 p
->son
[p
->cyclicBufferPos
] = curMatch
;
1053 static void Hc5_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
1062 curMatch = hash + kFix5HashSize)[hv];
1064 (hash + kFix3HashSize)[h3] =
1065 (hash + kFix4HashSize)[h4] =
1066 (hash + kFix5HashSize)[hv] = p->pos;
1067 p->son[p->cyclicBufferPos] = curMatch;
1074 void Hc3Zip_MatchFinder_Skip(CMatchFinder
*p
, UInt32 num
)
1080 curMatch
= p
->hash
[hv
];
1081 p
->hash
[hv
] = p
->pos
;
1082 p
->son
[p
->cyclicBufferPos
] = curMatch
;
1088 void MatchFinder_CreateVTable(CMatchFinder
*p
, IMatchFinder
*vTable
)
1090 vTable
->Init
= (Mf_Init_Func
)MatchFinder_Init
;
1091 vTable
->GetNumAvailableBytes
= (Mf_GetNumAvailableBytes_Func
)MatchFinder_GetNumAvailableBytes
;
1092 vTable
->GetPointerToCurrentPos
= (Mf_GetPointerToCurrentPos_Func
)MatchFinder_GetPointerToCurrentPos
;
1095 /* if (p->numHashBytes <= 4) */
1097 vTable
->GetMatches
= (Mf_GetMatches_Func
)Hc4_MatchFinder_GetMatches
;
1098 vTable
->Skip
= (Mf_Skip_Func
)Hc4_MatchFinder_Skip
;
1103 vTable->GetMatches = (Mf_GetMatches_Func)Hc5_MatchFinder_GetMatches;
1104 vTable->Skip = (Mf_Skip_Func)Hc5_MatchFinder_Skip;
1108 else if (p
->numHashBytes
== 2)
1110 vTable
->GetMatches
= (Mf_GetMatches_Func
)Bt2_MatchFinder_GetMatches
;
1111 vTable
->Skip
= (Mf_Skip_Func
)Bt2_MatchFinder_Skip
;
1113 else if (p
->numHashBytes
== 3)
1115 vTable
->GetMatches
= (Mf_GetMatches_Func
)Bt3_MatchFinder_GetMatches
;
1116 vTable
->Skip
= (Mf_Skip_Func
)Bt3_MatchFinder_Skip
;
1118 else /* if (p->numHashBytes == 4) */
1120 vTable
->GetMatches
= (Mf_GetMatches_Func
)Bt4_MatchFinder_GetMatches
;
1121 vTable
->Skip
= (Mf_Skip_Func
)Bt4_MatchFinder_Skip
;
1126 vTable->GetMatches = (Mf_GetMatches_Func)Bt5_MatchFinder_GetMatches;
1127 vTable->Skip = (Mf_Skip_Func)Bt5_MatchFinder_Skip;