goat3d

annotate libs/openctm/liblzma/LzFind.c @ 51:fa5c52ea9d59

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