13#define kEmptyHashValue 0
14#define kMaxValForNormalize ((UInt32)0xFFFFFFFF)
15#define kNormalizeStepMin (1 << 10)
16#define kNormalizeMask (~(UInt32)(kNormalizeStepMin - 1))
17#define kMaxHistorySize ((UInt32)7 << 29)
27 if (!p->directInput) {
28 ISzAlloc_Free (alloc, p->bufferBase);
38 UInt32 keepSizeReserv,
42 UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv;
45 p->blockSize = blockSize;
49 if (!p->bufferBase || (p->blockSize != blockSize)) {
50 LzInWindow_Free (p, alloc);
51 p->blockSize = blockSize;
52 p->bufferBase = (Byte *)ISzAlloc_Alloc (alloc, (
size_t)blockSize);
55 return (p->bufferBase !=
NULL);
59MatchFinder_GetPointerToCurrentPos (
67MatchFinder_GetNumAvailableBytes (
71 return p->streamPos - p->pos;
75MatchFinder_ReduceOffsets (
80 p->posLimit -= subValue;
82 p->streamPos -= subValue;
86MatchFinder_ReadBlock (
90 if (p->streamEndWasReached || (p->result != SZ_OK)) {
97 UInt32 curSize = 0xFFFFFFFF - (p->streamPos - p->pos);
98 if (curSize > p->directInputRem) {
99 curSize = (UInt32)p->directInputRem;
102 p->directInputRem -= curSize;
103 p->streamPos += curSize;
104 if (p->directInputRem == 0) {
105 p->streamEndWasReached = 1;
112 Byte *dest = p->buffer + (p->streamPos - p->pos);
113 size_t size = (p->bufferBase + p->blockSize - dest);
118 p->result = ISeqInStream_Read (p->stream, dest, &size);
119 if (p->result != SZ_OK) {
124 p->streamEndWasReached = 1;
128 p->streamPos += (UInt32)size;
129 if (p->streamPos - p->pos > p->keepSizeAfter) {
136MatchFinder_MoveBlock (
142 p->buffer - p->keepSizeBefore,
143 (
size_t)(p->streamPos - p->pos) + p->keepSizeBefore
145 p->buffer = p->bufferBase + p->keepSizeBefore;
149MatchFinder_NeedMove (
153 if (p->directInput) {
158 return ((
size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter);
162MatchFinder_ReadIfRequired (
166 if (p->streamEndWasReached) {
170 if (p->keepSizeAfter >= p->streamPos - p->pos) {
171 MatchFinder_ReadBlock (p);
176MatchFinder_CheckAndMoveAndRead (
180 if (MatchFinder_NeedMove (p)) {
181 MatchFinder_MoveBlock (p);
184 MatchFinder_ReadBlock (p);
188MatchFinder_SetDefaultSettings (
198#define kCrcPoly 0xEDB88320
201MatchFinder_Construct (
207 p->bufferBase =
NULL;
210 p->expectedDataSize = (UInt64)(Int64)-1;
211 MatchFinder_SetDefaultSettings (p);
213 for (i = 0; i < 256; i++) {
214 UInt32 r = (UInt32)i;
216 for (j = 0; j < 8; j++) {
217 r = (r >> 1) ^ (kCrcPoly & ((UInt32)0 - (r & 1)));
225MatchFinder_FreeThisClassMemory (
230 ISzAlloc_Free (alloc, p->hash);
240 MatchFinder_FreeThisClassMemory (p, alloc);
241 LzInWindow_Free (p, alloc);
250 size_t sizeInBytes = (size_t)num *
sizeof (CLzRef);
252 if (sizeInBytes /
sizeof (CLzRef) != num) {
256 return (CLzRef *)ISzAlloc_Alloc (alloc, sizeInBytes);
263 UInt32 keepAddBufferBefore,
265 UInt32 keepAddBufferAfter,
271 if (historySize > kMaxHistorySize) {
272 MatchFinder_Free (p, alloc);
276 sizeReserv = historySize >> 1;
277 if (historySize >= ((UInt32)3 << 30)) {
278 sizeReserv = historySize >> 3;
279 }
else if (historySize >= ((UInt32)2 << 30)) {
280 sizeReserv = historySize >> 2;
283 sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19);
285 p->keepSizeBefore = historySize + keepAddBufferBefore + 1;
286 p->keepSizeAfter = matchMaxLen + keepAddBufferAfter;
290 if (LzInWindow_Create (p, sizeReserv, alloc)) {
291 UInt32 newCyclicBufferSize = historySize + 1;
293 p->matchMaxLen = matchMaxLen;
295 p->fixedHashSize = 0;
296 if (p->numHashBytes == 2) {
300 if (hs > p->expectedDataSize) {
301 hs = (UInt32)p->expectedDataSize;
314 if (hs > (1 << 24)) {
315 if (p->numHashBytes == 3) {
327 if (p->numHashBytes > 2) {
328 p->fixedHashSize += kHash2Size;
331 if (p->numHashBytes > 3) {
332 p->fixedHashSize += kHash3Size;
335 if (p->numHashBytes > 4) {
336 p->fixedHashSize += kHash4Size;
339 hs += p->fixedHashSize;
345 p->historySize = historySize;
347 p->cyclicBufferSize = newCyclicBufferSize;
349 numSons = newCyclicBufferSize;
354 newSize = hs + numSons;
356 if (p->hash && (p->numRefs == newSize)) {
360 MatchFinder_FreeThisClassMemory (p, alloc);
361 p->numRefs = newSize;
362 p->hash = AllocRefs (newSize, alloc);
365 p->son = p->hash + p->hashSizeSum;
371 MatchFinder_Free (p, alloc);
376MatchFinder_SetLimits (
380 UInt32 limit = kMaxValForNormalize - p->pos;
381 UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos;
383 if (limit2 < limit) {
387 limit2 = p->streamPos - p->pos;
389 if (limit2 <= p->keepSizeAfter) {
394 limit2 -= p->keepSizeAfter;
397 if (limit2 < limit) {
402 UInt32 lenLimit = p->streamPos - p->pos;
403 if (lenLimit > p->matchMaxLen) {
404 lenLimit = p->matchMaxLen;
407 p->lenLimit = lenLimit;
409 p->posLimit = p->pos + limit;
413MatchFinder_Init_LowHash (
418 CLzRef *items = p->hash;
419 size_t numItems = p->fixedHashSize;
421 for (i = 0; i < numItems; i++) {
422 items[i] = kEmptyHashValue;
427MatchFinder_Init_HighHash (
432 CLzRef *items = p->hash + p->fixedHashSize;
433 size_t numItems = (size_t)p->hashMask + 1;
435 for (i = 0; i < numItems; i++) {
436 items[i] = kEmptyHashValue;
446 p->cyclicBufferPos = 0;
447 p->buffer = p->bufferBase;
449 p->streamPos = p->cyclicBufferSize;
451 p->streamEndWasReached = 0;
454 MatchFinder_ReadBlock (p);
457 MatchFinder_SetLimits (p);
465 MatchFinder_Init_HighHash (p);
466 MatchFinder_Init_LowHash (p);
467 MatchFinder_Init_3 (p, True);
471MatchFinder_GetSubValue (
475 return (p->pos - p->historySize - 1) & kNormalizeMask;
479MatchFinder_Normalize3 (
487 for (i = 0; i < numItems; i++) {
488 UInt32 value = items[i];
489 if (value <= subValue) {
490 value = kEmptyHashValue;
500MatchFinder_Normalize (
504 UInt32 subValue = MatchFinder_GetSubValue (p);
506 MatchFinder_Normalize3 (subValue, p->hash, p->numRefs);
507 MatchFinder_ReduceOffsets (p, subValue);
512MatchFinder_CheckLimits (
516 if (p->pos == kMaxValForNormalize) {
517 MatchFinder_Normalize (p);
520 if (!p->streamEndWasReached && (p->keepSizeAfter == p->streamPos - p->pos)) {
521 MatchFinder_CheckAndMoveAndRead (p);
524 if (p->cyclicBufferPos == p->cyclicBufferSize) {
525 p->cyclicBufferPos = 0;
528 MatchFinder_SetLimits (p);
542 UInt32 _cyclicBufferPos,
543 UInt32 _cyclicBufferSize,
578 const Byte *lim = cur + lenLimit;
580 son[_cyclicBufferPos] = curMatch;
582 UInt32 delta = pos - curMatch;
583 if (delta >= _cyclicBufferSize) {
589 curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];
590 diff = (ptrdiff_t)0 - delta;
591 if (cur[maxLen] == cur[maxLen + diff]) {
593 while (*c == c[diff]) {
595 distances[0] = (UInt32)(lim - cur);
596 distances[1] = delta - 1;
597 return distances + 2;
602 unsigned len = (unsigned)(c - cur);
605 distances[0] = (UInt32)len;
606 distances[1] = delta - 1;
612 }
while (--cutValue);
625 UInt32 _cyclicBufferPos,
626 UInt32 _cyclicBufferSize,
632 CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1;
633 CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1);
634 unsigned len0 = 0, len1 = 0;
637 UInt32 delta = pos - curMatch;
638 if ((cutValue-- == 0) || (delta >= _cyclicBufferSize)) {
639 *ptr0 = *ptr1 = kEmptyHashValue;
644 CLzRef *pair = son + ((size_t)(_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
645 const Byte *pb = cur - delta;
646 unsigned len = (len0 < len1 ? len0 : len1);
647 UInt32 pair0 = pair[0];
648 if (pb[len] == cur[len]) {
649 if ((++len != lenLimit) && (pb[len] == cur[len])) {
650 while (++len != lenLimit) {
651 if (pb[len] != cur[len]) {
658 maxLen = (UInt32)len;
659 *distances++ = (UInt32)len;
660 *distances++ = delta - 1;
661 if (len == lenLimit) {
669 if (pb[len] < cur[len]) {
691 UInt32 _cyclicBufferPos,
692 UInt32 _cyclicBufferSize,
696 CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1;
697 CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1);
698 unsigned len0 = 0, len1 = 0;
701 UInt32 delta = pos - curMatch;
702 if ((cutValue-- == 0) || (delta >= _cyclicBufferSize)) {
703 *ptr0 = *ptr1 = kEmptyHashValue;
708 CLzRef *pair = son + ((size_t)(_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
709 const Byte *pb = cur - delta;
710 unsigned len = (len0 < len1 ? len0 : len1);
711 if (pb[len] == cur[len]) {
712 while (++len != lenLimit) {
713 if (pb[len] != cur[len]) {
719 if (len == lenLimit) {
727 if (pb[len] < cur[len]) {
743 ++p->cyclicBufferPos; \
745 if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p);
747#define MOVE_POS_RET MOVE_POS return (UInt32)offset;
757#define GET_MATCHES_HEADER2(minLen, ret_op) \
758 unsigned lenLimit; UInt32 hv; const Byte *cur; UInt32 curMatch; \
759 lenLimit = (unsigned)p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \
762#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0)
763#define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue)
765#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue
767#define GET_MATCHES_FOOTER(offset, maxLen) \
768 offset = (unsigned)(GetMatchesSpec1((UInt32)lenLimit, curMatch, MF_PARAMS(p), \
769 distances + offset, (UInt32)maxLen) - distances); MOVE_POS_RET;
772 SkipMatchesSpec((UInt32)lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;
774#define UPDATE_maxLen {\
775 ptrdiff_t diff = (ptrdiff_t)0 - d2; \
776 const Byte *c = cur + maxLen; \
777 const Byte *lim = cur + lenLimit; \
778 for (; c != lim; c++) if (*(c + diff) != *c) break; \
779 maxLen = (unsigned)(c - cur); }
782Bt2_MatchFinder_GetMatches (
789 GET_MATCHES_HEADER (2)
791 curMatch = p->hash[hv];
792 p->hash[hv] = p->pos;
794 GET_MATCHES_FOOTER (offset, 1)
798Bt3Zip_MatchFinder_GetMatches (
805 GET_MATCHES_HEADER (3)
807 curMatch = p->hash[hv];
808 p->hash[hv] = p->pos;
810 GET_MATCHES_FOOTER (offset, 2)
814Bt3_MatchFinder_GetMatches (
820 unsigned maxLen, offset;
823 GET_MATCHES_HEADER (3)
832 curMatch = (hash + kFix3HashSize)[hv];
835 (hash + kFix3HashSize)[hv] = pos;
840 if ((d2 < p->cyclicBufferSize) && (*(cur - d2) == *cur)) {
842 distances[0] = (UInt32)maxLen;
843 distances[1] = d2 - 1;
845 if (maxLen == lenLimit) {
846 SkipMatchesSpec ((UInt32)lenLimit, curMatch, MF_PARAMS (p));
851 GET_MATCHES_FOOTER (offset, maxLen)
855Bt4_MatchFinder_GetMatches (
860 UInt32 h2, h3, d2, d3, pos;
861 unsigned maxLen, offset;
864 GET_MATCHES_HEADER (4)
872 d3 = pos - (hash + kFix3HashSize)[h3];
874 curMatch = (hash + kFix4HashSize)[hv];
877 (hash + kFix3HashSize)[h3] = pos;
878 (hash + kFix4HashSize)[hv] = pos;
883 if ((d2 < p->cyclicBufferSize) && (*(cur - d2) == *cur)) {
886 distances[1] = d2 - 1;
890 if ((d2 != d3) && (d3 < p->cyclicBufferSize) && (*(cur - d3) == *cur)) {
892 distances[(size_t)offset + 1] = d3 - 1;
899 distances[(size_t)offset - 2] = (UInt32)maxLen;
900 if (maxLen == lenLimit) {
901 SkipMatchesSpec ((UInt32)lenLimit, curMatch, MF_PARAMS (p));
910 GET_MATCHES_FOOTER (offset, maxLen)
990Hc4_MatchFinder_GetMatches (
995 UInt32 h2, h3, d2, d3, pos;
996 unsigned maxLen, offset;
999 GET_MATCHES_HEADER (4)
1006 d2 = pos - hash[h2];
1007 d3 = pos - (hash + kFix3HashSize)[h3];
1009 curMatch = (hash + kFix4HashSize)[hv];
1012 (hash + kFix3HashSize)[h3] = pos;
1013 (hash + kFix4HashSize)[hv] = pos;
1018 if ((d2 < p->cyclicBufferSize) && (*(cur - d2) == *cur)) {
1021 distances[1] = d2 - 1;
1025 if ((d2 != d3) && (d3 < p->cyclicBufferSize) && (*(cur - d3) == *cur)) {
1027 distances[(size_t)offset + 1] = d3 - 1;
1034 distances[(size_t)offset - 2] = (UInt32)maxLen;
1035 if (maxLen == lenLimit) {
1036 p->son[p->cyclicBufferPos] = curMatch;
1045 offset = (unsigned)(Hc_GetMatchesSpec (
1134Hc3Zip_MatchFinder_GetMatches (
1141 GET_MATCHES_HEADER (3)
1143 curMatch = p->hash[hv];
1144 p->hash[hv] = p->pos;
1145 offset = (
unsigned)(Hc_GetMatchesSpec (
1156Bt2_MatchFinder_Skip (
1164 curMatch = p->hash[hv];
1165 p->hash[hv] = p->pos;
1167 } while (--num != 0);
1171Bt3Zip_MatchFinder_Skip (
1179 curMatch = p->hash[hv];
1180 p->hash[hv] = p->pos;
1182 } while (--num != 0);
1186Bt3_MatchFinder_Skip (
1197 curMatch = (hash + kFix3HashSize)[hv];
1199 (hash + kFix3HashSize)[hv] = p->pos;
1201 } while (--num != 0);
1205Bt4_MatchFinder_Skip (
1216 curMatch = (hash + kFix4HashSize)[hv];
1218 (hash + kFix3HashSize)[h3] =
1219 (hash + kFix4HashSize)[hv] = p->pos;
1221 } while (--num != 0);
1245Hc4_MatchFinder_Skip (
1256 curMatch = (hash + kFix4HashSize)[hv];
1258 (hash + kFix3HashSize)[h3] =
1259 (hash + kFix4HashSize)[hv] = p->pos;
1260 p->son[p->cyclicBufferPos] = curMatch;
1262 } while (--num != 0);
1287Hc3Zip_MatchFinder_Skip (
1295 curMatch = p->hash[hv];
1296 p->hash[hv] = p->pos;
1297 p->son[p->cyclicBufferPos] = curMatch;
1299 } while (--num != 0);
1303MatchFinder_CreateVTable (
1308 vTable->Init = (Mf_Init_Func)MatchFinder_Init;
1309 vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes;
1310 vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos;
1314 vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches;
1315 vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip;
1325 }
else if (p->numHashBytes == 2) {
1326 vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches;
1327 vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip;
1328 }
else if (p->numHashBytes == 3) {
1329 vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches;
1330 vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip;
1333 vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches;
1334 vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip;