1 /* LzFind.c -- Match finder for LZ algorithms
2 2018-07-08 : 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
++)
150 UInt32 r
= (UInt32
)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
);
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
);
389 static UInt32
* Hc_GetMatchesSpec(unsigned lenLimit
, UInt32 curMatch
, UInt32 pos
, const Byte
*cur
, CLzRef
*son
,
390 UInt32 _cyclicBufferPos
, UInt32 _cyclicBufferSize
, UInt32 cutValue
,
391 UInt32
*distances
, unsigned maxLen
)
394 son[_cyclicBufferPos] = curMatch;
397 UInt32 delta = pos - curMatch;
398 if (cutValue-- == 0 || delta >= _cyclicBufferSize)
401 const Byte *pb = cur - delta;
402 curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];
403 if (pb[maxLen] == cur[maxLen] && *pb == *cur)
406 while (++len != lenLimit)
407 if (pb[len] != cur[len])
413 *distances++ = delta - 1;
422 const Byte
*lim
= cur
+ lenLimit
;
423 son
[_cyclicBufferPos
] = curMatch
;
426 UInt32 delta
= pos
- curMatch
;
427 if (delta
>= _cyclicBufferSize
)
431 curMatch
= son
[_cyclicBufferPos
- delta
+ ((delta
> _cyclicBufferPos
) ? _cyclicBufferSize
: 0)];
432 diff
= (ptrdiff_t)0 - delta
;
433 if (cur
[maxLen
] == cur
[maxLen
+ diff
])
436 while (*c
== c
[diff
])
440 distances
[0] = (UInt32
)(lim
- cur
);
441 distances
[1] = delta
- 1;
442 return distances
+ 2;
446 unsigned len
= (unsigned)(c
- cur
);
450 distances
[0] = (UInt32
)len
;
451 distances
[1] = delta
- 1;
465 UInt32
* GetMatchesSpec1(UInt32 lenLimit
, UInt32 curMatch
, UInt32 pos
, const Byte
*cur
, CLzRef
*son
,
466 UInt32 _cyclicBufferPos
, UInt32 _cyclicBufferSize
, UInt32 cutValue
,
467 UInt32
*distances
, UInt32 maxLen
)
469 CLzRef
*ptr0
= son
+ ((size_t)_cyclicBufferPos
<< 1) + 1;
470 CLzRef
*ptr1
= son
+ ((size_t)_cyclicBufferPos
<< 1);
471 unsigned len0
= 0, len1
= 0;
474 UInt32 delta
= pos
- curMatch
;
475 if (cutValue
-- == 0 || delta
>= _cyclicBufferSize
)
477 *ptr0
= *ptr1
= kEmptyHashValue
;
481 CLzRef
*pair
= son
+ ((size_t)(_cyclicBufferPos
- delta
+ ((delta
> _cyclicBufferPos
) ? _cyclicBufferSize
: 0)) << 1);
482 const Byte
*pb
= cur
- delta
;
483 unsigned len
= (len0
< len1
? len0
: len1
);
484 UInt32 pair0
= pair
[0];
485 if (pb
[len
] == cur
[len
])
487 if (++len
!= lenLimit
&& pb
[len
] == cur
[len
])
488 while (++len
!= lenLimit
)
489 if (pb
[len
] != cur
[len
])
493 maxLen
= (UInt32
)len
;
494 *distances
++ = (UInt32
)len
;
495 *distances
++ = delta
- 1;
504 if (pb
[len
] < cur
[len
])
522 static void SkipMatchesSpec(UInt32 lenLimit
, UInt32 curMatch
, UInt32 pos
, const Byte
*cur
, CLzRef
*son
,
523 UInt32 _cyclicBufferPos
, UInt32 _cyclicBufferSize
, UInt32 cutValue
)
525 CLzRef
*ptr0
= son
+ ((size_t)_cyclicBufferPos
<< 1) + 1;
526 CLzRef
*ptr1
= son
+ ((size_t)_cyclicBufferPos
<< 1);
527 unsigned len0
= 0, len1
= 0;
530 UInt32 delta
= pos
- curMatch
;
531 if (cutValue
-- == 0 || delta
>= _cyclicBufferSize
)
533 *ptr0
= *ptr1
= kEmptyHashValue
;
537 CLzRef
*pair
= son
+ ((size_t)(_cyclicBufferPos
- delta
+ ((delta
> _cyclicBufferPos
) ? _cyclicBufferSize
: 0)) << 1);
538 const Byte
*pb
= cur
- delta
;
539 unsigned len
= (len0
< len1
? len0
: len1
);
540 if (pb
[len
] == cur
[len
])
542 while (++len
!= lenLimit
)
543 if (pb
[len
] != cur
[len
])
554 if (pb
[len
] < cur
[len
])
573 ++p->cyclicBufferPos; \
575 if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p);
577 #define MOVE_POS_RET MOVE_POS return (UInt32)offset;
579 static void MatchFinder_MovePos(CMatchFinder
*p
) { MOVE_POS
; }
581 #define GET_MATCHES_HEADER2(minLen, ret_op) \
582 unsigned lenLimit; UInt32 hv; const Byte *cur; UInt32 curMatch; \
583 lenLimit = (unsigned)p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \
586 #define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0)
587 #define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue)
589 #define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue
591 #define GET_MATCHES_FOOTER(offset, maxLen) \
592 offset = (unsigned)(GetMatchesSpec1((UInt32)lenLimit, curMatch, MF_PARAMS(p), \
593 distances + offset, (UInt32)maxLen) - distances); MOVE_POS_RET;
595 #define SKIP_FOOTER \
596 SkipMatchesSpec((UInt32)lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;
598 #define UPDATE_maxLen { \
599 ptrdiff_t diff = (ptrdiff_t)0 - d2; \
600 const Byte *c = cur + maxLen; \
601 const Byte *lim = cur + lenLimit; \
602 for (; c != lim; c++) if (*(c + diff) != *c) break; \
603 maxLen = (unsigned)(c - cur); }
605 static UInt32
Bt2_MatchFinder_GetMatches(CMatchFinder
*p
, UInt32
*distances
)
608 GET_MATCHES_HEADER(2)
610 curMatch
= p
->hash
[hv
];
611 p
->hash
[hv
] = p
->pos
;
613 GET_MATCHES_FOOTER(offset
, 1)
616 UInt32
Bt3Zip_MatchFinder_GetMatches(CMatchFinder
*p
, UInt32
*distances
)
619 GET_MATCHES_HEADER(3)
621 curMatch
= p
->hash
[hv
];
622 p
->hash
[hv
] = p
->pos
;
624 GET_MATCHES_FOOTER(offset
, 2)
627 static UInt32
Bt3_MatchFinder_GetMatches(CMatchFinder
*p
, UInt32
*distances
)
630 unsigned maxLen
, offset
;
632 GET_MATCHES_HEADER(3)
641 curMatch
= (hash
+ kFix3HashSize
)[hv
];
644 (hash
+ kFix3HashSize
)[hv
] = pos
;
649 if (d2
< p
->cyclicBufferSize
&& *(cur
- d2
) == *cur
)
652 distances
[0] = (UInt32
)maxLen
;
653 distances
[1] = d2
- 1;
655 if (maxLen
== lenLimit
)
657 SkipMatchesSpec((UInt32
)lenLimit
, curMatch
, MF_PARAMS(p
));
662 GET_MATCHES_FOOTER(offset
, maxLen
)
665 static UInt32
Bt4_MatchFinder_GetMatches(CMatchFinder
*p
, UInt32
*distances
)
667 UInt32 h2
, h3
, d2
, d3
, pos
;
668 unsigned maxLen
, offset
;
670 GET_MATCHES_HEADER(4)
677 d2
= pos
- hash
[h2
];
678 d3
= pos
- (hash
+ kFix3HashSize
)[h3
];
680 curMatch
= (hash
+ kFix4HashSize
)[hv
];
683 (hash
+ kFix3HashSize
)[h3
] = pos
;
684 (hash
+ kFix4HashSize
)[hv
] = pos
;
689 if (d2
< p
->cyclicBufferSize
&& *(cur
- d2
) == *cur
)
693 distances
[1] = d2
- 1;
697 if (d2
!= d3
&& d3
< p
->cyclicBufferSize
&& *(cur
- d3
) == *cur
)
700 distances
[(size_t)offset
+ 1] = d3
- 1;
708 distances
[(size_t)offset
- 2] = (UInt32
)maxLen
;
709 if (maxLen
== lenLimit
)
711 SkipMatchesSpec((UInt32
)lenLimit
, curMatch
, MF_PARAMS(p
));
719 GET_MATCHES_FOOTER(offset
, maxLen
)
723 static UInt32 Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
725 UInt32 h2, h3, h4, d2, d3, d4, maxLen, offset, pos;
727 GET_MATCHES_HEADER(5)
734 d2 = pos - hash [h2];
735 d3 = pos - (hash + kFix3HashSize)[h3];
736 d4 = pos - (hash + kFix4HashSize)[h4];
738 curMatch = (hash + kFix5HashSize)[hv];
741 (hash + kFix3HashSize)[h3] = pos;
742 (hash + kFix4HashSize)[h4] = pos;
743 (hash + kFix5HashSize)[hv] = pos;
748 if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
750 distances[0] = maxLen = 2;
751 distances[1] = d2 - 1;
753 if (*(cur - d2 + 2) == cur[2])
754 distances[0] = maxLen = 3;
755 else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
757 distances[2] = maxLen = 3;
758 distances[3] = d3 - 1;
763 else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
765 distances[0] = maxLen = 3;
766 distances[1] = d3 - 1;
771 if (d2 != d4 && d4 < p->cyclicBufferSize
772 && *(cur - d4) == *cur
773 && *(cur - d4 + 3) == *(cur + 3))
776 distances[(size_t)offset + 1] = d4 - 1;
784 distances[(size_t)offset - 2] = maxLen;
785 if (maxLen == lenLimit)
787 SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
795 GET_MATCHES_FOOTER(offset, maxLen)
799 static UInt32
Hc4_MatchFinder_GetMatches(CMatchFinder
*p
, UInt32
*distances
)
801 UInt32 h2
, h3
, d2
, d3
, pos
;
802 unsigned maxLen
, offset
;
804 GET_MATCHES_HEADER(4)
811 d2
= pos
- hash
[h2
];
812 d3
= pos
- (hash
+ kFix3HashSize
)[h3
];
813 curMatch
= (hash
+ kFix4HashSize
)[hv
];
816 (hash
+ kFix3HashSize
)[h3
] = pos
;
817 (hash
+ kFix4HashSize
)[hv
] = pos
;
822 if (d2
< p
->cyclicBufferSize
&& *(cur
- d2
) == *cur
)
826 distances
[1] = d2
- 1;
830 if (d2
!= d3
&& d3
< p
->cyclicBufferSize
&& *(cur
- d3
) == *cur
)
833 distances
[(size_t)offset
+ 1] = d3
- 1;
841 distances
[(size_t)offset
- 2] = (UInt32
)maxLen
;
842 if (maxLen
== lenLimit
)
844 p
->son
[p
->cyclicBufferPos
] = curMatch
;
852 offset
= (unsigned)(Hc_GetMatchesSpec(lenLimit
, curMatch
, MF_PARAMS(p
),
853 distances
+ offset
, maxLen
) - (distances
));
858 static UInt32 Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
860 UInt32 h2, h3, h4, d2, d3, d4, maxLen, offset, pos
862 GET_MATCHES_HEADER(5)
869 d2 = pos - hash [h2];
870 d3 = pos - (hash + kFix3HashSize)[h3];
871 d4 = pos - (hash + kFix4HashSize)[h4];
873 curMatch = (hash + kFix5HashSize)[hv];
876 (hash + kFix3HashSize)[h3] = pos;
877 (hash + kFix4HashSize)[h4] = pos;
878 (hash + kFix5HashSize)[hv] = pos;
883 if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
885 distances[0] = maxLen = 2;
886 distances[1] = d2 - 1;
888 if (*(cur - d2 + 2) == cur[2])
889 distances[0] = maxLen = 3;
890 else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
892 distances[2] = maxLen = 3;
893 distances[3] = d3 - 1;
898 else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
900 distances[0] = maxLen = 3;
901 distances[1] = d3 - 1;
906 if (d2 != d4 && d4 < p->cyclicBufferSize
907 && *(cur - d4) == *cur
908 && *(cur - d4 + 3) == *(cur + 3))
911 distances[(size_t)offset + 1] = d4 - 1;
919 distances[(size_t)offset - 2] = maxLen;
920 if (maxLen == lenLimit)
922 p->son[p->cyclicBufferPos] = curMatch;
930 offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
931 distances + offset, maxLen) - (distances));
936 UInt32
Hc3Zip_MatchFinder_GetMatches(CMatchFinder
*p
, UInt32
*distances
)
939 GET_MATCHES_HEADER(3)
941 curMatch
= p
->hash
[hv
];
942 p
->hash
[hv
] = p
->pos
;
943 offset
= (unsigned)(Hc_GetMatchesSpec(lenLimit
, curMatch
, MF_PARAMS(p
),
944 distances
, 2) - (distances
));
948 static void Bt2_MatchFinder_Skip(CMatchFinder
*p
, UInt32 num
)
954 curMatch
= p
->hash
[hv
];
955 p
->hash
[hv
] = p
->pos
;
961 void Bt3Zip_MatchFinder_Skip(CMatchFinder
*p
, UInt32 num
)
967 curMatch
= p
->hash
[hv
];
968 p
->hash
[hv
] = p
->pos
;
974 static void Bt3_MatchFinder_Skip(CMatchFinder
*p
, UInt32 num
)
983 curMatch
= (hash
+ kFix3HashSize
)[hv
];
985 (hash
+ kFix3HashSize
)[hv
] = p
->pos
;
991 static void Bt4_MatchFinder_Skip(CMatchFinder
*p
, UInt32 num
)
1000 curMatch
= (hash
+ kFix4HashSize
)[hv
];
1002 (hash
+ kFix3HashSize
)[h3
] =
1003 (hash
+ kFix4HashSize
)[hv
] = p
->pos
;
1010 static void Bt5_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
1019 curMatch = (hash + kFix5HashSize)[hv];
1021 (hash + kFix3HashSize)[h3] =
1022 (hash + kFix4HashSize)[h4] =
1023 (hash + kFix5HashSize)[hv] = p->pos;
1030 static void Hc4_MatchFinder_Skip(CMatchFinder
*p
, UInt32 num
)
1039 curMatch
= (hash
+ kFix4HashSize
)[hv
];
1041 (hash
+ kFix3HashSize
)[h3
] =
1042 (hash
+ kFix4HashSize
)[hv
] = p
->pos
;
1043 p
->son
[p
->cyclicBufferPos
] = curMatch
;
1050 static void Hc5_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
1059 curMatch = hash + kFix5HashSize)[hv];
1061 (hash + kFix3HashSize)[h3] =
1062 (hash + kFix4HashSize)[h4] =
1063 (hash + kFix5HashSize)[hv] = p->pos;
1064 p->son[p->cyclicBufferPos] = curMatch;
1071 void Hc3Zip_MatchFinder_Skip(CMatchFinder
*p
, UInt32 num
)
1077 curMatch
= p
->hash
[hv
];
1078 p
->hash
[hv
] = p
->pos
;
1079 p
->son
[p
->cyclicBufferPos
] = curMatch
;
1085 void MatchFinder_CreateVTable(CMatchFinder
*p
, IMatchFinder
*vTable
)
1087 vTable
->Init
= (Mf_Init_Func
)MatchFinder_Init
;
1088 vTable
->GetNumAvailableBytes
= (Mf_GetNumAvailableBytes_Func
)MatchFinder_GetNumAvailableBytes
;
1089 vTable
->GetPointerToCurrentPos
= (Mf_GetPointerToCurrentPos_Func
)MatchFinder_GetPointerToCurrentPos
;
1092 /* if (p->numHashBytes <= 4) */
1094 vTable
->GetMatches
= (Mf_GetMatches_Func
)Hc4_MatchFinder_GetMatches
;
1095 vTable
->Skip
= (Mf_Skip_Func
)Hc4_MatchFinder_Skip
;
1100 vTable->GetMatches = (Mf_GetMatches_Func)Hc5_MatchFinder_GetMatches;
1101 vTable->Skip = (Mf_Skip_Func)Hc5_MatchFinder_Skip;
1105 else if (p
->numHashBytes
== 2)
1107 vTable
->GetMatches
= (Mf_GetMatches_Func
)Bt2_MatchFinder_GetMatches
;
1108 vTable
->Skip
= (Mf_Skip_Func
)Bt2_MatchFinder_Skip
;
1110 else if (p
->numHashBytes
== 3)
1112 vTable
->GetMatches
= (Mf_GetMatches_Func
)Bt3_MatchFinder_GetMatches
;
1113 vTable
->Skip
= (Mf_Skip_Func
)Bt3_MatchFinder_Skip
;
1115 else /* if (p->numHashBytes == 4) */
1117 vTable
->GetMatches
= (Mf_GetMatches_Func
)Bt4_MatchFinder_GetMatches
;
1118 vTable
->Skip
= (Mf_Skip_Func
)Bt4_MatchFinder_Skip
;
1123 vTable->GetMatches = (Mf_GetMatches_Func)Bt5_MatchFinder_GetMatches;
1124 vTable->Skip = (Mf_Skip_Func)Bt5_MatchFinder_Skip;