123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128 |
- /* LzFind.c -- Match finder for LZ algorithms
- 2018-07-08 : Igor Pavlov : Public domain */
- #include "Precomp.h"
- #include <string.h>
- #include "LzFind.h"
- #include "LzHash.h"
- #define kEmptyHashValue 0
- #define kMaxValForNormalize ((UInt32)0xFFFFFFFF)
- #define kNormalizeStepMin (1 << 10) /* it must be power of 2 */
- #define kNormalizeMask (~(UInt32)(kNormalizeStepMin - 1))
- #define kMaxHistorySize ((UInt32)7 << 29)
- #define kStartMaxLen 3
- static void LzInWindow_Free(CMatchFinder *p, ISzAllocPtr alloc)
- {
- if (!p->directInput)
- {
- ISzAlloc_Free(alloc, p->bufferBase);
- p->bufferBase = NULL;
- }
- }
- /* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */
- static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAllocPtr alloc)
- {
- UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv;
- if (p->directInput)
- {
- p->blockSize = blockSize;
- return 1;
- }
- if (!p->bufferBase || p->blockSize != blockSize)
- {
- LzInWindow_Free(p, alloc);
- p->blockSize = blockSize;
- p->bufferBase = (Byte *) ISzAlloc_Alloc(alloc, (size_t) blockSize);
- }
- return (p->bufferBase != NULL);
- }
- Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p)
- {
- return p->buffer;
- }
- UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p)
- {
- return p->streamPos - p->pos;
- }
- void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue)
- {
- p->posLimit -= subValue;
- p->pos -= subValue;
- p->streamPos -= subValue;
- }
- static void MatchFinder_ReadBlock(CMatchFinder *p)
- {
- if (p->streamEndWasReached || p->result != SZ_OK)
- return;
- /* We use (p->streamPos - p->pos) value. (p->streamPos < p->pos) is allowed. */
- if (p->directInput)
- {
- UInt32 curSize = 0xFFFFFFFF - (p->streamPos - p->pos);
- if (curSize > p->directInputRem)
- curSize = (UInt32) p->directInputRem;
- p->directInputRem -= curSize;
- p->streamPos += curSize;
- if (p->directInputRem == 0)
- p->streamEndWasReached = 1;
- return;
- }
- for (;;)
- {
- Byte *dest = p->buffer + (p->streamPos - p->pos);
- size_t size = (p->bufferBase + p->blockSize - dest);
- if (size == 0)
- return;
- p->result = ISeqInStream_Read(p->stream, dest, &size);
- if (p->result != SZ_OK)
- return;
- if (size == 0)
- {
- p->streamEndWasReached = 1;
- return;
- }
- p->streamPos += (UInt32) size;
- if (p->streamPos - p->pos > p->keepSizeAfter)
- return;
- }
- }
- void MatchFinder_MoveBlock(CMatchFinder *p)
- {
- memmove(p->bufferBase,
- p->buffer - p->keepSizeBefore,
- (size_t) (p->streamPos - p->pos) + p->keepSizeBefore);
- p->buffer = p->bufferBase + p->keepSizeBefore;
- }
- int MatchFinder_NeedMove(CMatchFinder *p)
- {
- if (p->directInput)
- return 0;
- /* if (p->streamEndWasReached) return 0; */
- return ((size_t) (p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter);
- }
- void MatchFinder_ReadIfRequired(CMatchFinder *p)
- {
- if (p->streamEndWasReached)
- return;
- if (p->keepSizeAfter >= p->streamPos - p->pos)
- MatchFinder_ReadBlock(p);
- }
- static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p)
- {
- if (MatchFinder_NeedMove(p))
- MatchFinder_MoveBlock(p);
- MatchFinder_ReadBlock(p);
- }
- static void MatchFinder_SetDefaultSettings(CMatchFinder *p)
- {
- p->cutValue = 32;
- p->btMode = 1;
- p->numHashBytes = 4;
- p->bigHash = 0;
- }
- #define kCrcPoly 0xEDB88320
- void MatchFinder_Construct(CMatchFinder *p)
- {
- unsigned i;
- p->bufferBase = NULL;
- p->directInput = 0;
- p->hash = NULL;
- p->expectedDataSize = (UInt64) (Int64) - 1;
- MatchFinder_SetDefaultSettings(p);
- for (i = 0; i < 256; i++)
- {
- UInt32 r = (UInt32) i;
- unsigned j;
- for (j = 0; j < 8; j++)
- r = (r >> 1) ^ (kCrcPoly & ((UInt32) 0 - (r & 1)));
- p->crc[i] = r;
- }
- }
- static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAllocPtr alloc)
- {
- ISzAlloc_Free(alloc, p->hash);
- p->hash = NULL;
- }
- void MatchFinder_Free(CMatchFinder *p, ISzAllocPtr alloc)
- {
- MatchFinder_FreeThisClassMemory(p, alloc);
- LzInWindow_Free(p, alloc);
- }
- static CLzRef* AllocRefs(size_t num, ISzAllocPtr alloc)
- {
- size_t sizeInBytes = (size_t) num * sizeof (CLzRef);
- if (sizeInBytes / sizeof (CLzRef) != num)
- return NULL;
- return (CLzRef *) ISzAlloc_Alloc(alloc, sizeInBytes);
- }
- int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
- UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
- ISzAllocPtr alloc)
- {
- UInt32 sizeReserv;
- if (historySize > kMaxHistorySize)
- {
- MatchFinder_Free(p, alloc);
- return 0;
- }
- sizeReserv = historySize >> 1;
- if (historySize >= ((UInt32) 3 << 30)) sizeReserv = historySize >> 3;
- else if (historySize >= ((UInt32) 2 << 30)) sizeReserv = historySize >> 2;
- sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19);
- p->keepSizeBefore = historySize + keepAddBufferBefore + 1;
- p->keepSizeAfter = matchMaxLen + keepAddBufferAfter;
- /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */
- if (LzInWindow_Create(p, sizeReserv, alloc))
- {
- UInt32 newCyclicBufferSize = historySize + 1;
- UInt32 hs;
- p->matchMaxLen = matchMaxLen;
- {
- p->fixedHashSize = 0;
- if (p->numHashBytes == 2)
- hs = (1 << 16) - 1;
- else
- {
- hs = historySize;
- if (hs > p->expectedDataSize)
- hs = (UInt32) p->expectedDataSize;
- if (hs != 0)
- hs--;
- hs |= (hs >> 1);
- hs |= (hs >> 2);
- hs |= (hs >> 4);
- hs |= (hs >> 8);
- hs >>= 1;
- hs |= 0xFFFF; /* don't change it! It's required for Deflate */
- if (hs > (1 << 24))
- {
- if (p->numHashBytes == 3)
- hs = (1 << 24) - 1;
- else
- hs >>= 1;
- /* if (bigHash) mode, GetHeads4b() in LzFindMt.c needs (hs >= ((1 << 24) - 1))) */
- }
- }
- p->hashMask = hs;
- hs++;
- if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size;
- if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size;
- if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size;
- hs += p->fixedHashSize;
- }
- {
- size_t newSize;
- size_t numSons;
- p->historySize = historySize;
- p->hashSizeSum = hs;
- p->cyclicBufferSize = newCyclicBufferSize;
- numSons = newCyclicBufferSize;
- if (p->btMode)
- numSons <<= 1;
- newSize = hs + numSons;
- if (p->hash && p->numRefs == newSize)
- return 1;
- MatchFinder_FreeThisClassMemory(p, alloc);
- p->numRefs = newSize;
- p->hash = AllocRefs(newSize, alloc);
- if (p->hash)
- {
- p->son = p->hash + p->hashSizeSum;
- return 1;
- }
- }
- }
- MatchFinder_Free(p, alloc);
- return 0;
- }
- static void MatchFinder_SetLimits(CMatchFinder *p)
- {
- UInt32 limit = kMaxValForNormalize - p->pos;
- UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos;
- if (limit2 < limit)
- limit = limit2;
- limit2 = p->streamPos - p->pos;
- if (limit2 <= p->keepSizeAfter)
- {
- if (limit2 > 0)
- limit2 = 1;
- }
- else
- limit2 -= p->keepSizeAfter;
- if (limit2 < limit)
- limit = limit2;
- {
- UInt32 lenLimit = p->streamPos - p->pos;
- if (lenLimit > p->matchMaxLen)
- lenLimit = p->matchMaxLen;
- p->lenLimit = lenLimit;
- }
- p->posLimit = p->pos + limit;
- }
- void MatchFinder_Init_LowHash(CMatchFinder *p)
- {
- size_t i;
- CLzRef *items = p->hash;
- size_t numItems = p->fixedHashSize;
- for (i = 0; i < numItems; i++)
- items[i] = kEmptyHashValue;
- }
- void MatchFinder_Init_HighHash(CMatchFinder *p)
- {
- size_t i;
- CLzRef *items = p->hash + p->fixedHashSize;
- size_t numItems = (size_t) p->hashMask + 1;
- for (i = 0; i < numItems; i++)
- items[i] = kEmptyHashValue;
- }
- void MatchFinder_Init_3(CMatchFinder *p, int readData)
- {
- p->cyclicBufferPos = 0;
- p->buffer = p->bufferBase;
- p->pos =
- p->streamPos = p->cyclicBufferSize;
- p->result = SZ_OK;
- p->streamEndWasReached = 0;
- if (readData)
- MatchFinder_ReadBlock(p);
- MatchFinder_SetLimits(p);
- }
- void MatchFinder_Init(CMatchFinder *p)
- {
- MatchFinder_Init_HighHash(p);
- MatchFinder_Init_LowHash(p);
- MatchFinder_Init_3(p, True);
- }
- static UInt32 MatchFinder_GetSubValue(CMatchFinder *p)
- {
- return (p->pos - p->historySize - 1) & kNormalizeMask;
- }
- void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems)
- {
- size_t i;
- for (i = 0; i < numItems; i++)
- {
- UInt32 value = items[i];
- if (value <= subValue)
- value = kEmptyHashValue;
- else
- value -= subValue;
- items[i] = value;
- }
- }
- static void MatchFinder_Normalize(CMatchFinder *p)
- {
- UInt32 subValue = MatchFinder_GetSubValue(p);
- MatchFinder_Normalize3(subValue, p->hash, p->numRefs);
- MatchFinder_ReduceOffsets(p, subValue);
- }
- MY_NO_INLINE
- static void MatchFinder_CheckLimits(CMatchFinder *p)
- {
- if (p->pos == kMaxValForNormalize)
- MatchFinder_Normalize(p);
- if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos)
- MatchFinder_CheckAndMoveAndRead(p);
- if (p->cyclicBufferPos == p->cyclicBufferSize)
- p->cyclicBufferPos = 0;
- MatchFinder_SetLimits(p);
- }
- /*
- (lenLimit > maxLen)
- */
- MY_FORCE_INLINE
- static UInt32 * Hc_GetMatchesSpec(unsigned lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
- UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
- UInt32 *distances, unsigned maxLen)
- {
- /*
- son[_cyclicBufferPos] = curMatch;
- for (;;)
- {
- UInt32 delta = pos - curMatch;
- if (cutValue-- == 0 || delta >= _cyclicBufferSize)
- return distances;
- {
- const Byte *pb = cur - delta;
- curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];
- if (pb[maxLen] == cur[maxLen] && *pb == *cur)
- {
- UInt32 len = 0;
- while (++len != lenLimit)
- if (pb[len] != cur[len])
- break;
- if (maxLen < len)
- {
- maxLen = len;
- *distances++ = len;
- *distances++ = delta - 1;
- if (len == lenLimit)
- return distances;
- }
- }
- }
- }
- */
- const Byte *lim = cur + lenLimit;
- son[_cyclicBufferPos] = curMatch;
- do
- {
- UInt32 delta = pos - curMatch;
- if (delta >= _cyclicBufferSize)
- break;
- {
- ptrdiff_t diff;
- curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];
- diff = (ptrdiff_t) 0 - delta;
- if (cur[maxLen] == cur[maxLen + diff])
- {
- const Byte *c = cur;
- while (*c == c[diff])
- {
- if (++c == lim)
- {
- distances[0] = (UInt32) (lim - cur);
- distances[1] = delta - 1;
- return distances + 2;
- }
- }
- {
- unsigned len = (unsigned) (c - cur);
- if (maxLen < len)
- {
- maxLen = len;
- distances[0] = (UInt32) len;
- distances[1] = delta - 1;
- distances += 2;
- }
- }
- }
- }
- }
- while (--cutValue);
- return distances;
- }
- MY_FORCE_INLINE
- UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
- UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
- UInt32 *distances, UInt32 maxLen)
- {
- CLzRef *ptr0 = son + ((size_t) _cyclicBufferPos << 1) + 1;
- CLzRef *ptr1 = son + ((size_t) _cyclicBufferPos << 1);
- unsigned len0 = 0, len1 = 0;
- for (;;)
- {
- UInt32 delta = pos - curMatch;
- if (cutValue-- == 0 || delta >= _cyclicBufferSize)
- {
- *ptr0 = *ptr1 = kEmptyHashValue;
- return distances;
- }
- {
- CLzRef *pair = son + ((size_t) (_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
- const Byte *pb = cur - delta;
- unsigned len = (len0 < len1 ? len0 : len1);
- UInt32 pair0 = pair[0];
- if (pb[len] == cur[len])
- {
- if (++len != lenLimit && pb[len] == cur[len])
- while (++len != lenLimit)
- if (pb[len] != cur[len])
- break;
- if (maxLen < len)
- {
- maxLen = (UInt32) len;
- *distances++ = (UInt32) len;
- *distances++ = delta - 1;
- if (len == lenLimit)
- {
- *ptr1 = pair0;
- *ptr0 = pair[1];
- return distances;
- }
- }
- }
- if (pb[len] < cur[len])
- {
- *ptr1 = curMatch;
- ptr1 = pair + 1;
- curMatch = *ptr1;
- len1 = len;
- }
- else
- {
- *ptr0 = curMatch;
- ptr0 = pair;
- curMatch = *ptr0;
- len0 = len;
- }
- }
- }
- }
- static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
- UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue)
- {
- CLzRef *ptr0 = son + ((size_t) _cyclicBufferPos << 1) + 1;
- CLzRef *ptr1 = son + ((size_t) _cyclicBufferPos << 1);
- unsigned len0 = 0, len1 = 0;
- for (;;)
- {
- UInt32 delta = pos - curMatch;
- if (cutValue-- == 0 || delta >= _cyclicBufferSize)
- {
- *ptr0 = *ptr1 = kEmptyHashValue;
- return;
- }
- {
- CLzRef *pair = son + ((size_t) (_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
- const Byte *pb = cur - delta;
- unsigned len = (len0 < len1 ? len0 : len1);
- if (pb[len] == cur[len])
- {
- while (++len != lenLimit)
- if (pb[len] != cur[len])
- break;
- {
- if (len == lenLimit)
- {
- *ptr1 = pair[0];
- *ptr0 = pair[1];
- return;
- }
- }
- }
- if (pb[len] < cur[len])
- {
- *ptr1 = curMatch;
- ptr1 = pair + 1;
- curMatch = *ptr1;
- len1 = len;
- }
- else
- {
- *ptr0 = curMatch;
- ptr0 = pair;
- curMatch = *ptr0;
- len0 = len;
- }
- }
- }
- }
- #define MOVE_POS \
- ++p->cyclicBufferPos; \
- p->buffer++; \
- if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p);
- #define MOVE_POS_RET MOVE_POS return (UInt32)offset;
- static void MatchFinder_MovePos(CMatchFinder *p)
- {
- MOVE_POS;
- }
- #define GET_MATCHES_HEADER2(minLen, ret_op) \
- unsigned lenLimit; UInt32 hv; const Byte *cur; UInt32 curMatch; \
- lenLimit = (unsigned)p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \
- cur = p->buffer;
- #define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0)
- #define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue)
- #define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue
- #define GET_MATCHES_FOOTER(offset, maxLen) \
- offset = (unsigned)(GetMatchesSpec1((UInt32)lenLimit, curMatch, MF_PARAMS(p), \
- distances + offset, (UInt32)maxLen) - distances); MOVE_POS_RET;
- #define SKIP_FOOTER \
- SkipMatchesSpec((UInt32)lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;
- #define UPDATE_maxLen { \
- ptrdiff_t diff = (ptrdiff_t)0 - d2; \
- const Byte *c = cur + maxLen; \
- const Byte *lim = cur + lenLimit; \
- for (; c != lim; c++) if (*(c + diff) != *c) break; \
- maxLen = (unsigned)(c - cur); }
- static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
- {
- unsigned offset;
- GET_MATCHES_HEADER(2)
- HASH2_CALC;
- curMatch = p->hash[hv];
- p->hash[hv] = p->pos;
- offset = 0;
- GET_MATCHES_FOOTER(offset, 1)
- }
- UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
- {
- unsigned offset;
- GET_MATCHES_HEADER(3)
- HASH_ZIP_CALC;
- curMatch = p->hash[hv];
- p->hash[hv] = p->pos;
- offset = 0;
- GET_MATCHES_FOOTER(offset, 2)
- }
- static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
- {
- UInt32 h2, d2, pos;
- unsigned maxLen, offset;
- UInt32 *hash;
- GET_MATCHES_HEADER(3)
- HASH3_CALC;
- hash = p->hash;
- pos = p->pos;
- d2 = pos - hash[h2];
- curMatch = (hash + kFix3HashSize)[hv];
- hash[h2] = pos;
- (hash + kFix3HashSize)[hv] = pos;
- maxLen = 2;
- offset = 0;
- if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
- {
- UPDATE_maxLen
- distances[0] = (UInt32) maxLen;
- distances[1] = d2 - 1;
- offset = 2;
- if (maxLen == lenLimit)
- {
- SkipMatchesSpec((UInt32) lenLimit, curMatch, MF_PARAMS(p));
- MOVE_POS_RET;
- }
- }
- GET_MATCHES_FOOTER(offset, maxLen)
- }
- static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
- {
- UInt32 h2, h3, d2, d3, pos;
- unsigned maxLen, offset;
- UInt32 *hash;
- GET_MATCHES_HEADER(4)
- HASH4_CALC;
- hash = p->hash;
- pos = p->pos;
- d2 = pos - hash [h2];
- d3 = pos - (hash + kFix3HashSize)[h3];
- curMatch = (hash + kFix4HashSize)[hv];
- hash [h2] = pos;
- (hash + kFix3HashSize)[h3] = pos;
- (hash + kFix4HashSize)[hv] = pos;
- maxLen = 0;
- offset = 0;
- if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
- {
- maxLen = 2;
- distances[0] = 2;
- distances[1] = d2 - 1;
- offset = 2;
- }
- if (d2 != d3 && d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
- {
- maxLen = 3;
- distances[(size_t) offset + 1] = d3 - 1;
- offset += 2;
- d2 = d3;
- }
- if (offset != 0)
- {
- UPDATE_maxLen
- distances[(size_t) offset - 2] = (UInt32) maxLen;
- if (maxLen == lenLimit)
- {
- SkipMatchesSpec((UInt32) lenLimit, curMatch, MF_PARAMS(p));
- MOVE_POS_RET;
- }
- }
- if (maxLen < 3)
- maxLen = 3;
- GET_MATCHES_FOOTER(offset, maxLen)
- }
- /*
- static UInt32 Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
- {
- UInt32 h2, h3, h4, d2, d3, d4, maxLen, offset, pos;
- UInt32 *hash;
- GET_MATCHES_HEADER(5)
- HASH5_CALC;
- hash = p->hash;
- pos = p->pos;
- d2 = pos - hash [h2];
- d3 = pos - (hash + kFix3HashSize)[h3];
- d4 = pos - (hash + kFix4HashSize)[h4];
- curMatch = (hash + kFix5HashSize)[hv];
- hash [h2] = pos;
- (hash + kFix3HashSize)[h3] = pos;
- (hash + kFix4HashSize)[h4] = pos;
- (hash + kFix5HashSize)[hv] = pos;
- maxLen = 0;
- offset = 0;
- if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
- {
- distances[0] = maxLen = 2;
- distances[1] = d2 - 1;
- offset = 2;
- if (*(cur - d2 + 2) == cur[2])
- distances[0] = maxLen = 3;
- else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
- {
- distances[2] = maxLen = 3;
- distances[3] = d3 - 1;
- offset = 4;
- d2 = d3;
- }
- }
- else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
- {
- distances[0] = maxLen = 3;
- distances[1] = d3 - 1;
- offset = 2;
- d2 = d3;
- }
-
- if (d2 != d4 && d4 < p->cyclicBufferSize
- && *(cur - d4) == *cur
- && *(cur - d4 + 3) == *(cur + 3))
- {
- maxLen = 4;
- distances[(size_t)offset + 1] = d4 - 1;
- offset += 2;
- d2 = d4;
- }
-
- if (offset != 0)
- {
- UPDATE_maxLen
- distances[(size_t)offset - 2] = maxLen;
- if (maxLen == lenLimit)
- {
- SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
- MOVE_POS_RET;
- }
- }
- if (maxLen < 4)
- maxLen = 4;
-
- GET_MATCHES_FOOTER(offset, maxLen)
- }
- */
- static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
- {
- UInt32 h2, h3, d2, d3, pos;
- unsigned maxLen, offset;
- UInt32 *hash;
- GET_MATCHES_HEADER(4)
- HASH4_CALC;
- hash = p->hash;
- pos = p->pos;
- d2 = pos - hash [h2];
- d3 = pos - (hash + kFix3HashSize)[h3];
- curMatch = (hash + kFix4HashSize)[hv];
- hash [h2] = pos;
- (hash + kFix3HashSize)[h3] = pos;
- (hash + kFix4HashSize)[hv] = pos;
- maxLen = 0;
- offset = 0;
- if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
- {
- maxLen = 2;
- distances[0] = 2;
- distances[1] = d2 - 1;
- offset = 2;
- }
- if (d2 != d3 && d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
- {
- maxLen = 3;
- distances[(size_t) offset + 1] = d3 - 1;
- offset += 2;
- d2 = d3;
- }
- if (offset != 0)
- {
- UPDATE_maxLen
- distances[(size_t) offset - 2] = (UInt32) maxLen;
- if (maxLen == lenLimit)
- {
- p->son[p->cyclicBufferPos] = curMatch;
- MOVE_POS_RET;
- }
- }
- if (maxLen < 3)
- maxLen = 3;
- offset = (unsigned) (Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
- distances + offset, maxLen) - (distances));
- MOVE_POS_RET
- }
- /*
- static UInt32 Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
- {
- UInt32 h2, h3, h4, d2, d3, d4, maxLen, offset, pos
- UInt32 *hash;
- GET_MATCHES_HEADER(5)
- HASH5_CALC;
- hash = p->hash;
- pos = p->pos;
-
- d2 = pos - hash [h2];
- d3 = pos - (hash + kFix3HashSize)[h3];
- d4 = pos - (hash + kFix4HashSize)[h4];
- curMatch = (hash + kFix5HashSize)[hv];
- hash [h2] = pos;
- (hash + kFix3HashSize)[h3] = pos;
- (hash + kFix4HashSize)[h4] = pos;
- (hash + kFix5HashSize)[hv] = pos;
- maxLen = 0;
- offset = 0;
- if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
- {
- distances[0] = maxLen = 2;
- distances[1] = d2 - 1;
- offset = 2;
- if (*(cur - d2 + 2) == cur[2])
- distances[0] = maxLen = 3;
- else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
- {
- distances[2] = maxLen = 3;
- distances[3] = d3 - 1;
- offset = 4;
- d2 = d3;
- }
- }
- else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
- {
- distances[0] = maxLen = 3;
- distances[1] = d3 - 1;
- offset = 2;
- d2 = d3;
- }
-
- if (d2 != d4 && d4 < p->cyclicBufferSize
- && *(cur - d4) == *cur
- && *(cur - d4 + 3) == *(cur + 3))
- {
- maxLen = 4;
- distances[(size_t)offset + 1] = d4 - 1;
- offset += 2;
- d2 = d4;
- }
-
- if (offset != 0)
- {
- UPDATE_maxLen
- distances[(size_t)offset - 2] = maxLen;
- if (maxLen == lenLimit)
- {
- p->son[p->cyclicBufferPos] = curMatch;
- MOVE_POS_RET;
- }
- }
-
- if (maxLen < 4)
- maxLen = 4;
- offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
- distances + offset, maxLen) - (distances));
- MOVE_POS_RET
- }
- */
- UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
- {
- unsigned offset;
- GET_MATCHES_HEADER(3)
- HASH_ZIP_CALC;
- curMatch = p->hash[hv];
- p->hash[hv] = p->pos;
- offset = (unsigned) (Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
- distances, 2) - (distances));
- MOVE_POS_RET
- }
- static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
- {
- do
- {
- SKIP_HEADER(2)
- HASH2_CALC;
- curMatch = p->hash[hv];
- p->hash[hv] = p->pos;
- SKIP_FOOTER
- }
- while (--num != 0);
- }
- void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
- {
- do
- {
- SKIP_HEADER(3)
- HASH_ZIP_CALC;
- curMatch = p->hash[hv];
- p->hash[hv] = p->pos;
- SKIP_FOOTER
- }
- while (--num != 0);
- }
- static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
- {
- do
- {
- UInt32 h2;
- UInt32 *hash;
- SKIP_HEADER(3)
- HASH3_CALC;
- hash = p->hash;
- curMatch = (hash + kFix3HashSize)[hv];
- hash[h2] =
- (hash + kFix3HashSize)[hv] = p->pos;
- SKIP_FOOTER
- }
- while (--num != 0);
- }
- static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
- {
- do
- {
- UInt32 h2, h3;
- UInt32 *hash;
- SKIP_HEADER(4)
- HASH4_CALC;
- hash = p->hash;
- curMatch = (hash + kFix4HashSize)[hv];
- hash [h2] =
- (hash + kFix3HashSize)[h3] =
- (hash + kFix4HashSize)[hv] = p->pos;
- SKIP_FOOTER
- }
- while (--num != 0);
- }
- /*
- static void Bt5_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
- {
- do
- {
- UInt32 h2, h3, h4;
- UInt32 *hash;
- SKIP_HEADER(5)
- HASH5_CALC;
- hash = p->hash;
- curMatch = (hash + kFix5HashSize)[hv];
- hash [h2] =
- (hash + kFix3HashSize)[h3] =
- (hash + kFix4HashSize)[h4] =
- (hash + kFix5HashSize)[hv] = p->pos;
- SKIP_FOOTER
- }
- while (--num != 0);
- }
- */
- static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
- {
- do
- {
- UInt32 h2, h3;
- UInt32 *hash;
- SKIP_HEADER(4)
- HASH4_CALC;
- hash = p->hash;
- curMatch = (hash + kFix4HashSize)[hv];
- hash [h2] =
- (hash + kFix3HashSize)[h3] =
- (hash + kFix4HashSize)[hv] = p->pos;
- p->son[p->cyclicBufferPos] = curMatch;
- MOVE_POS
- }
- while (--num != 0);
- }
- /*
- static void Hc5_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
- {
- do
- {
- UInt32 h2, h3, h4;
- UInt32 *hash;
- SKIP_HEADER(5)
- HASH5_CALC;
- hash = p->hash;
- curMatch = hash + kFix5HashSize)[hv];
- hash [h2] =
- (hash + kFix3HashSize)[h3] =
- (hash + kFix4HashSize)[h4] =
- (hash + kFix5HashSize)[hv] = p->pos;
- p->son[p->cyclicBufferPos] = curMatch;
- MOVE_POS
- }
- while (--num != 0);
- }
- */
- void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
- {
- do
- {
- SKIP_HEADER(3)
- HASH_ZIP_CALC;
- curMatch = p->hash[hv];
- p->hash[hv] = p->pos;
- p->son[p->cyclicBufferPos] = curMatch;
- MOVE_POS
- }
- while (--num != 0);
- }
- void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable)
- {
- vTable->Init = (Mf_Init_Func) MatchFinder_Init;
- vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func) MatchFinder_GetNumAvailableBytes;
- vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func) MatchFinder_GetPointerToCurrentPos;
- if (!p->btMode)
- {
- /* if (p->numHashBytes <= 4) */
- {
- vTable->GetMatches = (Mf_GetMatches_Func) Hc4_MatchFinder_GetMatches;
- vTable->Skip = (Mf_Skip_Func) Hc4_MatchFinder_Skip;
- }
- /*
- else
- {
- vTable->GetMatches = (Mf_GetMatches_Func)Hc5_MatchFinder_GetMatches;
- vTable->Skip = (Mf_Skip_Func)Hc5_MatchFinder_Skip;
- }
- */
- }
- else if (p->numHashBytes == 2)
- {
- vTable->GetMatches = (Mf_GetMatches_Func) Bt2_MatchFinder_GetMatches;
- vTable->Skip = (Mf_Skip_Func) Bt2_MatchFinder_Skip;
- }
- else if (p->numHashBytes == 3)
- {
- vTable->GetMatches = (Mf_GetMatches_Func) Bt3_MatchFinder_GetMatches;
- vTable->Skip = (Mf_Skip_Func) Bt3_MatchFinder_Skip;
- }
- else /* if (p->numHashBytes == 4) */
- {
- vTable->GetMatches = (Mf_GetMatches_Func) Bt4_MatchFinder_GetMatches;
- vTable->Skip = (Mf_Skip_Func) Bt4_MatchFinder_Skip;
- }
- /*
- else
- {
- vTable->GetMatches = (Mf_GetMatches_Func)Bt5_MatchFinder_GetMatches;
- vTable->Skip = (Mf_Skip_Func)Bt5_MatchFinder_Skip;
- }
- */
- }
|