Annotation of elwix/tools/oldlzma/SRC/7zip/Compress/LZ/BinTree/BinTreeMain.h, revision 1.1
1.1 ! misho 1: // BinTreeMain.h
! 2:
! 3: #include "../../../../Common/Defs.h"
! 4: #include "../../../../Common/CRC.h"
! 5: #include "../../../../Common/Alloc.h"
! 6:
! 7: namespace BT_NAMESPACE {
! 8:
! 9: #ifdef HASH_ARRAY_2
! 10: static const UInt32 kHash2Size = 1 << 10;
! 11: #ifdef HASH_ARRAY_3
! 12: static const UInt32 kNumHashDirectBytes = 0;
! 13: static const UInt32 kNumHashBytes = 4;
! 14: static const UInt32 kHash3Size = 1 << 18;
! 15: #ifdef HASH_BIG
! 16: static const UInt32 kHashSize = 1 << 23;
! 17: #else
! 18: static const UInt32 kHashSize = 1 << 20;
! 19: #endif
! 20: #else
! 21: static const UInt32 kNumHashDirectBytes = 3;
! 22: static const UInt32 kNumHashBytes = 3;
! 23: static const UInt32 kHashSize = 1 << (8 * kNumHashBytes);
! 24: #endif
! 25: #else
! 26: #ifdef HASH_ZIP
! 27: static const UInt32 kNumHashDirectBytes = 0;
! 28: static const UInt32 kNumHashBytes = 3;
! 29: static const UInt32 kHashSize = 1 << 16;
! 30: #else
! 31: #define THERE_ARE_DIRECT_HASH_BYTES
! 32: static const UInt32 kNumHashDirectBytes = 2;
! 33: static const UInt32 kNumHashBytes = 2;
! 34: static const UInt32 kHashSize = 1 << (8 * kNumHashBytes);
! 35: #endif
! 36: #endif
! 37:
! 38: static const UInt32 kHashSizeSum = kHashSize
! 39: #ifdef HASH_ARRAY_2
! 40: + kHash2Size
! 41: #ifdef HASH_ARRAY_3
! 42: + kHash3Size
! 43: #endif
! 44: #endif
! 45: ;
! 46:
! 47: #ifdef HASH_ARRAY_2
! 48: static const UInt32 kHash2Offset = kHashSize;
! 49: #ifdef HASH_ARRAY_3
! 50: static const UInt32 kHash3Offset = kHashSize + kHash2Size;
! 51: #endif
! 52: #endif
! 53:
! 54: CMatchFinderBinTree::CMatchFinderBinTree():
! 55: _hash(0),
! 56: _cutValue(0xFF)
! 57: {
! 58: }
! 59:
! 60: void CMatchFinderBinTree::FreeThisClassMemory()
! 61: {
! 62: BigFree(_hash);
! 63: _hash = 0;
! 64: }
! 65:
! 66: void CMatchFinderBinTree::FreeMemory()
! 67: {
! 68: FreeThisClassMemory();
! 69: CLZInWindow::Free();
! 70: }
! 71:
! 72: CMatchFinderBinTree::~CMatchFinderBinTree()
! 73: {
! 74: FreeMemory();
! 75: }
! 76:
! 77: STDMETHODIMP CMatchFinderBinTree::Create(UInt32 historySize, UInt32 keepAddBufferBefore,
! 78: UInt32 matchMaxLen, UInt32 keepAddBufferAfter)
! 79: {
! 80: UInt32 sizeReserv = (historySize + keepAddBufferBefore +
! 81: matchMaxLen + keepAddBufferAfter) / 2 + 256;
! 82: if (CLZInWindow::Create(historySize + keepAddBufferBefore,
! 83: matchMaxLen + keepAddBufferAfter, sizeReserv))
! 84: {
! 85: if (historySize + 256 > kMaxValForNormalize)
! 86: {
! 87: FreeMemory();
! 88: return E_INVALIDARG;
! 89: }
! 90: _matchMaxLen = matchMaxLen;
! 91: UInt32 newCyclicBufferSize = historySize + 1;
! 92: if (_hash != 0 && newCyclicBufferSize == _cyclicBufferSize)
! 93: return S_OK;
! 94: FreeThisClassMemory();
! 95: _cyclicBufferSize = newCyclicBufferSize; // don't change it
! 96: _hash = (CIndex *)BigAlloc((kHashSizeSum + _cyclicBufferSize * 2) * sizeof(CIndex));
! 97: if (_hash != 0)
! 98: return S_OK;
! 99: }
! 100: FreeMemory();
! 101: return E_OUTOFMEMORY;
! 102: }
! 103:
! 104: static const UInt32 kEmptyHashValue = 0;
! 105:
! 106: STDMETHODIMP CMatchFinderBinTree::Init(ISequentialInStream *stream)
! 107: {
! 108: RINOK(CLZInWindow::Init(stream));
! 109: for(UInt32 i = 0; i < kHashSizeSum; i++)
! 110: _hash[i] = kEmptyHashValue;
! 111: _cyclicBufferPos = 0;
! 112: ReduceOffsets(-1);
! 113: return S_OK;
! 114: }
! 115:
! 116: STDMETHODIMP_(void) CMatchFinderBinTree::ReleaseStream()
! 117: {
! 118: // ReleaseStream();
! 119: }
! 120:
! 121: #ifdef HASH_ARRAY_2
! 122: #ifdef HASH_ARRAY_3
! 123: inline UInt32 Hash(const Byte *pointer, UInt32 &hash2Value, UInt32 &hash3Value)
! 124: {
! 125: UInt32 temp = CCRC::Table[pointer[0]] ^ pointer[1];
! 126: hash2Value = temp & (kHash2Size - 1);
! 127: hash3Value = (temp ^ (UInt32(pointer[2]) << 8)) & (kHash3Size - 1);
! 128: return (temp ^ (UInt32(pointer[2]) << 8) ^ (CCRC::Table[pointer[3]] << 5)) &
! 129: (kHashSize - 1);
! 130: }
! 131: #else // no HASH_ARRAY_3
! 132: inline UInt32 Hash(const Byte *pointer, UInt32 &hash2Value)
! 133: {
! 134: hash2Value = (CCRC::Table[pointer[0]] ^ pointer[1]) & (kHash2Size - 1);
! 135: return ((UInt32(pointer[0]) << 16)) | ((UInt32(pointer[1]) << 8)) | pointer[2];
! 136: }
! 137: #endif // HASH_ARRAY_3
! 138: #else // no HASH_ARRAY_2
! 139: #ifdef HASH_ZIP
! 140: inline UInt32 Hash(const Byte *pointer)
! 141: {
! 142: return ((UInt32(pointer[0]) << 8) ^
! 143: CCRC::Table[pointer[1]] ^ pointer[2]) & (kHashSize - 1);
! 144: }
! 145: #else // no HASH_ZIP
! 146: inline UInt32 Hash(const Byte *pointer)
! 147: {
! 148: return pointer[0] ^ (UInt32(pointer[1]) << 8);
! 149: }
! 150: #endif // HASH_ZIP
! 151: #endif // HASH_ARRAY_2
! 152:
! 153: STDMETHODIMP_(UInt32) CMatchFinderBinTree::GetLongestMatch(UInt32 *distances)
! 154: {
! 155: UInt32 lenLimit;
! 156: if (_pos + _matchMaxLen <= _streamPos)
! 157: lenLimit = _matchMaxLen;
! 158: else
! 159: {
! 160: lenLimit = _streamPos - _pos;
! 161: if(lenLimit < kNumHashBytes)
! 162: return 0;
! 163: }
! 164:
! 165: UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
! 166: Byte *cur = _buffer + _pos;
! 167:
! 168: UInt32 maxLen = 0;
! 169:
! 170: #ifdef HASH_ARRAY_2
! 171: UInt32 hash2Value;
! 172: #ifdef HASH_ARRAY_3
! 173: UInt32 hash3Value;
! 174: UInt32 hashValue = Hash(cur, hash2Value, hash3Value);
! 175: #else
! 176: UInt32 hashValue = Hash(cur, hash2Value);
! 177: #endif
! 178: #else
! 179: UInt32 hashValue = Hash(cur);
! 180: #endif
! 181:
! 182: UInt32 curMatch = _hash[hashValue];
! 183: #ifdef HASH_ARRAY_2
! 184: UInt32 curMatch2 = _hash[kHash2Offset + hash2Value];
! 185: #ifdef HASH_ARRAY_3
! 186: UInt32 curMatch3 = _hash[kHash3Offset + hash3Value];
! 187: #endif
! 188: _hash[kHash2Offset + hash2Value] = _pos;
! 189: distances[2] = 0xFFFFFFFF;
! 190: if(curMatch2 > matchMinPos)
! 191: if (_buffer[curMatch2] == cur[0])
! 192: {
! 193: distances[2] = _pos - curMatch2 - 1;
! 194: maxLen = 2;
! 195: }
! 196:
! 197: #ifdef HASH_ARRAY_3
! 198: _hash[kHash3Offset + hash3Value] = _pos;
! 199: distances[3] = 0xFFFFFFFF;
! 200: if(curMatch3 > matchMinPos)
! 201: if (_buffer[curMatch3] == cur[0])
! 202: {
! 203: distances[3] = _pos - curMatch3 - 1;
! 204: maxLen = 3;
! 205: }
! 206: #endif
! 207: #endif
! 208:
! 209: _hash[hashValue] = _pos;
! 210:
! 211: CIndex *son = _hash + kHashSizeSum;
! 212: CIndex *ptr0 = son + (_cyclicBufferPos << 1) + 1;
! 213: CIndex *ptr1 = son + (_cyclicBufferPos << 1);
! 214:
! 215: distances[kNumHashBytes] = 0xFFFFFFFF;
! 216:
! 217: #ifdef THERE_ARE_DIRECT_HASH_BYTES
! 218: if (lenLimit == kNumHashDirectBytes)
! 219: {
! 220: if(curMatch > matchMinPos)
! 221: while (maxLen < kNumHashDirectBytes)
! 222: distances[++maxLen] = _pos - curMatch - 1;
! 223: // We don't need tree in this case
! 224: }
! 225: else
! 226: #endif
! 227: {
! 228: UInt32 len0, len1;
! 229: len0 = len1 = kNumHashDirectBytes;
! 230: UInt32 count = _cutValue;
! 231: while(true)
! 232: {
! 233: if(curMatch <= matchMinPos || count-- == 0)
! 234: {
! 235: *ptr0 = kEmptyHashValue;
! 236: *ptr1 = kEmptyHashValue;
! 237: break;
! 238: }
! 239: Byte *pb = _buffer + curMatch;
! 240: UInt32 len = MyMin(len0, len1);
! 241: do
! 242: {
! 243: if (pb[len] != cur[len])
! 244: break;
! 245: }
! 246: while(++len != lenLimit);
! 247:
! 248: UInt32 delta = _pos - curMatch;
! 249: while (maxLen < len)
! 250: distances[++maxLen] = delta - 1;
! 251:
! 252: UInt32 cyclicPos = (delta <= _cyclicBufferPos) ?
! 253: (_cyclicBufferPos - delta):
! 254: (_cyclicBufferPos - delta + _cyclicBufferSize);
! 255: CIndex *pair = son + (cyclicPos << 1);
! 256:
! 257: if (len != lenLimit)
! 258: {
! 259: if (pb[len] < cur[len])
! 260: {
! 261: *ptr1 = curMatch;
! 262: ptr1 = pair + 1;
! 263: curMatch = *ptr1;
! 264: len1 = len;
! 265: }
! 266: else
! 267: {
! 268: *ptr0 = curMatch;
! 269: ptr0 = pair;
! 270: curMatch = *ptr0;
! 271: len0 = len;
! 272: }
! 273: }
! 274: else
! 275: {
! 276: *ptr1 = pair[0];
! 277: *ptr0 = pair[1];
! 278: break;
! 279: }
! 280: }
! 281: }
! 282: #ifdef HASH_ARRAY_2
! 283: #ifdef HASH_ARRAY_3
! 284: if (distances[4] < distances[3])
! 285: distances[3] = distances[4];
! 286: #endif
! 287: if (distances[3] < distances[2])
! 288: distances[2] = distances[3];
! 289: #endif
! 290: return maxLen;
! 291: }
! 292:
! 293: STDMETHODIMP_(void) CMatchFinderBinTree::DummyLongestMatch()
! 294: {
! 295: UInt32 lenLimit;
! 296: if (_pos + _matchMaxLen <= _streamPos)
! 297: lenLimit = _matchMaxLen;
! 298: else
! 299: {
! 300: lenLimit = _streamPos - _pos;
! 301: if(lenLimit < kNumHashBytes)
! 302: return;
! 303: }
! 304: UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
! 305: Byte *cur = _buffer + _pos;
! 306:
! 307: #ifdef HASH_ARRAY_2
! 308: UInt32 hash2Value;
! 309: #ifdef HASH_ARRAY_3
! 310: UInt32 hash3Value;
! 311: UInt32 hashValue = Hash(cur, hash2Value, hash3Value);
! 312: _hash[kHash3Offset + hash3Value] = _pos;
! 313: #else
! 314: UInt32 hashValue = Hash(cur, hash2Value);
! 315: #endif
! 316: _hash[kHash2Offset + hash2Value] = _pos;
! 317: #else
! 318: UInt32 hashValue = Hash(cur);
! 319: #endif
! 320:
! 321: UInt32 curMatch = _hash[hashValue];
! 322: _hash[hashValue] = _pos;
! 323:
! 324: CIndex *son = _hash + kHashSizeSum;
! 325: CIndex *ptr0 = son + (_cyclicBufferPos << 1) + 1;
! 326: CIndex *ptr1 = son + (_cyclicBufferPos << 1);
! 327:
! 328: #ifdef THERE_ARE_DIRECT_HASH_BYTES
! 329: if (lenLimit != kNumHashDirectBytes)
! 330: #endif
! 331: {
! 332: UInt32 len0, len1;
! 333: len0 = len1 = kNumHashDirectBytes;
! 334: UInt32 count = _cutValue;
! 335: while(true)
! 336: {
! 337: if(curMatch <= matchMinPos || count-- == 0)
! 338: break;
! 339: Byte *pb = _buffer + curMatch;
! 340: UInt32 len = MyMin(len0, len1);
! 341: do
! 342: {
! 343: if (pb[len] != cur[len])
! 344: break;
! 345: }
! 346: while(++len != lenLimit);
! 347:
! 348: UInt32 delta = _pos - curMatch;
! 349: UInt32 cyclicPos = (delta <= _cyclicBufferPos) ?
! 350: (_cyclicBufferPos - delta):
! 351: (_cyclicBufferPos - delta + _cyclicBufferSize);
! 352: CIndex *pair = son + (cyclicPos << 1);
! 353:
! 354: if (len != lenLimit)
! 355: {
! 356: if (pb[len] < cur[len])
! 357: {
! 358: *ptr1 = curMatch;
! 359: ptr1 = pair + 1;
! 360: curMatch = *ptr1;
! 361: len1 = len;
! 362: }
! 363: else
! 364: {
! 365: *ptr0 = curMatch;
! 366: ptr0 = pair;
! 367: curMatch = *ptr0;
! 368: len0 = len;
! 369: }
! 370: }
! 371: else
! 372: {
! 373: *ptr1 = pair[0];
! 374: *ptr0 = pair[1];
! 375: return;
! 376: }
! 377: }
! 378: }
! 379: *ptr0 = kEmptyHashValue;
! 380: *ptr1 = kEmptyHashValue;
! 381: }
! 382:
! 383: void CMatchFinderBinTree::Normalize()
! 384: {
! 385: UInt32 subValue = _pos - _cyclicBufferSize;
! 386: CIndex *items = _hash;
! 387: UInt32 numItems = (kHashSizeSum + _cyclicBufferSize * 2);
! 388: for (UInt32 i = 0; i < numItems; i++)
! 389: {
! 390: UInt32 value = items[i];
! 391: if (value <= subValue)
! 392: value = kEmptyHashValue;
! 393: else
! 394: value -= subValue;
! 395: items[i] = value;
! 396: }
! 397: ReduceOffsets(subValue);
! 398: }
! 399:
! 400: STDMETHODIMP CMatchFinderBinTree::MovePos()
! 401: {
! 402: if (++_cyclicBufferPos == _cyclicBufferSize)
! 403: _cyclicBufferPos = 0;
! 404: RINOK(CLZInWindow::MovePos());
! 405: if (_pos == kMaxValForNormalize)
! 406: Normalize();
! 407: return S_OK;
! 408: }
! 409:
! 410: STDMETHODIMP_(Byte) CMatchFinderBinTree::GetIndexByte(Int32 index)
! 411: { return CLZInWindow::GetIndexByte(index); }
! 412:
! 413: STDMETHODIMP_(UInt32) CMatchFinderBinTree::GetMatchLen(Int32 index,
! 414: UInt32 back, UInt32 limit)
! 415: { return CLZInWindow::GetMatchLen(index, back, limit); }
! 416:
! 417: STDMETHODIMP_(UInt32) CMatchFinderBinTree::GetNumAvailableBytes()
! 418: { return CLZInWindow::GetNumAvailableBytes(); }
! 419:
! 420: STDMETHODIMP_(const Byte *) CMatchFinderBinTree::GetPointerToCurrentPos()
! 421: { return CLZInWindow::GetPointerToCurrentPos(); }
! 422:
! 423: // IMatchFinderSetCallback
! 424: STDMETHODIMP CMatchFinderBinTree::SetCallback(IMatchFinderCallback *callback)
! 425: {
! 426: m_Callback = callback;
! 427: return S_OK;
! 428: }
! 429:
! 430: void CMatchFinderBinTree::BeforeMoveBlock()
! 431: {
! 432: if (m_Callback)
! 433: m_Callback->BeforeChangingBufferPos();
! 434: CLZInWindow::BeforeMoveBlock();
! 435: }
! 436:
! 437: void CMatchFinderBinTree::AfterMoveBlock()
! 438: {
! 439: if (m_Callback)
! 440: m_Callback->AfterChangingBufferPos();
! 441: CLZInWindow::AfterMoveBlock();
! 442: }
! 443:
! 444: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>