1*b1efbcd6SAlok Aggarwal /* 2*b1efbcd6SAlok Aggarwal * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 3*b1efbcd6SAlok Aggarwal * Use is subject to license terms. 4*b1efbcd6SAlok Aggarwal */ 5*b1efbcd6SAlok Aggarwal 6*b1efbcd6SAlok Aggarwal /* LzFind.c -- Match finder for LZ algorithms 7*b1efbcd6SAlok Aggarwal 2008-10-04 : Igor Pavlov : Public domain */ 8*b1efbcd6SAlok Aggarwal 9*b1efbcd6SAlok Aggarwal #include <string.h> 10*b1efbcd6SAlok Aggarwal 11*b1efbcd6SAlok Aggarwal #include "LzFind.h" 12*b1efbcd6SAlok Aggarwal #include "LzHash.h" 13*b1efbcd6SAlok Aggarwal 14*b1efbcd6SAlok Aggarwal #define kEmptyHashValue 0 15*b1efbcd6SAlok Aggarwal #define kMaxValForNormalize ((UInt32)0xFFFFFFFF) 16*b1efbcd6SAlok Aggarwal #define kNormalizeStepMin (1 << 10) /* it must be power of 2 */ 17*b1efbcd6SAlok Aggarwal #define kNormalizeMask (~(kNormalizeStepMin - 1)) 18*b1efbcd6SAlok Aggarwal #define kMaxHistorySize ((UInt32)3 << 30) 19*b1efbcd6SAlok Aggarwal 20*b1efbcd6SAlok Aggarwal #define kStartMaxLen 3 21*b1efbcd6SAlok Aggarwal 22*b1efbcd6SAlok Aggarwal static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc) 23*b1efbcd6SAlok Aggarwal { 24*b1efbcd6SAlok Aggarwal if (!p->directInput) 25*b1efbcd6SAlok Aggarwal { 26*b1efbcd6SAlok Aggarwal alloc->Free(alloc, p->bufferBase, 0); 27*b1efbcd6SAlok Aggarwal p->bufferBase = 0; 28*b1efbcd6SAlok Aggarwal } 29*b1efbcd6SAlok Aggarwal } 30*b1efbcd6SAlok Aggarwal 31*b1efbcd6SAlok Aggarwal /* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */ 32*b1efbcd6SAlok Aggarwal 33*b1efbcd6SAlok Aggarwal static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc) 34*b1efbcd6SAlok Aggarwal { 35*b1efbcd6SAlok Aggarwal UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv; 36*b1efbcd6SAlok Aggarwal if (p->directInput) 37*b1efbcd6SAlok Aggarwal { 38*b1efbcd6SAlok Aggarwal p->blockSize = blockSize; 39*b1efbcd6SAlok Aggarwal return 1; 40*b1efbcd6SAlok Aggarwal } 41*b1efbcd6SAlok Aggarwal if (p->bufferBase == 0 || p->blockSize != blockSize) 42*b1efbcd6SAlok Aggarwal { 43*b1efbcd6SAlok Aggarwal LzInWindow_Free(p, alloc); 44*b1efbcd6SAlok Aggarwal p->blockSize = blockSize; 45*b1efbcd6SAlok Aggarwal p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize); 46*b1efbcd6SAlok Aggarwal } 47*b1efbcd6SAlok Aggarwal return (p->bufferBase != 0); 48*b1efbcd6SAlok Aggarwal } 49*b1efbcd6SAlok Aggarwal 50*b1efbcd6SAlok Aggarwal Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } 51*b1efbcd6SAlok Aggarwal Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; } 52*b1efbcd6SAlok Aggarwal 53*b1efbcd6SAlok Aggarwal UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; } 54*b1efbcd6SAlok Aggarwal 55*b1efbcd6SAlok Aggarwal void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue) 56*b1efbcd6SAlok Aggarwal { 57*b1efbcd6SAlok Aggarwal p->posLimit -= subValue; 58*b1efbcd6SAlok Aggarwal p->pos -= subValue; 59*b1efbcd6SAlok Aggarwal p->streamPos -= subValue; 60*b1efbcd6SAlok Aggarwal } 61*b1efbcd6SAlok Aggarwal 62*b1efbcd6SAlok Aggarwal static void MatchFinder_ReadBlock(CMatchFinder *p) 63*b1efbcd6SAlok Aggarwal { 64*b1efbcd6SAlok Aggarwal if (p->streamEndWasReached || p->result != SZ_OK) 65*b1efbcd6SAlok Aggarwal return; 66*b1efbcd6SAlok Aggarwal for (;;) 67*b1efbcd6SAlok Aggarwal { 68*b1efbcd6SAlok Aggarwal Byte *dest = p->buffer + (p->streamPos - p->pos); 69*b1efbcd6SAlok Aggarwal size_t size = (p->bufferBase + p->blockSize - dest); 70*b1efbcd6SAlok Aggarwal if (size == 0) 71*b1efbcd6SAlok Aggarwal return; 72*b1efbcd6SAlok Aggarwal p->result = p->stream->Read(p->stream, dest, &size); 73*b1efbcd6SAlok Aggarwal if (p->result != SZ_OK) 74*b1efbcd6SAlok Aggarwal return; 75*b1efbcd6SAlok Aggarwal if (size == 0) 76*b1efbcd6SAlok Aggarwal { 77*b1efbcd6SAlok Aggarwal p->streamEndWasReached = 1; 78*b1efbcd6SAlok Aggarwal return; 79*b1efbcd6SAlok Aggarwal } 80*b1efbcd6SAlok Aggarwal p->streamPos += (UInt32)size; 81*b1efbcd6SAlok Aggarwal if (p->streamPos - p->pos > p->keepSizeAfter) 82*b1efbcd6SAlok Aggarwal return; 83*b1efbcd6SAlok Aggarwal } 84*b1efbcd6SAlok Aggarwal } 85*b1efbcd6SAlok Aggarwal 86*b1efbcd6SAlok Aggarwal void MatchFinder_MoveBlock(CMatchFinder *p) 87*b1efbcd6SAlok Aggarwal { 88*b1efbcd6SAlok Aggarwal memmove(p->bufferBase, 89*b1efbcd6SAlok Aggarwal p->buffer - p->keepSizeBefore, 90*b1efbcd6SAlok Aggarwal (size_t)(p->streamPos - p->pos + p->keepSizeBefore)); 91*b1efbcd6SAlok Aggarwal p->buffer = p->bufferBase + p->keepSizeBefore; 92*b1efbcd6SAlok Aggarwal } 93*b1efbcd6SAlok Aggarwal 94*b1efbcd6SAlok Aggarwal int MatchFinder_NeedMove(CMatchFinder *p) 95*b1efbcd6SAlok Aggarwal { 96*b1efbcd6SAlok Aggarwal /* if (p->streamEndWasReached) return 0; */ 97*b1efbcd6SAlok Aggarwal return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter); 98*b1efbcd6SAlok Aggarwal } 99*b1efbcd6SAlok Aggarwal 100*b1efbcd6SAlok Aggarwal void MatchFinder_ReadIfRequired(CMatchFinder *p) 101*b1efbcd6SAlok Aggarwal { 102*b1efbcd6SAlok Aggarwal if (p->streamEndWasReached) 103*b1efbcd6SAlok Aggarwal return; 104*b1efbcd6SAlok Aggarwal if (p->keepSizeAfter >= p->streamPos - p->pos) 105*b1efbcd6SAlok Aggarwal MatchFinder_ReadBlock(p); 106*b1efbcd6SAlok Aggarwal } 107*b1efbcd6SAlok Aggarwal 108*b1efbcd6SAlok Aggarwal static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p) 109*b1efbcd6SAlok Aggarwal { 110*b1efbcd6SAlok Aggarwal if (MatchFinder_NeedMove(p)) 111*b1efbcd6SAlok Aggarwal MatchFinder_MoveBlock(p); 112*b1efbcd6SAlok Aggarwal MatchFinder_ReadBlock(p); 113*b1efbcd6SAlok Aggarwal } 114*b1efbcd6SAlok Aggarwal 115*b1efbcd6SAlok Aggarwal static void MatchFinder_SetDefaultSettings(CMatchFinder *p) 116*b1efbcd6SAlok Aggarwal { 117*b1efbcd6SAlok Aggarwal p->cutValue = 32; 118*b1efbcd6SAlok Aggarwal p->btMode = 1; 119*b1efbcd6SAlok Aggarwal p->numHashBytes = 4; 120*b1efbcd6SAlok Aggarwal /* p->skipModeBits = 0; */ 121*b1efbcd6SAlok Aggarwal p->directInput = 0; 122*b1efbcd6SAlok Aggarwal p->bigHash = 0; 123*b1efbcd6SAlok Aggarwal } 124*b1efbcd6SAlok Aggarwal 125*b1efbcd6SAlok Aggarwal #define kCrcPoly 0xEDB88320 126*b1efbcd6SAlok Aggarwal 127*b1efbcd6SAlok Aggarwal void MatchFinder_Construct(CMatchFinder *p) 128*b1efbcd6SAlok Aggarwal { 129*b1efbcd6SAlok Aggarwal UInt32 i; 130*b1efbcd6SAlok Aggarwal p->bufferBase = 0; 131*b1efbcd6SAlok Aggarwal p->directInput = 0; 132*b1efbcd6SAlok Aggarwal p->hash = 0; 133*b1efbcd6SAlok Aggarwal MatchFinder_SetDefaultSettings(p); 134*b1efbcd6SAlok Aggarwal 135*b1efbcd6SAlok Aggarwal for (i = 0; i < 256; i++) 136*b1efbcd6SAlok Aggarwal { 137*b1efbcd6SAlok Aggarwal UInt32 r = i; 138*b1efbcd6SAlok Aggarwal int j; 139*b1efbcd6SAlok Aggarwal for (j = 0; j < 8; j++) 140*b1efbcd6SAlok Aggarwal r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); 141*b1efbcd6SAlok Aggarwal p->crc[i] = r; 142*b1efbcd6SAlok Aggarwal } 143*b1efbcd6SAlok Aggarwal } 144*b1efbcd6SAlok Aggarwal 145*b1efbcd6SAlok Aggarwal static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc) 146*b1efbcd6SAlok Aggarwal { 147*b1efbcd6SAlok Aggarwal alloc->Free(alloc, p->hash, 0); 148*b1efbcd6SAlok Aggarwal p->hash = 0; 149*b1efbcd6SAlok Aggarwal } 150*b1efbcd6SAlok Aggarwal 151*b1efbcd6SAlok Aggarwal void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc) 152*b1efbcd6SAlok Aggarwal { 153*b1efbcd6SAlok Aggarwal MatchFinder_FreeThisClassMemory(p, alloc); 154*b1efbcd6SAlok Aggarwal LzInWindow_Free(p, alloc); 155*b1efbcd6SAlok Aggarwal } 156*b1efbcd6SAlok Aggarwal 157*b1efbcd6SAlok Aggarwal static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc) 158*b1efbcd6SAlok Aggarwal { 159*b1efbcd6SAlok Aggarwal size_t sizeInBytes = (size_t)num * sizeof(CLzRef); 160*b1efbcd6SAlok Aggarwal if (sizeInBytes / sizeof(CLzRef) != num) 161*b1efbcd6SAlok Aggarwal return 0; 162*b1efbcd6SAlok Aggarwal return (CLzRef *)alloc->Alloc(alloc, sizeInBytes); 163*b1efbcd6SAlok Aggarwal } 164*b1efbcd6SAlok Aggarwal 165*b1efbcd6SAlok Aggarwal int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, 166*b1efbcd6SAlok Aggarwal UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, 167*b1efbcd6SAlok Aggarwal ISzAlloc *alloc) 168*b1efbcd6SAlok Aggarwal { 169*b1efbcd6SAlok Aggarwal UInt32 sizeReserv; 170*b1efbcd6SAlok Aggarwal if (historySize > kMaxHistorySize) 171*b1efbcd6SAlok Aggarwal { 172*b1efbcd6SAlok Aggarwal MatchFinder_Free(p, alloc); 173*b1efbcd6SAlok Aggarwal return 0; 174*b1efbcd6SAlok Aggarwal } 175*b1efbcd6SAlok Aggarwal sizeReserv = historySize >> 1; 176*b1efbcd6SAlok Aggarwal if (historySize > ((UInt32)2 << 30)) 177*b1efbcd6SAlok Aggarwal sizeReserv = historySize >> 2; 178*b1efbcd6SAlok Aggarwal sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19); 179*b1efbcd6SAlok Aggarwal 180*b1efbcd6SAlok Aggarwal p->keepSizeBefore = historySize + keepAddBufferBefore + 1; 181*b1efbcd6SAlok Aggarwal p->keepSizeAfter = matchMaxLen + keepAddBufferAfter; 182*b1efbcd6SAlok Aggarwal /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */ 183*b1efbcd6SAlok Aggarwal if (LzInWindow_Create(p, sizeReserv, alloc)) 184*b1efbcd6SAlok Aggarwal { 185*b1efbcd6SAlok Aggarwal UInt32 newCyclicBufferSize = (historySize /* >> p->skipModeBits */) + 1; 186*b1efbcd6SAlok Aggarwal UInt32 hs; 187*b1efbcd6SAlok Aggarwal p->matchMaxLen = matchMaxLen; 188*b1efbcd6SAlok Aggarwal { 189*b1efbcd6SAlok Aggarwal p->fixedHashSize = 0; 190*b1efbcd6SAlok Aggarwal if (p->numHashBytes == 2) 191*b1efbcd6SAlok Aggarwal hs = (1 << 16) - 1; 192*b1efbcd6SAlok Aggarwal else 193*b1efbcd6SAlok Aggarwal { 194*b1efbcd6SAlok Aggarwal hs = historySize - 1; 195*b1efbcd6SAlok Aggarwal hs |= (hs >> 1); 196*b1efbcd6SAlok Aggarwal hs |= (hs >> 2); 197*b1efbcd6SAlok Aggarwal hs |= (hs >> 4); 198*b1efbcd6SAlok Aggarwal hs |= (hs >> 8); 199*b1efbcd6SAlok Aggarwal hs >>= 1; 200*b1efbcd6SAlok Aggarwal /* hs >>= p->skipModeBits; */ 201*b1efbcd6SAlok Aggarwal hs |= 0xFFFF; /* don't change it! It's required for Deflate */ 202*b1efbcd6SAlok Aggarwal if (hs > (1 << 24)) 203*b1efbcd6SAlok Aggarwal { 204*b1efbcd6SAlok Aggarwal if (p->numHashBytes == 3) 205*b1efbcd6SAlok Aggarwal hs = (1 << 24) - 1; 206*b1efbcd6SAlok Aggarwal else 207*b1efbcd6SAlok Aggarwal hs >>= 1; 208*b1efbcd6SAlok Aggarwal } 209*b1efbcd6SAlok Aggarwal } 210*b1efbcd6SAlok Aggarwal p->hashMask = hs; 211*b1efbcd6SAlok Aggarwal hs++; 212*b1efbcd6SAlok Aggarwal if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size; 213*b1efbcd6SAlok Aggarwal if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size; 214*b1efbcd6SAlok Aggarwal if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size; 215*b1efbcd6SAlok Aggarwal hs += p->fixedHashSize; 216*b1efbcd6SAlok Aggarwal } 217*b1efbcd6SAlok Aggarwal 218*b1efbcd6SAlok Aggarwal { 219*b1efbcd6SAlok Aggarwal UInt32 prevSize = p->hashSizeSum + p->numSons; 220*b1efbcd6SAlok Aggarwal UInt32 newSize; 221*b1efbcd6SAlok Aggarwal p->historySize = historySize; 222*b1efbcd6SAlok Aggarwal p->hashSizeSum = hs; 223*b1efbcd6SAlok Aggarwal p->cyclicBufferSize = newCyclicBufferSize; 224*b1efbcd6SAlok Aggarwal p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize); 225*b1efbcd6SAlok Aggarwal newSize = p->hashSizeSum + p->numSons; 226*b1efbcd6SAlok Aggarwal if (p->hash != 0 && prevSize == newSize) 227*b1efbcd6SAlok Aggarwal return 1; 228*b1efbcd6SAlok Aggarwal MatchFinder_FreeThisClassMemory(p, alloc); 229*b1efbcd6SAlok Aggarwal p->hash = AllocRefs(newSize, alloc); 230*b1efbcd6SAlok Aggarwal if (p->hash != 0) 231*b1efbcd6SAlok Aggarwal { 232*b1efbcd6SAlok Aggarwal p->son = p->hash + p->hashSizeSum; 233*b1efbcd6SAlok Aggarwal return 1; 234*b1efbcd6SAlok Aggarwal } 235*b1efbcd6SAlok Aggarwal } 236*b1efbcd6SAlok Aggarwal } 237*b1efbcd6SAlok Aggarwal MatchFinder_Free(p, alloc); 238*b1efbcd6SAlok Aggarwal return 0; 239*b1efbcd6SAlok Aggarwal } 240*b1efbcd6SAlok Aggarwal 241*b1efbcd6SAlok Aggarwal static void MatchFinder_SetLimits(CMatchFinder *p) 242*b1efbcd6SAlok Aggarwal { 243*b1efbcd6SAlok Aggarwal UInt32 limit = kMaxValForNormalize - p->pos; 244*b1efbcd6SAlok Aggarwal UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos; 245*b1efbcd6SAlok Aggarwal if (limit2 < limit) 246*b1efbcd6SAlok Aggarwal limit = limit2; 247*b1efbcd6SAlok Aggarwal limit2 = p->streamPos - p->pos; 248*b1efbcd6SAlok Aggarwal if (limit2 <= p->keepSizeAfter) 249*b1efbcd6SAlok Aggarwal { 250*b1efbcd6SAlok Aggarwal if (limit2 > 0) 251*b1efbcd6SAlok Aggarwal limit2 = 1; 252*b1efbcd6SAlok Aggarwal } 253*b1efbcd6SAlok Aggarwal else 254*b1efbcd6SAlok Aggarwal limit2 -= p->keepSizeAfter; 255*b1efbcd6SAlok Aggarwal if (limit2 < limit) 256*b1efbcd6SAlok Aggarwal limit = limit2; 257*b1efbcd6SAlok Aggarwal { 258*b1efbcd6SAlok Aggarwal UInt32 lenLimit = p->streamPos - p->pos; 259*b1efbcd6SAlok Aggarwal if (lenLimit > p->matchMaxLen) 260*b1efbcd6SAlok Aggarwal lenLimit = p->matchMaxLen; 261*b1efbcd6SAlok Aggarwal p->lenLimit = lenLimit; 262*b1efbcd6SAlok Aggarwal } 263*b1efbcd6SAlok Aggarwal p->posLimit = p->pos + limit; 264*b1efbcd6SAlok Aggarwal } 265*b1efbcd6SAlok Aggarwal 266*b1efbcd6SAlok Aggarwal void MatchFinder_Init(CMatchFinder *p) 267*b1efbcd6SAlok Aggarwal { 268*b1efbcd6SAlok Aggarwal UInt32 i; 269*b1efbcd6SAlok Aggarwal for (i = 0; i < p->hashSizeSum; i++) 270*b1efbcd6SAlok Aggarwal p->hash[i] = kEmptyHashValue; 271*b1efbcd6SAlok Aggarwal p->cyclicBufferPos = 0; 272*b1efbcd6SAlok Aggarwal p->buffer = p->bufferBase; 273*b1efbcd6SAlok Aggarwal p->pos = p->streamPos = p->cyclicBufferSize; 274*b1efbcd6SAlok Aggarwal p->result = SZ_OK; 275*b1efbcd6SAlok Aggarwal p->streamEndWasReached = 0; 276*b1efbcd6SAlok Aggarwal MatchFinder_ReadBlock(p); 277*b1efbcd6SAlok Aggarwal MatchFinder_SetLimits(p); 278*b1efbcd6SAlok Aggarwal } 279*b1efbcd6SAlok Aggarwal 280*b1efbcd6SAlok Aggarwal static UInt32 MatchFinder_GetSubValue(CMatchFinder *p) 281*b1efbcd6SAlok Aggarwal { 282*b1efbcd6SAlok Aggarwal return (p->pos - p->historySize - 1) & kNormalizeMask; 283*b1efbcd6SAlok Aggarwal } 284*b1efbcd6SAlok Aggarwal 285*b1efbcd6SAlok Aggarwal void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems) 286*b1efbcd6SAlok Aggarwal { 287*b1efbcd6SAlok Aggarwal UInt32 i; 288*b1efbcd6SAlok Aggarwal for (i = 0; i < numItems; i++) 289*b1efbcd6SAlok Aggarwal { 290*b1efbcd6SAlok Aggarwal UInt32 value = items[i]; 291*b1efbcd6SAlok Aggarwal if (value <= subValue) 292*b1efbcd6SAlok Aggarwal value = kEmptyHashValue; 293*b1efbcd6SAlok Aggarwal else 294*b1efbcd6SAlok Aggarwal value -= subValue; 295*b1efbcd6SAlok Aggarwal items[i] = value; 296*b1efbcd6SAlok Aggarwal } 297*b1efbcd6SAlok Aggarwal } 298*b1efbcd6SAlok Aggarwal 299*b1efbcd6SAlok Aggarwal static void MatchFinder_Normalize(CMatchFinder *p) 300*b1efbcd6SAlok Aggarwal { 301*b1efbcd6SAlok Aggarwal UInt32 subValue = MatchFinder_GetSubValue(p); 302*b1efbcd6SAlok Aggarwal MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons); 303*b1efbcd6SAlok Aggarwal MatchFinder_ReduceOffsets(p, subValue); 304*b1efbcd6SAlok Aggarwal } 305*b1efbcd6SAlok Aggarwal 306*b1efbcd6SAlok Aggarwal static void MatchFinder_CheckLimits(CMatchFinder *p) 307*b1efbcd6SAlok Aggarwal { 308*b1efbcd6SAlok Aggarwal if (p->pos == kMaxValForNormalize) 309*b1efbcd6SAlok Aggarwal MatchFinder_Normalize(p); 310*b1efbcd6SAlok Aggarwal if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos) 311*b1efbcd6SAlok Aggarwal MatchFinder_CheckAndMoveAndRead(p); 312*b1efbcd6SAlok Aggarwal if (p->cyclicBufferPos == p->cyclicBufferSize) 313*b1efbcd6SAlok Aggarwal p->cyclicBufferPos = 0; 314*b1efbcd6SAlok Aggarwal MatchFinder_SetLimits(p); 315*b1efbcd6SAlok Aggarwal } 316*b1efbcd6SAlok Aggarwal 317*b1efbcd6SAlok Aggarwal static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, 318*b1efbcd6SAlok Aggarwal UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, 319*b1efbcd6SAlok Aggarwal UInt32 *distances, UInt32 maxLen) 320*b1efbcd6SAlok Aggarwal { 321*b1efbcd6SAlok Aggarwal son[_cyclicBufferPos] = curMatch; 322*b1efbcd6SAlok Aggarwal for (;;) 323*b1efbcd6SAlok Aggarwal { 324*b1efbcd6SAlok Aggarwal UInt32 delta = pos - curMatch; 325*b1efbcd6SAlok Aggarwal if (cutValue-- == 0 || delta >= _cyclicBufferSize) 326*b1efbcd6SAlok Aggarwal return distances; 327*b1efbcd6SAlok Aggarwal { 328*b1efbcd6SAlok Aggarwal const Byte *pb = cur - delta; 329*b1efbcd6SAlok Aggarwal curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; 330*b1efbcd6SAlok Aggarwal if (pb[maxLen] == cur[maxLen] && *pb == *cur) 331*b1efbcd6SAlok Aggarwal { 332*b1efbcd6SAlok Aggarwal UInt32 len = 0; 333*b1efbcd6SAlok Aggarwal while (++len != lenLimit) 334*b1efbcd6SAlok Aggarwal if (pb[len] != cur[len]) 335*b1efbcd6SAlok Aggarwal break; 336*b1efbcd6SAlok Aggarwal if (maxLen < len) 337*b1efbcd6SAlok Aggarwal { 338*b1efbcd6SAlok Aggarwal *distances++ = maxLen = len; 339*b1efbcd6SAlok Aggarwal *distances++ = delta - 1; 340*b1efbcd6SAlok Aggarwal if (len == lenLimit) 341*b1efbcd6SAlok Aggarwal return distances; 342*b1efbcd6SAlok Aggarwal } 343*b1efbcd6SAlok Aggarwal } 344*b1efbcd6SAlok Aggarwal } 345*b1efbcd6SAlok Aggarwal } 346*b1efbcd6SAlok Aggarwal } 347*b1efbcd6SAlok Aggarwal 348*b1efbcd6SAlok Aggarwal UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, 349*b1efbcd6SAlok Aggarwal UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, 350*b1efbcd6SAlok Aggarwal UInt32 *distances, UInt32 maxLen) 351*b1efbcd6SAlok Aggarwal { 352*b1efbcd6SAlok Aggarwal CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; 353*b1efbcd6SAlok Aggarwal CLzRef *ptr1 = son + (_cyclicBufferPos << 1); 354*b1efbcd6SAlok Aggarwal UInt32 len0 = 0, len1 = 0; 355*b1efbcd6SAlok Aggarwal for (;;) 356*b1efbcd6SAlok Aggarwal { 357*b1efbcd6SAlok Aggarwal UInt32 delta = pos - curMatch; 358*b1efbcd6SAlok Aggarwal if (cutValue-- == 0 || delta >= _cyclicBufferSize) 359*b1efbcd6SAlok Aggarwal { 360*b1efbcd6SAlok Aggarwal *ptr0 = *ptr1 = kEmptyHashValue; 361*b1efbcd6SAlok Aggarwal return distances; 362*b1efbcd6SAlok Aggarwal } 363*b1efbcd6SAlok Aggarwal { 364*b1efbcd6SAlok Aggarwal CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); 365*b1efbcd6SAlok Aggarwal const Byte *pb = cur - delta; 366*b1efbcd6SAlok Aggarwal UInt32 len = (len0 < len1 ? len0 : len1); 367*b1efbcd6SAlok Aggarwal if (pb[len] == cur[len]) 368*b1efbcd6SAlok Aggarwal { 369*b1efbcd6SAlok Aggarwal if (++len != lenLimit && pb[len] == cur[len]) 370*b1efbcd6SAlok Aggarwal while (++len != lenLimit) 371*b1efbcd6SAlok Aggarwal if (pb[len] != cur[len]) 372*b1efbcd6SAlok Aggarwal break; 373*b1efbcd6SAlok Aggarwal if (maxLen < len) 374*b1efbcd6SAlok Aggarwal { 375*b1efbcd6SAlok Aggarwal *distances++ = maxLen = len; 376*b1efbcd6SAlok Aggarwal *distances++ = delta - 1; 377*b1efbcd6SAlok Aggarwal if (len == lenLimit) 378*b1efbcd6SAlok Aggarwal { 379*b1efbcd6SAlok Aggarwal *ptr1 = pair[0]; 380*b1efbcd6SAlok Aggarwal *ptr0 = pair[1]; 381*b1efbcd6SAlok Aggarwal return distances; 382*b1efbcd6SAlok Aggarwal } 383*b1efbcd6SAlok Aggarwal } 384*b1efbcd6SAlok Aggarwal } 385*b1efbcd6SAlok Aggarwal if (pb[len] < cur[len]) 386*b1efbcd6SAlok Aggarwal { 387*b1efbcd6SAlok Aggarwal *ptr1 = curMatch; 388*b1efbcd6SAlok Aggarwal ptr1 = pair + 1; 389*b1efbcd6SAlok Aggarwal curMatch = *ptr1; 390*b1efbcd6SAlok Aggarwal len1 = len; 391*b1efbcd6SAlok Aggarwal } 392*b1efbcd6SAlok Aggarwal else 393*b1efbcd6SAlok Aggarwal { 394*b1efbcd6SAlok Aggarwal *ptr0 = curMatch; 395*b1efbcd6SAlok Aggarwal ptr0 = pair; 396*b1efbcd6SAlok Aggarwal curMatch = *ptr0; 397*b1efbcd6SAlok Aggarwal len0 = len; 398*b1efbcd6SAlok Aggarwal } 399*b1efbcd6SAlok Aggarwal } 400*b1efbcd6SAlok Aggarwal } 401*b1efbcd6SAlok Aggarwal } 402*b1efbcd6SAlok Aggarwal 403*b1efbcd6SAlok Aggarwal static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, 404*b1efbcd6SAlok Aggarwal UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue) 405*b1efbcd6SAlok Aggarwal { 406*b1efbcd6SAlok Aggarwal CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; 407*b1efbcd6SAlok Aggarwal CLzRef *ptr1 = son + (_cyclicBufferPos << 1); 408*b1efbcd6SAlok Aggarwal UInt32 len0 = 0, len1 = 0; 409*b1efbcd6SAlok Aggarwal for (;;) 410*b1efbcd6SAlok Aggarwal { 411*b1efbcd6SAlok Aggarwal UInt32 delta = pos - curMatch; 412*b1efbcd6SAlok Aggarwal if (cutValue-- == 0 || delta >= _cyclicBufferSize) 413*b1efbcd6SAlok Aggarwal { 414*b1efbcd6SAlok Aggarwal *ptr0 = *ptr1 = kEmptyHashValue; 415*b1efbcd6SAlok Aggarwal return; 416*b1efbcd6SAlok Aggarwal } 417*b1efbcd6SAlok Aggarwal { 418*b1efbcd6SAlok Aggarwal CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); 419*b1efbcd6SAlok Aggarwal const Byte *pb = cur - delta; 420*b1efbcd6SAlok Aggarwal UInt32 len = (len0 < len1 ? len0 : len1); 421*b1efbcd6SAlok Aggarwal if (pb[len] == cur[len]) 422*b1efbcd6SAlok Aggarwal { 423*b1efbcd6SAlok Aggarwal while (++len != lenLimit) 424*b1efbcd6SAlok Aggarwal if (pb[len] != cur[len]) 425*b1efbcd6SAlok Aggarwal break; 426*b1efbcd6SAlok Aggarwal { 427*b1efbcd6SAlok Aggarwal if (len == lenLimit) 428*b1efbcd6SAlok Aggarwal { 429*b1efbcd6SAlok Aggarwal *ptr1 = pair[0]; 430*b1efbcd6SAlok Aggarwal *ptr0 = pair[1]; 431*b1efbcd6SAlok Aggarwal return; 432*b1efbcd6SAlok Aggarwal } 433*b1efbcd6SAlok Aggarwal } 434*b1efbcd6SAlok Aggarwal } 435*b1efbcd6SAlok Aggarwal if (pb[len] < cur[len]) 436*b1efbcd6SAlok Aggarwal { 437*b1efbcd6SAlok Aggarwal *ptr1 = curMatch; 438*b1efbcd6SAlok Aggarwal ptr1 = pair + 1; 439*b1efbcd6SAlok Aggarwal curMatch = *ptr1; 440*b1efbcd6SAlok Aggarwal len1 = len; 441*b1efbcd6SAlok Aggarwal } 442*b1efbcd6SAlok Aggarwal else 443*b1efbcd6SAlok Aggarwal { 444*b1efbcd6SAlok Aggarwal *ptr0 = curMatch; 445*b1efbcd6SAlok Aggarwal ptr0 = pair; 446*b1efbcd6SAlok Aggarwal curMatch = *ptr0; 447*b1efbcd6SAlok Aggarwal len0 = len; 448*b1efbcd6SAlok Aggarwal } 449*b1efbcd6SAlok Aggarwal } 450*b1efbcd6SAlok Aggarwal } 451*b1efbcd6SAlok Aggarwal } 452*b1efbcd6SAlok Aggarwal 453*b1efbcd6SAlok Aggarwal #define MOVE_POS \ 454*b1efbcd6SAlok Aggarwal ++p->cyclicBufferPos; \ 455*b1efbcd6SAlok Aggarwal p->buffer++; \ 456*b1efbcd6SAlok Aggarwal if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p); 457*b1efbcd6SAlok Aggarwal 458*b1efbcd6SAlok Aggarwal #define MOVE_POS_RET MOVE_POS return offset; 459*b1efbcd6SAlok Aggarwal 460*b1efbcd6SAlok Aggarwal static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; } 461*b1efbcd6SAlok Aggarwal 462*b1efbcd6SAlok Aggarwal #define GET_MATCHES_HEADER2(minLen, ret_op) \ 463*b1efbcd6SAlok Aggarwal UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \ 464*b1efbcd6SAlok Aggarwal lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \ 465*b1efbcd6SAlok Aggarwal cur = p->buffer; 466*b1efbcd6SAlok Aggarwal 467*b1efbcd6SAlok Aggarwal #define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0) 468*b1efbcd6SAlok Aggarwal #define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue) 469*b1efbcd6SAlok Aggarwal 470*b1efbcd6SAlok Aggarwal #define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue 471*b1efbcd6SAlok Aggarwal 472*b1efbcd6SAlok Aggarwal #define GET_MATCHES_FOOTER(offset, maxLen) \ 473*b1efbcd6SAlok Aggarwal offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \ 474*b1efbcd6SAlok Aggarwal distances + offset, maxLen) - distances); MOVE_POS_RET; 475*b1efbcd6SAlok Aggarwal 476*b1efbcd6SAlok Aggarwal #define SKIP_FOOTER \ 477*b1efbcd6SAlok Aggarwal SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS; 478*b1efbcd6SAlok Aggarwal 479*b1efbcd6SAlok Aggarwal static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) 480*b1efbcd6SAlok Aggarwal { 481*b1efbcd6SAlok Aggarwal UInt32 offset; 482*b1efbcd6SAlok Aggarwal GET_MATCHES_HEADER(2) 483*b1efbcd6SAlok Aggarwal HASH2_CALC; 484*b1efbcd6SAlok Aggarwal curMatch = p->hash[hashValue]; 485*b1efbcd6SAlok Aggarwal p->hash[hashValue] = p->pos; 486*b1efbcd6SAlok Aggarwal offset = 0; 487*b1efbcd6SAlok Aggarwal GET_MATCHES_FOOTER(offset, 1) 488*b1efbcd6SAlok Aggarwal } 489*b1efbcd6SAlok Aggarwal 490*b1efbcd6SAlok Aggarwal UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) 491*b1efbcd6SAlok Aggarwal { 492*b1efbcd6SAlok Aggarwal UInt32 offset; 493*b1efbcd6SAlok Aggarwal GET_MATCHES_HEADER(3) 494*b1efbcd6SAlok Aggarwal HASH_ZIP_CALC; 495*b1efbcd6SAlok Aggarwal curMatch = p->hash[hashValue]; 496*b1efbcd6SAlok Aggarwal p->hash[hashValue] = p->pos; 497*b1efbcd6SAlok Aggarwal offset = 0; 498*b1efbcd6SAlok Aggarwal GET_MATCHES_FOOTER(offset, 2) 499*b1efbcd6SAlok Aggarwal } 500*b1efbcd6SAlok Aggarwal 501*b1efbcd6SAlok Aggarwal static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) 502*b1efbcd6SAlok Aggarwal { 503*b1efbcd6SAlok Aggarwal UInt32 hash2Value, delta2, maxLen, offset; 504*b1efbcd6SAlok Aggarwal GET_MATCHES_HEADER(3) 505*b1efbcd6SAlok Aggarwal 506*b1efbcd6SAlok Aggarwal HASH3_CALC; 507*b1efbcd6SAlok Aggarwal 508*b1efbcd6SAlok Aggarwal delta2 = p->pos - p->hash[hash2Value]; 509*b1efbcd6SAlok Aggarwal curMatch = p->hash[kFix3HashSize + hashValue]; 510*b1efbcd6SAlok Aggarwal 511*b1efbcd6SAlok Aggarwal p->hash[hash2Value] = 512*b1efbcd6SAlok Aggarwal p->hash[kFix3HashSize + hashValue] = p->pos; 513*b1efbcd6SAlok Aggarwal 514*b1efbcd6SAlok Aggarwal 515*b1efbcd6SAlok Aggarwal maxLen = 2; 516*b1efbcd6SAlok Aggarwal offset = 0; 517*b1efbcd6SAlok Aggarwal if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) 518*b1efbcd6SAlok Aggarwal { 519*b1efbcd6SAlok Aggarwal for (; maxLen != lenLimit; maxLen++) 520*b1efbcd6SAlok Aggarwal if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) 521*b1efbcd6SAlok Aggarwal break; 522*b1efbcd6SAlok Aggarwal distances[0] = maxLen; 523*b1efbcd6SAlok Aggarwal distances[1] = delta2 - 1; 524*b1efbcd6SAlok Aggarwal offset = 2; 525*b1efbcd6SAlok Aggarwal if (maxLen == lenLimit) 526*b1efbcd6SAlok Aggarwal { 527*b1efbcd6SAlok Aggarwal SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); 528*b1efbcd6SAlok Aggarwal MOVE_POS_RET; 529*b1efbcd6SAlok Aggarwal } 530*b1efbcd6SAlok Aggarwal } 531*b1efbcd6SAlok Aggarwal GET_MATCHES_FOOTER(offset, maxLen) 532*b1efbcd6SAlok Aggarwal } 533*b1efbcd6SAlok Aggarwal 534*b1efbcd6SAlok Aggarwal static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) 535*b1efbcd6SAlok Aggarwal { 536*b1efbcd6SAlok Aggarwal UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; 537*b1efbcd6SAlok Aggarwal GET_MATCHES_HEADER(4) 538*b1efbcd6SAlok Aggarwal 539*b1efbcd6SAlok Aggarwal HASH4_CALC; 540*b1efbcd6SAlok Aggarwal 541*b1efbcd6SAlok Aggarwal delta2 = p->pos - p->hash[ hash2Value]; 542*b1efbcd6SAlok Aggarwal delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; 543*b1efbcd6SAlok Aggarwal curMatch = p->hash[kFix4HashSize + hashValue]; 544*b1efbcd6SAlok Aggarwal 545*b1efbcd6SAlok Aggarwal p->hash[ hash2Value] = 546*b1efbcd6SAlok Aggarwal p->hash[kFix3HashSize + hash3Value] = 547*b1efbcd6SAlok Aggarwal p->hash[kFix4HashSize + hashValue] = p->pos; 548*b1efbcd6SAlok Aggarwal 549*b1efbcd6SAlok Aggarwal maxLen = 1; 550*b1efbcd6SAlok Aggarwal offset = 0; 551*b1efbcd6SAlok Aggarwal if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) 552*b1efbcd6SAlok Aggarwal { 553*b1efbcd6SAlok Aggarwal distances[0] = maxLen = 2; 554*b1efbcd6SAlok Aggarwal distances[1] = delta2 - 1; 555*b1efbcd6SAlok Aggarwal offset = 2; 556*b1efbcd6SAlok Aggarwal } 557*b1efbcd6SAlok Aggarwal if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) 558*b1efbcd6SAlok Aggarwal { 559*b1efbcd6SAlok Aggarwal maxLen = 3; 560*b1efbcd6SAlok Aggarwal distances[offset + 1] = delta3 - 1; 561*b1efbcd6SAlok Aggarwal offset += 2; 562*b1efbcd6SAlok Aggarwal delta2 = delta3; 563*b1efbcd6SAlok Aggarwal } 564*b1efbcd6SAlok Aggarwal if (offset != 0) 565*b1efbcd6SAlok Aggarwal { 566*b1efbcd6SAlok Aggarwal for (; maxLen != lenLimit; maxLen++) 567*b1efbcd6SAlok Aggarwal if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) 568*b1efbcd6SAlok Aggarwal break; 569*b1efbcd6SAlok Aggarwal distances[offset - 2] = maxLen; 570*b1efbcd6SAlok Aggarwal if (maxLen == lenLimit) 571*b1efbcd6SAlok Aggarwal { 572*b1efbcd6SAlok Aggarwal SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); 573*b1efbcd6SAlok Aggarwal MOVE_POS_RET; 574*b1efbcd6SAlok Aggarwal } 575*b1efbcd6SAlok Aggarwal } 576*b1efbcd6SAlok Aggarwal if (maxLen < 3) 577*b1efbcd6SAlok Aggarwal maxLen = 3; 578*b1efbcd6SAlok Aggarwal GET_MATCHES_FOOTER(offset, maxLen) 579*b1efbcd6SAlok Aggarwal } 580*b1efbcd6SAlok Aggarwal 581*b1efbcd6SAlok Aggarwal static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) 582*b1efbcd6SAlok Aggarwal { 583*b1efbcd6SAlok Aggarwal UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; 584*b1efbcd6SAlok Aggarwal GET_MATCHES_HEADER(4) 585*b1efbcd6SAlok Aggarwal 586*b1efbcd6SAlok Aggarwal HASH4_CALC; 587*b1efbcd6SAlok Aggarwal 588*b1efbcd6SAlok Aggarwal delta2 = p->pos - p->hash[ hash2Value]; 589*b1efbcd6SAlok Aggarwal delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; 590*b1efbcd6SAlok Aggarwal curMatch = p->hash[kFix4HashSize + hashValue]; 591*b1efbcd6SAlok Aggarwal 592*b1efbcd6SAlok Aggarwal p->hash[ hash2Value] = 593*b1efbcd6SAlok Aggarwal p->hash[kFix3HashSize + hash3Value] = 594*b1efbcd6SAlok Aggarwal p->hash[kFix4HashSize + hashValue] = p->pos; 595*b1efbcd6SAlok Aggarwal 596*b1efbcd6SAlok Aggarwal maxLen = 1; 597*b1efbcd6SAlok Aggarwal offset = 0; 598*b1efbcd6SAlok Aggarwal if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) 599*b1efbcd6SAlok Aggarwal { 600*b1efbcd6SAlok Aggarwal distances[0] = maxLen = 2; 601*b1efbcd6SAlok Aggarwal distances[1] = delta2 - 1; 602*b1efbcd6SAlok Aggarwal offset = 2; 603*b1efbcd6SAlok Aggarwal } 604*b1efbcd6SAlok Aggarwal if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) 605*b1efbcd6SAlok Aggarwal { 606*b1efbcd6SAlok Aggarwal maxLen = 3; 607*b1efbcd6SAlok Aggarwal distances[offset + 1] = delta3 - 1; 608*b1efbcd6SAlok Aggarwal offset += 2; 609*b1efbcd6SAlok Aggarwal delta2 = delta3; 610*b1efbcd6SAlok Aggarwal } 611*b1efbcd6SAlok Aggarwal if (offset != 0) 612*b1efbcd6SAlok Aggarwal { 613*b1efbcd6SAlok Aggarwal for (; maxLen != lenLimit; maxLen++) 614*b1efbcd6SAlok Aggarwal if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) 615*b1efbcd6SAlok Aggarwal break; 616*b1efbcd6SAlok Aggarwal distances[offset - 2] = maxLen; 617*b1efbcd6SAlok Aggarwal if (maxLen == lenLimit) 618*b1efbcd6SAlok Aggarwal { 619*b1efbcd6SAlok Aggarwal p->son[p->cyclicBufferPos] = curMatch; 620*b1efbcd6SAlok Aggarwal MOVE_POS_RET; 621*b1efbcd6SAlok Aggarwal } 622*b1efbcd6SAlok Aggarwal } 623*b1efbcd6SAlok Aggarwal if (maxLen < 3) 624*b1efbcd6SAlok Aggarwal maxLen = 3; 625*b1efbcd6SAlok Aggarwal offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), 626*b1efbcd6SAlok Aggarwal distances + offset, maxLen) - (distances)); 627*b1efbcd6SAlok Aggarwal MOVE_POS_RET 628*b1efbcd6SAlok Aggarwal } 629*b1efbcd6SAlok Aggarwal 630*b1efbcd6SAlok Aggarwal UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) 631*b1efbcd6SAlok Aggarwal { 632*b1efbcd6SAlok Aggarwal UInt32 offset; 633*b1efbcd6SAlok Aggarwal GET_MATCHES_HEADER(3) 634*b1efbcd6SAlok Aggarwal HASH_ZIP_CALC; 635*b1efbcd6SAlok Aggarwal curMatch = p->hash[hashValue]; 636*b1efbcd6SAlok Aggarwal p->hash[hashValue] = p->pos; 637*b1efbcd6SAlok Aggarwal offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), 638*b1efbcd6SAlok Aggarwal distances, 2) - (distances)); 639*b1efbcd6SAlok Aggarwal MOVE_POS_RET 640*b1efbcd6SAlok Aggarwal } 641*b1efbcd6SAlok Aggarwal 642*b1efbcd6SAlok Aggarwal static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num) 643*b1efbcd6SAlok Aggarwal { 644*b1efbcd6SAlok Aggarwal do 645*b1efbcd6SAlok Aggarwal { 646*b1efbcd6SAlok Aggarwal SKIP_HEADER(2) 647*b1efbcd6SAlok Aggarwal HASH2_CALC; 648*b1efbcd6SAlok Aggarwal curMatch = p->hash[hashValue]; 649*b1efbcd6SAlok Aggarwal p->hash[hashValue] = p->pos; 650*b1efbcd6SAlok Aggarwal SKIP_FOOTER 651*b1efbcd6SAlok Aggarwal } 652*b1efbcd6SAlok Aggarwal while (--num != 0); 653*b1efbcd6SAlok Aggarwal } 654*b1efbcd6SAlok Aggarwal 655*b1efbcd6SAlok Aggarwal void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) 656*b1efbcd6SAlok Aggarwal { 657*b1efbcd6SAlok Aggarwal do 658*b1efbcd6SAlok Aggarwal { 659*b1efbcd6SAlok Aggarwal SKIP_HEADER(3) 660*b1efbcd6SAlok Aggarwal HASH_ZIP_CALC; 661*b1efbcd6SAlok Aggarwal curMatch = p->hash[hashValue]; 662*b1efbcd6SAlok Aggarwal p->hash[hashValue] = p->pos; 663*b1efbcd6SAlok Aggarwal SKIP_FOOTER 664*b1efbcd6SAlok Aggarwal } 665*b1efbcd6SAlok Aggarwal while (--num != 0); 666*b1efbcd6SAlok Aggarwal } 667*b1efbcd6SAlok Aggarwal 668*b1efbcd6SAlok Aggarwal static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num) 669*b1efbcd6SAlok Aggarwal { 670*b1efbcd6SAlok Aggarwal do 671*b1efbcd6SAlok Aggarwal { 672*b1efbcd6SAlok Aggarwal UInt32 hash2Value; 673*b1efbcd6SAlok Aggarwal SKIP_HEADER(3) 674*b1efbcd6SAlok Aggarwal HASH3_CALC; 675*b1efbcd6SAlok Aggarwal curMatch = p->hash[kFix3HashSize + hashValue]; 676*b1efbcd6SAlok Aggarwal p->hash[hash2Value] = 677*b1efbcd6SAlok Aggarwal p->hash[kFix3HashSize + hashValue] = p->pos; 678*b1efbcd6SAlok Aggarwal SKIP_FOOTER 679*b1efbcd6SAlok Aggarwal } 680*b1efbcd6SAlok Aggarwal while (--num != 0); 681*b1efbcd6SAlok Aggarwal } 682*b1efbcd6SAlok Aggarwal 683*b1efbcd6SAlok Aggarwal static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) 684*b1efbcd6SAlok Aggarwal { 685*b1efbcd6SAlok Aggarwal do 686*b1efbcd6SAlok Aggarwal { 687*b1efbcd6SAlok Aggarwal UInt32 hash2Value, hash3Value; 688*b1efbcd6SAlok Aggarwal SKIP_HEADER(4) 689*b1efbcd6SAlok Aggarwal HASH4_CALC; 690*b1efbcd6SAlok Aggarwal curMatch = p->hash[kFix4HashSize + hashValue]; 691*b1efbcd6SAlok Aggarwal p->hash[ hash2Value] = 692*b1efbcd6SAlok Aggarwal p->hash[kFix3HashSize + hash3Value] = p->pos; 693*b1efbcd6SAlok Aggarwal p->hash[kFix4HashSize + hashValue] = p->pos; 694*b1efbcd6SAlok Aggarwal SKIP_FOOTER 695*b1efbcd6SAlok Aggarwal } 696*b1efbcd6SAlok Aggarwal while (--num != 0); 697*b1efbcd6SAlok Aggarwal } 698*b1efbcd6SAlok Aggarwal 699*b1efbcd6SAlok Aggarwal static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) 700*b1efbcd6SAlok Aggarwal { 701*b1efbcd6SAlok Aggarwal do 702*b1efbcd6SAlok Aggarwal { 703*b1efbcd6SAlok Aggarwal UInt32 hash2Value, hash3Value; 704*b1efbcd6SAlok Aggarwal SKIP_HEADER(4) 705*b1efbcd6SAlok Aggarwal HASH4_CALC; 706*b1efbcd6SAlok Aggarwal curMatch = p->hash[kFix4HashSize + hashValue]; 707*b1efbcd6SAlok Aggarwal p->hash[ hash2Value] = 708*b1efbcd6SAlok Aggarwal p->hash[kFix3HashSize + hash3Value] = 709*b1efbcd6SAlok Aggarwal p->hash[kFix4HashSize + hashValue] = p->pos; 710*b1efbcd6SAlok Aggarwal p->son[p->cyclicBufferPos] = curMatch; 711*b1efbcd6SAlok Aggarwal MOVE_POS 712*b1efbcd6SAlok Aggarwal } 713*b1efbcd6SAlok Aggarwal while (--num != 0); 714*b1efbcd6SAlok Aggarwal } 715*b1efbcd6SAlok Aggarwal 716*b1efbcd6SAlok Aggarwal void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) 717*b1efbcd6SAlok Aggarwal { 718*b1efbcd6SAlok Aggarwal do 719*b1efbcd6SAlok Aggarwal { 720*b1efbcd6SAlok Aggarwal SKIP_HEADER(3) 721*b1efbcd6SAlok Aggarwal HASH_ZIP_CALC; 722*b1efbcd6SAlok Aggarwal curMatch = p->hash[hashValue]; 723*b1efbcd6SAlok Aggarwal p->hash[hashValue] = p->pos; 724*b1efbcd6SAlok Aggarwal p->son[p->cyclicBufferPos] = curMatch; 725*b1efbcd6SAlok Aggarwal MOVE_POS 726*b1efbcd6SAlok Aggarwal } 727*b1efbcd6SAlok Aggarwal while (--num != 0); 728*b1efbcd6SAlok Aggarwal } 729*b1efbcd6SAlok Aggarwal 730*b1efbcd6SAlok Aggarwal void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable) 731*b1efbcd6SAlok Aggarwal { 732*b1efbcd6SAlok Aggarwal vTable->Init = (Mf_Init_Func)MatchFinder_Init; 733*b1efbcd6SAlok Aggarwal vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte; 734*b1efbcd6SAlok Aggarwal vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes; 735*b1efbcd6SAlok Aggarwal vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos; 736*b1efbcd6SAlok Aggarwal if (!p->btMode) 737*b1efbcd6SAlok Aggarwal { 738*b1efbcd6SAlok Aggarwal vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches; 739*b1efbcd6SAlok Aggarwal vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip; 740*b1efbcd6SAlok Aggarwal } 741*b1efbcd6SAlok Aggarwal else if (p->numHashBytes == 2) 742*b1efbcd6SAlok Aggarwal { 743*b1efbcd6SAlok Aggarwal vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches; 744*b1efbcd6SAlok Aggarwal vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip; 745*b1efbcd6SAlok Aggarwal } 746*b1efbcd6SAlok Aggarwal else if (p->numHashBytes == 3) 747*b1efbcd6SAlok Aggarwal { 748*b1efbcd6SAlok Aggarwal vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches; 749*b1efbcd6SAlok Aggarwal vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip; 750*b1efbcd6SAlok Aggarwal } 751*b1efbcd6SAlok Aggarwal else 752*b1efbcd6SAlok Aggarwal { 753*b1efbcd6SAlok Aggarwal vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches; 754*b1efbcd6SAlok Aggarwal vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip; 755*b1efbcd6SAlok Aggarwal } 756*b1efbcd6SAlok Aggarwal } 757