Annotation of elwix/tools/oldlzma/SRC/7zip/Compress/LZ/Patricia/PatMain.h, revision 1.1
1.1 ! misho 1: // PatMain.h
! 2:
! 3: #include "../../../../Common/Defs.h"
! 4: #include "../../../../Common/Alloc.h"
! 5:
! 6: namespace PAT_NAMESPACE {
! 7:
! 8: STDMETHODIMP CPatricia::SetCallback(IMatchFinderCallback *callback)
! 9: {
! 10: m_Callback = callback;
! 11: return S_OK;
! 12: }
! 13:
! 14: void CPatricia::BeforeMoveBlock()
! 15: {
! 16: if (m_Callback)
! 17: m_Callback->BeforeChangingBufferPos();
! 18: CLZInWindow::BeforeMoveBlock();
! 19: }
! 20:
! 21: void CPatricia::AfterMoveBlock()
! 22: {
! 23: if (m_Callback)
! 24: m_Callback->AfterChangingBufferPos();
! 25: CLZInWindow::AfterMoveBlock();
! 26: }
! 27:
! 28: const UInt32 kMatchStartValue2 = 2;
! 29: const UInt32 kDescendantEmptyValue2 = kMatchStartValue2 - 1;
! 30: const UInt32 kDescendantsNotInitilized2 = kDescendantEmptyValue2 - 1;
! 31:
! 32: #ifdef __HASH_3
! 33:
! 34: static const UInt32 kNumHashBytes = 3;
! 35: static const UInt32 kHashSize = 1 << (8 * kNumHashBytes);
! 36:
! 37: static const UInt32 kNumHash2Bytes = 2;
! 38: static const UInt32 kHash2Size = 1 << (8 * kNumHash2Bytes);
! 39: static const UInt32 kPrevHashSize = kNumHash2Bytes;
! 40:
! 41: #else
! 42:
! 43: static const UInt32 kNumHashBytes = 2;
! 44: static const UInt32 kHashSize = 1 << (8 * kNumHashBytes);
! 45: static const UInt32 kPrevHashSize = 0;
! 46:
! 47: #endif
! 48:
! 49:
! 50: CPatricia::CPatricia():
! 51: m_HashDescendants(0),
! 52: #ifdef __HASH_3
! 53: m_Hash2Descendants(0),
! 54: #endif
! 55: m_Nodes(0),
! 56: m_TmpBacks(0)
! 57: {
! 58: }
! 59:
! 60: CPatricia::~CPatricia()
! 61: {
! 62: FreeMemory();
! 63: }
! 64:
! 65: void CPatricia::FreeMemory()
! 66: {
! 67: MyFree(m_TmpBacks);
! 68: m_TmpBacks = 0;
! 69:
! 70: ::BigFree(m_Nodes);
! 71: m_Nodes = 0;
! 72:
! 73: ::BigFree(m_HashDescendants);
! 74: m_HashDescendants = 0;
! 75:
! 76: #ifdef __HASH_3
! 77:
! 78: ::BigFree(m_Hash2Descendants);
! 79: m_Hash2Descendants = 0;
! 80:
! 81: CLZInWindow::Free();
! 82:
! 83: #endif
! 84: }
! 85:
! 86: STDMETHODIMP CPatricia::Create(UInt32 historySize, UInt32 keepAddBufferBefore,
! 87: UInt32 matchMaxLen, UInt32 keepAddBufferAfter)
! 88: {
! 89: FreeMemory();
! 90: int kNumBitsInNumSameBits = sizeof(CSameBitsType) * 8;
! 91: if (kNumBitsInNumSameBits < 32 && ((matchMaxLen * MY_BYTE_SIZE) > ((UInt32)1 << kNumBitsInNumSameBits)))
! 92: return E_INVALIDARG;
! 93:
! 94: const UInt32 kAlignMask = (1 << 16) - 1;
! 95: UInt32 windowReservSize = historySize;
! 96: windowReservSize += kAlignMask;
! 97: windowReservSize &= ~(kAlignMask);
! 98:
! 99: const UInt32 kMinReservSize = (1 << 19);
! 100: if (windowReservSize < kMinReservSize)
! 101: windowReservSize = kMinReservSize;
! 102: windowReservSize += 256;
! 103:
! 104: if (!CLZInWindow::Create(historySize + keepAddBufferBefore,
! 105: matchMaxLen + keepAddBufferAfter, windowReservSize))
! 106: return E_OUTOFMEMORY;
! 107:
! 108: _sizeHistory = historySize;
! 109: _matchMaxLen = matchMaxLen;
! 110: m_HashDescendants = (CDescendant *)BigAlloc(kHashSize * sizeof(CDescendant));
! 111: if (m_HashDescendants == 0)
! 112: {
! 113: FreeMemory();
! 114: return E_OUTOFMEMORY;
! 115: }
! 116:
! 117: #ifdef __HASH_3
! 118: m_Hash2Descendants = (CDescendant *)BigAlloc(kHash2Size * sizeof(CDescendant));
! 119: if (m_Hash2Descendants == 0)
! 120: {
! 121: FreeMemory();
! 122: return E_OUTOFMEMORY;
! 123: }
! 124: #endif
! 125:
! 126: #ifdef __AUTO_REMOVE
! 127:
! 128: #ifdef __HASH_3
! 129: m_NumNodes = historySize + _sizeHistory * 4 / 8 + (1 << 19);
! 130: #else
! 131: m_NumNodes = historySize + _sizeHistory * 4 / 8 + (1 << 10);
! 132: #endif
! 133:
! 134: #else
! 135:
! 136: UInt32 m_NumNodes = historySize;
! 137:
! 138: #endif
! 139:
! 140: const UInt32 kMaxNumNodes = UInt32(1) << (sizeof(CIndex) * 8 - 1);
! 141: if (m_NumNodes + 32 > kMaxNumNodes)
! 142: return E_INVALIDARG;
! 143:
! 144: // m_Nodes = (CNode *)::BigAlloc((m_NumNodes + 2) * sizeof(CNode));
! 145: m_Nodes = (CNode *)::BigAlloc((m_NumNodes + 12) * sizeof(CNode));
! 146: if (m_Nodes == 0)
! 147: {
! 148: FreeMemory();
! 149: return E_OUTOFMEMORY;
! 150: }
! 151:
! 152: m_TmpBacks = (UInt32 *)MyAlloc((_matchMaxLen + 1) * sizeof(UInt32));
! 153: if (m_TmpBacks == 0)
! 154: {
! 155: FreeMemory();
! 156: return E_OUTOFMEMORY;
! 157: }
! 158: return S_OK;
! 159: }
! 160:
! 161: STDMETHODIMP CPatricia::Init(ISequentialInStream *aStream)
! 162: {
! 163: RINOK(CLZInWindow::Init(aStream));
! 164:
! 165: // memset(m_HashDescendants, 0xFF, kHashSize * sizeof(m_HashDescendants[0]));
! 166:
! 167: #ifdef __HASH_3
! 168: for (UInt32 i = 0; i < kHash2Size; i++)
! 169: m_Hash2Descendants[i].MatchPointer = kDescendantsNotInitilized2;
! 170: #else
! 171: for (UInt32 i = 0; i < kHashSize; i++)
! 172: m_HashDescendants[i].MakeEmpty();
! 173: #endif
! 174:
! 175: m_Nodes[0].NextFreeNode = 1;
! 176: m_FreeNode = 0;
! 177: m_FreeNodeMax = 0;
! 178: #ifdef __AUTO_REMOVE
! 179: m_NumUsedNodes = 0;
! 180: #else
! 181: m_SpecialRemoveMode = false;
! 182: #endif
! 183: m_SpecialMode = false;
! 184: return S_OK;
! 185: }
! 186:
! 187: STDMETHODIMP_(void) CPatricia::ReleaseStream()
! 188: {
! 189: // CLZInWindow::ReleaseStream();
! 190: }
! 191:
! 192: // pos = _pos + kNumHashBytes
! 193: // fullCurrentLimit = currentLimit + kNumHashBytes
! 194: // fullMatchLen = matchLen + kNumHashBytes
! 195:
! 196: void CPatricia::ChangeLastMatch(UInt32 hashValue)
! 197: {
! 198: UInt32 pos = _pos + kNumHashBytes - 1;
! 199: UInt32 descendantIndex;
! 200: const Byte *currentBytePointer = _buffer + pos;
! 201: UInt32 numLoadedBits = 0;
! 202: Byte curByte = 0; // = 0 to disable warning of GCC
! 203: CNodePointer node = &m_Nodes[m_HashDescendants[hashValue].NodePointer];
! 204:
! 205: while(true)
! 206: {
! 207: UInt32 numSameBits = node->NumSameBits;
! 208: if(numSameBits > 0)
! 209: {
! 210: if (numLoadedBits < numSameBits)
! 211: {
! 212: numSameBits -= numLoadedBits;
! 213: currentBytePointer += (numSameBits / MY_BYTE_SIZE);
! 214: numSameBits %= MY_BYTE_SIZE;
! 215: curByte = *currentBytePointer++;
! 216: numLoadedBits = MY_BYTE_SIZE;
! 217: }
! 218: curByte >>= numSameBits;
! 219: numLoadedBits -= numSameBits;
! 220: }
! 221: if(numLoadedBits == 0)
! 222: {
! 223: curByte = *currentBytePointer++;
! 224: numLoadedBits = MY_BYTE_SIZE;
! 225: }
! 226: descendantIndex = (curByte & kSubNodesMask);
! 227: node->LastMatch = pos;
! 228: numLoadedBits -= kNumSubBits;
! 229: curByte >>= kNumSubBits;
! 230: if(node->Descendants[descendantIndex].IsNode())
! 231: node = &m_Nodes[node->Descendants[descendantIndex].NodePointer];
! 232: else
! 233: break;
! 234: }
! 235: node->Descendants[descendantIndex].MatchPointer = pos + kMatchStartValue;
! 236: }
! 237:
! 238: UInt32 CPatricia::GetLongestMatch(UInt32 *distances)
! 239: {
! 240: UInt32 fullCurrentLimit;
! 241: if (_pos + _matchMaxLen <= _streamPos)
! 242: fullCurrentLimit = _matchMaxLen;
! 243: else
! 244: {
! 245: fullCurrentLimit = _streamPos - _pos;
! 246: if(fullCurrentLimit < kNumHashBytes)
! 247: return 0;
! 248: }
! 249: UInt32 pos = _pos + kNumHashBytes;
! 250:
! 251: #ifdef __HASH_3
! 252: UInt32 hash2Value = ((UInt32(_buffer[_pos])) << 8) | _buffer[_pos + 1];
! 253: UInt32 hashValue = (hash2Value << 8) | _buffer[_pos + 2];
! 254: CDescendant &hash2Descendant = m_Hash2Descendants[hash2Value];
! 255: CDescendant &hashDescendant = m_HashDescendants[hashValue];
! 256: if(hash2Descendant.MatchPointer <= kDescendantEmptyValue2)
! 257: {
! 258: if(hash2Descendant.MatchPointer == kDescendantsNotInitilized2)
! 259: {
! 260: UInt32 base = hashValue & 0xFFFF00;
! 261: for (UInt32 i = 0; i < 0x100; i++)
! 262: m_HashDescendants[base + i].MakeEmpty();
! 263: }
! 264: hash2Descendant.MatchPointer = pos + kMatchStartValue2;
! 265: hashDescendant.MatchPointer = pos + kMatchStartValue;
! 266: return 0;
! 267: }
! 268:
! 269: distances[kNumHash2Bytes] = pos - (hash2Descendant.MatchPointer - kMatchStartValue2) - 1;
! 270: hash2Descendant.MatchPointer = pos + kMatchStartValue2;
! 271: #ifdef __AUTO_REMOVE
! 272: if (distances[kNumHash2Bytes] >= _sizeHistory)
! 273: {
! 274: if (hashDescendant.IsNode())
! 275: RemoveNode(hashDescendant.NodePointer);
! 276: hashDescendant.MatchPointer = pos + kMatchStartValue;
! 277: return 0;
! 278: }
! 279: #endif
! 280: if (fullCurrentLimit == kNumHash2Bytes)
! 281: return kNumHash2Bytes;
! 282:
! 283: #else
! 284: UInt32 hashValue = UInt32(GetIndexByte(1)) | (UInt32(GetIndexByte(0)) << 8);
! 285: CDescendant &hashDescendant = m_HashDescendants[hashValue];
! 286: #endif
! 287:
! 288:
! 289: if(m_SpecialMode)
! 290: {
! 291: if(hashDescendant.IsMatch())
! 292: m_NumNotChangedCycles = 0;
! 293: if(m_NumNotChangedCycles >= _sizeHistory - 1)
! 294: {
! 295: ChangeLastMatch(hashValue);
! 296: m_NumNotChangedCycles = 0;
! 297: }
! 298: if(GetIndexByte(fullCurrentLimit - 1) == GetIndexByte(fullCurrentLimit - 2))
! 299: {
! 300: if(hashDescendant.IsMatch())
! 301: hashDescendant.MatchPointer = pos + kMatchStartValue;
! 302: else
! 303: m_NumNotChangedCycles++;
! 304: for(UInt32 i = kNumHashBytes; i <= fullCurrentLimit; i++)
! 305: distances[i] = 0;
! 306: return fullCurrentLimit;
! 307: }
! 308: else if(m_NumNotChangedCycles > 0)
! 309: ChangeLastMatch(hashValue);
! 310: m_SpecialMode = false;
! 311: }
! 312:
! 313: if(hashDescendant.IsEmpty())
! 314: {
! 315: hashDescendant.MatchPointer = pos + kMatchStartValue;
! 316: return kPrevHashSize;
! 317: }
! 318:
! 319: UInt32 currentLimit = fullCurrentLimit - kNumHashBytes;
! 320:
! 321: if(hashDescendant.IsMatch())
! 322: {
! 323: CMatchPointer matchPointer = hashDescendant.MatchPointer;
! 324: UInt32 backReal = pos - (matchPointer - kMatchStartValue);
! 325: UInt32 back = backReal - 1;
! 326: #ifdef __AUTO_REMOVE
! 327: if (back >= _sizeHistory)
! 328: {
! 329: hashDescendant.MatchPointer = pos + kMatchStartValue;
! 330: return kPrevHashSize;
! 331: }
! 332: #endif
! 333:
! 334: UInt32 matchLen;
! 335: distances += kNumHashBytes;
! 336: Byte *buffer = _buffer + pos;
! 337: for(matchLen = 0; true; matchLen++)
! 338: {
! 339: *distances++ = back;
! 340: if (matchLen == currentLimit)
! 341: {
! 342: hashDescendant.MatchPointer = pos + kMatchStartValue;
! 343: return kNumHashBytes + matchLen;
! 344: }
! 345: if (buffer[matchLen] != buffer[(size_t)matchLen - backReal])
! 346: break;
! 347: }
! 348:
! 349: // UInt32 matchLen = GetMatchLen(kNumHashBytes, back, currentLimit);
! 350:
! 351: UInt32 fullMatchLen = matchLen + kNumHashBytes;
! 352: hashDescendant.NodePointer = m_FreeNode;
! 353: CNodePointer node = &m_Nodes[m_FreeNode];
! 354: m_FreeNode = node->NextFreeNode;
! 355: #ifdef __AUTO_REMOVE
! 356: m_NumUsedNodes++;
! 357: #endif
! 358: if (m_FreeNode > m_FreeNodeMax)
! 359: {
! 360: m_FreeNodeMax = m_FreeNode;
! 361: m_Nodes[m_FreeNode].NextFreeNode = m_FreeNode + 1;
! 362: }
! 363:
! 364: for (UInt32 i = 0; i < kNumSubNodes; i++)
! 365: node->Descendants[i].NodePointer = kDescendantEmptyValue;
! 366: node->LastMatch = pos;
! 367:
! 368: Byte byteNew = GetIndexByte(fullMatchLen);
! 369: Byte byteOld = GetIndexByte(fullMatchLen - backReal);
! 370: Byte bitsNew, bitsOld;
! 371: UInt32 numSameBits = matchLen * MY_BYTE_SIZE;
! 372: while (true)
! 373: {
! 374: bitsNew = (byteNew & kSubNodesMask);
! 375: bitsOld = (byteOld & kSubNodesMask);
! 376: if(bitsNew != bitsOld)
! 377: break;
! 378: byteNew >>= kNumSubBits;
! 379: byteOld >>= kNumSubBits;
! 380: numSameBits += kNumSubBits;
! 381: }
! 382: node->NumSameBits = CSameBitsType(numSameBits);
! 383: node->Descendants[bitsNew].MatchPointer = pos + kMatchStartValue;
! 384: node->Descendants[bitsOld].MatchPointer = matchPointer;
! 385: return fullMatchLen;
! 386: }
! 387: const Byte *baseCurrentBytePointer = _buffer + pos;
! 388: const Byte *currentBytePointer = baseCurrentBytePointer;
! 389: UInt32 numLoadedBits = 0;
! 390: Byte curByte = 0;
! 391: CIndex *nodePointerPointer = &hashDescendant.NodePointer;
! 392: CNodePointer node = &m_Nodes[*nodePointerPointer];
! 393: distances += kNumHashBytes;
! 394: const Byte *bytePointerLimit = baseCurrentBytePointer + currentLimit;
! 395: const Byte *currentAddingOffset = _buffer;
! 396:
! 397: #ifdef __AUTO_REMOVE
! 398: UInt32 lowPos;
! 399: if (pos > _sizeHistory)
! 400: lowPos = pos - _sizeHistory;
! 401: else
! 402: lowPos = 0;
! 403: #endif
! 404:
! 405: while(true)
! 406: {
! 407: #ifdef __AUTO_REMOVE
! 408: if (node->LastMatch < lowPos)
! 409: {
! 410: RemoveNode(*nodePointerPointer);
! 411: *nodePointerPointer = pos + kMatchStartValue;
! 412: if (currentBytePointer == baseCurrentBytePointer)
! 413: return kPrevHashSize;
! 414: return kNumHashBytes + (currentBytePointer - baseCurrentBytePointer - 1);
! 415: }
! 416: #endif
! 417: if(numLoadedBits == 0)
! 418: {
! 419: *distances++ = pos - node->LastMatch - 1;
! 420: if(currentBytePointer >= bytePointerLimit)
! 421: {
! 422: for (UInt32 i = 0; i < kNumSubNodes; i++)
! 423: node->Descendants[i].MatchPointer = pos + kMatchStartValue;
! 424: node->LastMatch = pos;
! 425: node->NumSameBits = 0;
! 426: return fullCurrentLimit;
! 427: }
! 428: curByte = (*currentBytePointer++);
! 429: currentAddingOffset++;
! 430: numLoadedBits = MY_BYTE_SIZE;
! 431: }
! 432: UInt32 numSameBits = node->NumSameBits;
! 433: if(numSameBits > 0)
! 434: {
! 435: Byte byteXOR = ((*(currentAddingOffset + node->LastMatch -1)) >>
! 436: (MY_BYTE_SIZE - numLoadedBits)) ^ curByte;
! 437: while(numLoadedBits <= numSameBits)
! 438: {
! 439: if(byteXOR != 0)
! 440: {
! 441: AddInternalNode(node, nodePointerPointer, curByte, byteXOR,
! 442: numSameBits, pos);
! 443: return kNumHashBytes + (currentBytePointer - baseCurrentBytePointer - 1);
! 444: }
! 445: *distances++ = pos - node->LastMatch - 1;
! 446: numSameBits -= numLoadedBits;
! 447: if(currentBytePointer >= bytePointerLimit)
! 448: {
! 449: for (UInt32 i = 0; i < kNumSubNodes; i++)
! 450: node->Descendants[i].MatchPointer = pos + kMatchStartValue;
! 451: node->LastMatch = pos;
! 452: node->NumSameBits = CSameBitsType(node->NumSameBits - numSameBits);
! 453: return fullCurrentLimit;
! 454: }
! 455: numLoadedBits = MY_BYTE_SIZE;
! 456: curByte = (*currentBytePointer++);
! 457: byteXOR = curByte ^ (*(currentAddingOffset + node->LastMatch));
! 458: currentAddingOffset++;
! 459: }
! 460: if((byteXOR & ((1 << numSameBits) - 1)) != 0)
! 461: {
! 462: AddInternalNode(node, nodePointerPointer, curByte, byteXOR,
! 463: numSameBits, pos);
! 464: return kNumHashBytes + (currentBytePointer - baseCurrentBytePointer - 1);
! 465: }
! 466: curByte >>= numSameBits;
! 467: numLoadedBits -= numSameBits;
! 468: }
! 469: UInt32 descendantIndex = (curByte & kSubNodesMask);
! 470: numLoadedBits -= kNumSubBits;
! 471: nodePointerPointer = &node->Descendants[descendantIndex].NodePointer;
! 472: UInt32 nextNodeIndex = *nodePointerPointer;
! 473: node->LastMatch = pos;
! 474: if (nextNodeIndex < kDescendantEmptyValue)
! 475: {
! 476: curByte >>= kNumSubBits;
! 477: node = &m_Nodes[nextNodeIndex];
! 478: }
! 479: else if (nextNodeIndex == kDescendantEmptyValue)
! 480: {
! 481: node->Descendants[descendantIndex].MatchPointer = pos + kMatchStartValue;
! 482: return kNumHashBytes + (currentBytePointer - baseCurrentBytePointer - 1);
! 483: }
! 484: else
! 485: break;
! 486: }
! 487:
! 488: UInt32 descendantIndex = (curByte & kSubNodesMask);
! 489: curByte >>= kNumSubBits;
! 490: CMatchPointer matchPointer = node->Descendants[descendantIndex].MatchPointer;
! 491: CMatchPointer realMatchPointer;
! 492: realMatchPointer = matchPointer - kMatchStartValue;
! 493:
! 494: #ifdef __AUTO_REMOVE
! 495: if (realMatchPointer < lowPos)
! 496: {
! 497: node->Descendants[descendantIndex].MatchPointer = pos + kMatchStartValue;
! 498: return kNumHashBytes + (currentBytePointer - baseCurrentBytePointer - 1);
! 499: }
! 500: #endif
! 501:
! 502: Byte byteXOR;
! 503: UInt32 numSameBits = 0;
! 504: if(numLoadedBits != 0)
! 505: {
! 506: Byte matchByte = *(currentAddingOffset + realMatchPointer -1);
! 507: matchByte >>= (MY_BYTE_SIZE - numLoadedBits);
! 508: byteXOR = matchByte ^ curByte;
! 509: if(byteXOR != 0)
! 510: {
! 511: AddLeafNode(node, curByte, byteXOR, numSameBits, pos, descendantIndex);
! 512: return kNumHashBytes + (currentBytePointer - baseCurrentBytePointer - 1);
! 513: }
! 514: numSameBits += numLoadedBits;
! 515: }
! 516:
! 517: const Byte *matchBytePointer = _buffer + realMatchPointer +
! 518: (currentBytePointer - baseCurrentBytePointer);
! 519: for(; currentBytePointer < bytePointerLimit; numSameBits += MY_BYTE_SIZE)
! 520: {
! 521: curByte = (*currentBytePointer++);
! 522: *distances++ = pos - realMatchPointer - 1;
! 523: byteXOR = curByte ^ (*matchBytePointer++);
! 524: if(byteXOR != 0)
! 525: {
! 526: AddLeafNode(node, curByte, byteXOR, numSameBits, pos, descendantIndex);
! 527: return kNumHashBytes + (currentBytePointer - baseCurrentBytePointer - 1);
! 528: }
! 529: }
! 530: *distances = pos - realMatchPointer - 1;
! 531: node->Descendants[descendantIndex].MatchPointer = pos + kMatchStartValue;
! 532:
! 533: if(*distances == 0)
! 534: {
! 535: m_SpecialMode = true;
! 536: m_NumNotChangedCycles = 0;
! 537: }
! 538: return fullCurrentLimit;
! 539: }
! 540:
! 541: STDMETHODIMP_(void) CPatricia::DummyLongestMatch()
! 542: {
! 543: GetLongestMatch(m_TmpBacks);
! 544: }
! 545:
! 546:
! 547: // ------------------------------------
! 548: // Remove Match
! 549:
! 550: typedef Byte CRemoveDataWord;
! 551:
! 552: static const int kSizeRemoveDataWordInBits = MY_BYTE_SIZE * sizeof(CRemoveDataWord);
! 553:
! 554: #ifndef __AUTO_REMOVE
! 555:
! 556: void CPatricia::RemoveMatch()
! 557: {
! 558: if(m_SpecialRemoveMode)
! 559: {
! 560: if(GetIndexByte(_matchMaxLen - 1 - _sizeHistory) ==
! 561: GetIndexByte(_matchMaxLen - _sizeHistory))
! 562: return;
! 563: m_SpecialRemoveMode = false;
! 564: }
! 565: UInt32 pos = _pos + kNumHashBytes - _sizeHistory;
! 566:
! 567: #ifdef __HASH_3
! 568: const Byte *pp = _buffer + _pos - _sizeHistory;
! 569: UInt32 hash2Value = ((UInt32(pp[0])) << 8) | pp[1];
! 570: UInt32 hashValue = (hash2Value << 8) | pp[2];
! 571: CDescendant &hashDescendant = m_HashDescendants[hashValue];
! 572: CDescendant &hash2Descendant = m_Hash2Descendants[hash2Value];
! 573: if (hash2Descendant >= kMatchStartValue2)
! 574: if(hash2Descendant.MatchPointer == pos + kMatchStartValue2)
! 575: hash2Descendant.MatchPointer = kDescendantEmptyValue2;
! 576: #else
! 577: UInt32 hashValue = UInt32(GetIndexByte(1 - _sizeHistory)) |
! 578: (UInt32(GetIndexByte(0 - _sizeHistory)) << 8);
! 579: CDescendant &hashDescendant = m_HashDescendants[hashValue];
! 580: #endif
! 581:
! 582: if(hashDescendant.IsEmpty())
! 583: return;
! 584: if(hashDescendant.IsMatch())
! 585: {
! 586: if(hashDescendant.MatchPointer == pos + kMatchStartValue)
! 587: hashDescendant.MakeEmpty();
! 588: return;
! 589: }
! 590:
! 591: UInt32 descendantIndex;
! 592: const CRemoveDataWord *currentPointer = (const CRemoveDataWord *)(_buffer + pos);
! 593: UInt32 numLoadedBits = 0;
! 594: CRemoveDataWord curWord = 0; // = 0 to disable GCC warning
! 595:
! 596: CIndex *nodePointerPointer = &hashDescendant.NodePointer;
! 597:
! 598: CNodePointer node = &m_Nodes[hashDescendant.NodePointer];
! 599:
! 600: while(true)
! 601: {
! 602: if(numLoadedBits == 0)
! 603: {
! 604: curWord = *currentPointer++;
! 605: numLoadedBits = kSizeRemoveDataWordInBits;
! 606: }
! 607: UInt32 numSameBits = node->NumSameBits;
! 608: if(numSameBits > 0)
! 609: {
! 610: if (numLoadedBits <= numSameBits)
! 611: {
! 612: numSameBits -= numLoadedBits;
! 613: currentPointer += (numSameBits / kSizeRemoveDataWordInBits);
! 614: numSameBits %= kSizeRemoveDataWordInBits;
! 615: curWord = *currentPointer++;
! 616: numLoadedBits = kSizeRemoveDataWordInBits;
! 617: }
! 618: curWord >>= numSameBits;
! 619: numLoadedBits -= numSameBits;
! 620: }
! 621: descendantIndex = (curWord & kSubNodesMask);
! 622: numLoadedBits -= kNumSubBits;
! 623: curWord >>= kNumSubBits;
! 624: UInt32 nextNodeIndex = node->Descendants[descendantIndex].NodePointer;
! 625: if (nextNodeIndex < kDescendantEmptyValue)
! 626: {
! 627: nodePointerPointer = &node->Descendants[descendantIndex].NodePointer;
! 628: node = &m_Nodes[nextNodeIndex];
! 629: }
! 630: else
! 631: break;
! 632: }
! 633: if (node->Descendants[descendantIndex].MatchPointer != pos + kMatchStartValue)
! 634: {
! 635: const Byte *currentBytePointer = _buffer + _pos - _sizeHistory;
! 636: const Byte *currentBytePointerLimit = currentBytePointer + _matchMaxLen;
! 637: for(;currentBytePointer < currentBytePointerLimit; currentBytePointer++)
! 638: if(*currentBytePointer != *(currentBytePointer+1))
! 639: return;
! 640: m_SpecialRemoveMode = true;
! 641: return;
! 642: }
! 643:
! 644: UInt32 numNodes = 0, numMatches = 0;
! 645:
! 646: UInt32 i;
! 647: for (i = 0; i < kNumSubNodes; i++)
! 648: {
! 649: UInt32 nodeIndex = node->Descendants[i].NodePointer;
! 650: if (nodeIndex < kDescendantEmptyValue)
! 651: numNodes++;
! 652: else if (nodeIndex > kDescendantEmptyValue)
! 653: numMatches++;
! 654: }
! 655: numMatches -= 1;
! 656: if (numNodes + numMatches > 1)
! 657: {
! 658: node->Descendants[descendantIndex].MakeEmpty();
! 659: return;
! 660: }
! 661: if(numNodes == 1)
! 662: {
! 663: UInt32 i;
! 664: for (i = 0; i < kNumSubNodes; i++)
! 665: if (node->Descendants[i].IsNode())
! 666: break;
! 667: UInt32 nextNodeIndex = node->Descendants[i].NodePointer;
! 668: CNodePointer nextNode = &m_Nodes[nextNodeIndex];
! 669: nextNode->NumSameBits += node->NumSameBits + kNumSubBits;
! 670: *node = *nextNode;
! 671:
! 672: nextNode->NextFreeNode = m_FreeNode;
! 673: m_FreeNode = nextNodeIndex;
! 674: return;
! 675: }
! 676: UInt32 matchPointer = 0; // = 0 to disable GCC warning
! 677: for (i = 0; i < kNumSubNodes; i++)
! 678: if (node->Descendants[i].IsMatch() && i != descendantIndex)
! 679: {
! 680: matchPointer = node->Descendants[i].MatchPointer;
! 681: break;
! 682: }
! 683: node->NextFreeNode = m_FreeNode;
! 684: m_FreeNode = *nodePointerPointer;
! 685: *nodePointerPointer = matchPointer;
! 686: }
! 687: #endif
! 688:
! 689:
! 690: // Commented code is more correct, but it gives warning
! 691: // on GCC: (1 << 32)
! 692: // So we use kMatchStartValue twice:
! 693: // kMatchStartValue = UInt32(1) << (kNumBitsInIndex - 1);
! 694: // must be defined in Pat.h
! 695: /*
! 696: const UInt32 kNormalizeStartPos = (UInt32(1) << (kNumBitsInIndex)) -
! 697: kMatchStartValue - kNumHashBytes - 1;
! 698: */
! 699: const UInt32 kNormalizeStartPos = kMatchStartValue - kNumHashBytes - 1;
! 700:
! 701: STDMETHODIMP CPatricia::MovePos()
! 702: {
! 703: #ifndef __AUTO_REMOVE
! 704: if(_pos >= _sizeHistory)
! 705: RemoveMatch();
! 706: #endif
! 707: RINOK(CLZInWindow::MovePos());
! 708: #ifdef __AUTO_REMOVE
! 709: if (m_NumUsedNodes >= m_NumNodes)
! 710: TestRemoveNodes();
! 711: #endif
! 712: if (_pos >= kNormalizeStartPos)
! 713: {
! 714: #ifdef __AUTO_REMOVE
! 715: TestRemoveNodesAndNormalize();
! 716: #else
! 717: Normalize();
! 718: #endif
! 719: }
! 720: return S_OK;
! 721: }
! 722:
! 723: #ifndef __AUTO_REMOVE
! 724:
! 725: void CPatricia::NormalizeDescendant(CDescendant &descendant, UInt32 subValue)
! 726: {
! 727: if (descendant.IsEmpty())
! 728: return;
! 729: if (descendant.IsMatch())
! 730: descendant.MatchPointer = descendant.MatchPointer - subValue;
! 731: else
! 732: {
! 733: CNode &node = m_Nodes[descendant.NodePointer];
! 734: node.LastMatch = node.LastMatch - subValue;
! 735: for (UInt32 i = 0; i < kNumSubNodes; i++)
! 736: NormalizeDescendant(node.Descendants[i], subValue);
! 737: }
! 738: }
! 739:
! 740: void CPatricia::Normalize()
! 741: {
! 742: UInt32 subValue = _pos - _sizeHistory;
! 743: CLZInWindow::ReduceOffsets(subValue);
! 744:
! 745: #ifdef __HASH_3
! 746:
! 747: for(UInt32 hash = 0; hash < kHash2Size; hash++)
! 748: {
! 749: CDescendant &descendant = m_Hash2Descendants[hash];
! 750: if (descendant.MatchPointer != kDescendantsNotInitilized2)
! 751: {
! 752: UInt32 base = hash << 8;
! 753: for (UInt32 i = 0; i < 0x100; i++)
! 754: NormalizeDescendant(m_HashDescendants[base + i], subValue);
! 755: }
! 756: if (descendant.MatchPointer < kMatchStartValue2)
! 757: continue;
! 758: descendant.MatchPointer = descendant.MatchPointer - subValue;
! 759: }
! 760:
! 761: #else
! 762:
! 763: for(UInt32 hash = 0; hash < kHashSize; hash++)
! 764: NormalizeDescendant(m_HashDescendants[hash], subValue);
! 765:
! 766: #endif
! 767:
! 768: }
! 769:
! 770: #else
! 771:
! 772: void CPatricia::TestRemoveDescendant(CDescendant &descendant, UInt32 limitPos)
! 773: {
! 774: CNode &node = m_Nodes[descendant.NodePointer];
! 775: UInt32 numChilds = 0;
! 776: UInt32 childIndex = 0; // = 0 to disable GCC warning
! 777: for (UInt32 i = 0; i < kNumSubNodes; i++)
! 778: {
! 779: CDescendant &descendant2 = node.Descendants[i];
! 780: if (descendant2.IsEmpty())
! 781: continue;
! 782: if (descendant2.IsMatch())
! 783: {
! 784: if (descendant2.MatchPointer < limitPos)
! 785: descendant2.MakeEmpty();
! 786: else
! 787: {
! 788: numChilds++;
! 789: childIndex = i;
! 790: }
! 791: }
! 792: else
! 793: {
! 794: TestRemoveDescendant(descendant2, limitPos);
! 795: if (!descendant2.IsEmpty())
! 796: {
! 797: numChilds++;
! 798: childIndex = i;
! 799: }
! 800: }
! 801: }
! 802: if (numChilds > 1)
! 803: return;
! 804:
! 805: CIndex nodePointerTemp = descendant.NodePointer;
! 806: if (numChilds == 1)
! 807: {
! 808: const CDescendant &descendant2 = node.Descendants[childIndex];
! 809: if (descendant2.IsNode())
! 810: m_Nodes[descendant2.NodePointer].NumSameBits += node.NumSameBits + kNumSubBits;
! 811: descendant = descendant2;
! 812: }
! 813: else
! 814: descendant.MakeEmpty();
! 815: node.NextFreeNode = m_FreeNode;
! 816: m_FreeNode = nodePointerTemp;
! 817: m_NumUsedNodes--;
! 818: }
! 819:
! 820: void CPatricia::RemoveNode(UInt32 index)
! 821: {
! 822: CNode &node = m_Nodes[index];
! 823: for (UInt32 i = 0; i < kNumSubNodes; i++)
! 824: {
! 825: CDescendant &descendant2 = node.Descendants[i];
! 826: if (descendant2.IsNode())
! 827: RemoveNode(descendant2.NodePointer);
! 828: }
! 829: node.NextFreeNode = m_FreeNode;
! 830: m_FreeNode = index;
! 831: m_NumUsedNodes--;
! 832: }
! 833:
! 834: void CPatricia::TestRemoveNodes()
! 835: {
! 836: UInt32 limitPos = kMatchStartValue + _pos - _sizeHistory + kNumHashBytes;
! 837:
! 838: #ifdef __HASH_3
! 839:
! 840: UInt32 limitPos2 = kMatchStartValue2 + _pos - _sizeHistory + kNumHashBytes;
! 841: for(UInt32 hash = 0; hash < kHash2Size; hash++)
! 842: {
! 843: CDescendant &descendant = m_Hash2Descendants[hash];
! 844: if (descendant.MatchPointer != kDescendantsNotInitilized2)
! 845: {
! 846: UInt32 base = hash << 8;
! 847: for (UInt32 i = 0; i < 0x100; i++)
! 848: {
! 849: CDescendant &descendant = m_HashDescendants[base + i];
! 850: if (descendant.IsEmpty())
! 851: continue;
! 852: if (descendant.IsMatch())
! 853: {
! 854: if (descendant.MatchPointer < limitPos)
! 855: descendant.MakeEmpty();
! 856: }
! 857: else
! 858: TestRemoveDescendant(descendant, limitPos);
! 859: }
! 860: }
! 861: if (descendant.MatchPointer < kMatchStartValue2)
! 862: continue;
! 863: if (descendant.MatchPointer < limitPos2)
! 864: descendant.MatchPointer = kDescendantEmptyValue2;
! 865: }
! 866:
! 867: #else
! 868:
! 869: for(UInt32 hash = 0; hash < kHashSize; hash++)
! 870: {
! 871: CDescendant &descendant = m_HashDescendants[hash];
! 872: if (descendant.IsEmpty())
! 873: continue;
! 874: if (descendant.IsMatch())
! 875: {
! 876: if (descendant.MatchPointer < limitPos)
! 877: descendant.MakeEmpty();
! 878: }
! 879: else
! 880: TestRemoveDescendant(descendant, limitPos);
! 881: }
! 882:
! 883: #endif
! 884: }
! 885:
! 886: void CPatricia::TestRemoveAndNormalizeDescendant(CDescendant &descendant,
! 887: UInt32 limitPos, UInt32 subValue)
! 888: {
! 889: if (descendant.IsEmpty())
! 890: return;
! 891: if (descendant.IsMatch())
! 892: {
! 893: if (descendant.MatchPointer < limitPos)
! 894: descendant.MakeEmpty();
! 895: else
! 896: descendant.MatchPointer = descendant.MatchPointer - subValue;
! 897: return;
! 898: }
! 899: CNode &node = m_Nodes[descendant.NodePointer];
! 900: UInt32 numChilds = 0;
! 901: UInt32 childIndex = 0; // = 0 to disable GCC warning
! 902: for (UInt32 i = 0; i < kNumSubNodes; i++)
! 903: {
! 904: CDescendant &descendant2 = node.Descendants[i];
! 905: TestRemoveAndNormalizeDescendant(descendant2, limitPos, subValue);
! 906: if (!descendant2.IsEmpty())
! 907: {
! 908: numChilds++;
! 909: childIndex = i;
! 910: }
! 911: }
! 912: if (numChilds > 1)
! 913: {
! 914: node.LastMatch = node.LastMatch - subValue;
! 915: return;
! 916: }
! 917:
! 918: CIndex nodePointerTemp = descendant.NodePointer;
! 919: if (numChilds == 1)
! 920: {
! 921: const CDescendant &descendant2 = node.Descendants[childIndex];
! 922: if (descendant2.IsNode())
! 923: m_Nodes[descendant2.NodePointer].NumSameBits += node.NumSameBits + kNumSubBits;
! 924: descendant = descendant2;
! 925: }
! 926: else
! 927: descendant.MakeEmpty();
! 928: node.NextFreeNode = m_FreeNode;
! 929: m_FreeNode = nodePointerTemp;
! 930: m_NumUsedNodes--;
! 931: }
! 932:
! 933: void CPatricia::TestRemoveNodesAndNormalize()
! 934: {
! 935: UInt32 subValue = _pos - _sizeHistory;
! 936: UInt32 limitPos = kMatchStartValue + _pos - _sizeHistory + kNumHashBytes;
! 937: CLZInWindow::ReduceOffsets(subValue);
! 938:
! 939: #ifdef __HASH_3
! 940:
! 941: UInt32 limitPos2 = kMatchStartValue2 + _pos - _sizeHistory + kNumHashBytes;
! 942: for(UInt32 hash = 0; hash < kHash2Size; hash++)
! 943: {
! 944: CDescendant &descendant = m_Hash2Descendants[hash];
! 945: if (descendant.MatchPointer != kDescendantsNotInitilized2)
! 946: {
! 947: UInt32 base = hash << 8;
! 948: for (UInt32 i = 0; i < 0x100; i++)
! 949: TestRemoveAndNormalizeDescendant(m_HashDescendants[base + i], limitPos, subValue);
! 950: }
! 951: if (descendant.MatchPointer < kMatchStartValue2)
! 952: continue;
! 953: if (descendant.MatchPointer < limitPos2)
! 954: descendant.MatchPointer = kDescendantEmptyValue2;
! 955: else
! 956: descendant.MatchPointer = descendant.MatchPointer - subValue;
! 957: }
! 958:
! 959: #else
! 960:
! 961: for(UInt32 hash = 0; hash < kHashSize; hash++)
! 962: TestRemoveAndNormalizeDescendant(m_HashDescendants[hash], limitPos, subValue);
! 963:
! 964: #endif
! 965: }
! 966:
! 967: #endif
! 968:
! 969: STDMETHODIMP_(Byte) CPatricia::GetIndexByte(Int32 index)
! 970: {
! 971: return CLZInWindow::GetIndexByte(index);
! 972: }
! 973:
! 974: STDMETHODIMP_(UInt32) CPatricia::GetMatchLen(Int32 index, UInt32 back, UInt32 limit)
! 975: {
! 976: return CLZInWindow::GetMatchLen(index, back, limit);
! 977: }
! 978:
! 979: STDMETHODIMP_(UInt32) CPatricia::GetNumAvailableBytes()
! 980: {
! 981: return CLZInWindow::GetNumAvailableBytes();
! 982: }
! 983:
! 984: STDMETHODIMP_(const Byte *) CPatricia::GetPointerToCurrentPos()
! 985: {
! 986: return CLZInWindow::GetPointerToCurrentPos();
! 987: }
! 988:
! 989: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>