Annotation of elwix/tools/oldlzma/SRC/7zip/Compress/LZ/HashChain/HCMain.h, revision 1.1
1.1 ! misho 1: // HC.h
! 2:
! 3: #include "../../../../Common/Defs.h"
! 4: #include "../../../../Common/CRC.h"
! 5: #include "../../../../Common/Alloc.h"
! 6:
! 7: namespace HC_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 = 0;
! 22: static const UInt32 kNumHashBytes = 3;
! 23: static const UInt32 kHashSize = 1 << (16);
! 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: CMatchFinderHC::CMatchFinderHC():
! 55: _hash(0),
! 56: _cutValue(16)
! 57: {
! 58: }
! 59:
! 60: void CMatchFinderHC::FreeThisClassMemory()
! 61: {
! 62: BigFree(_hash);
! 63: _hash = 0;
! 64: }
! 65:
! 66: void CMatchFinderHC::FreeMemory()
! 67: {
! 68: FreeThisClassMemory();
! 69: CLZInWindow::Free();
! 70: }
! 71:
! 72: CMatchFinderHC::~CMatchFinderHC()
! 73: {
! 74: FreeMemory();
! 75: }
! 76:
! 77: STDMETHODIMP CMatchFinderHC::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) * 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 CMatchFinderHC::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) CMatchFinderHC::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: UInt32 temp = CCRC::Table[pointer[0]] ^ pointer[1];
! 135: hash2Value = temp & (kHash2Size - 1);
! 136: return (temp ^ (UInt32(pointer[2]) << 8)) & (kHashSize - 1);;
! 137: }
! 138: #endif // HASH_ARRAY_3
! 139: #else // no HASH_ARRAY_2
! 140: #ifdef HASH_ZIP
! 141: inline UInt32 Hash(const Byte *pointer)
! 142: {
! 143: return ((UInt32(pointer[0]) << 8) ^
! 144: CCRC::Table[pointer[1]] ^ pointer[2]) & (kHashSize - 1);
! 145: }
! 146: #else // no HASH_ZIP
! 147: inline UInt32 Hash(const Byte *pointer)
! 148: {
! 149: return pointer[0] ^ (UInt32(pointer[1]) << 8);
! 150: }
! 151: #endif // HASH_ZIP
! 152: #endif // HASH_ARRAY_2
! 153:
! 154:
! 155: STDMETHODIMP_(UInt32) CMatchFinderHC::GetLongestMatch(UInt32 *distances)
! 156: {
! 157: UInt32 lenLimit;
! 158: if (_pos + _matchMaxLen <= _streamPos)
! 159: lenLimit = _matchMaxLen;
! 160: else
! 161: {
! 162: lenLimit = _streamPos - _pos;
! 163: if(lenLimit < kNumHashBytes)
! 164: return 0;
! 165: }
! 166:
! 167: UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
! 168: Byte *cur = _buffer + _pos;
! 169:
! 170: UInt32 maxLen = 0;
! 171:
! 172: #ifdef HASH_ARRAY_2
! 173: UInt32 hash2Value;
! 174: #ifdef HASH_ARRAY_3
! 175: UInt32 hash3Value;
! 176: UInt32 hashValue = Hash(cur, hash2Value, hash3Value);
! 177: #else
! 178: UInt32 hashValue = Hash(cur, hash2Value);
! 179: #endif
! 180: #else
! 181: UInt32 hashValue = Hash(cur);
! 182: #endif
! 183: #ifdef HASH_ARRAY_2
! 184:
! 185: UInt32 curMatch2 = _hash[kHash2Offset + hash2Value];
! 186: _hash[kHash2Offset + hash2Value] = _pos;
! 187: distances[2] = 0xFFFFFFFF;
! 188: if(curMatch2 > matchMinPos)
! 189: if (_buffer[curMatch2] == cur[0])
! 190: {
! 191: distances[2] = _pos - curMatch2 - 1;
! 192: maxLen = 2;
! 193: }
! 194:
! 195: #ifdef HASH_ARRAY_3
! 196:
! 197: UInt32 curMatch3 = _hash[kHash3Offset + hash3Value];
! 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:
! 207: #endif
! 208: #endif
! 209:
! 210: UInt32 curMatch = _hash[hashValue];
! 211: _hash[hashValue] = _pos;
! 212: CIndex *chain = _hash + kHashSizeSum;
! 213: chain[_cyclicBufferPos] = curMatch;
! 214: distances[kNumHashBytes] = 0xFFFFFFFF;
! 215: #ifdef THERE_ARE_DIRECT_HASH_BYTES
! 216: if (lenLimit == kNumHashDirectBytes)
! 217: {
! 218: if(curMatch > matchMinPos)
! 219: while (maxLen < kNumHashDirectBytes)
! 220: distances[++maxLen] = _pos - curMatch - 1;
! 221: }
! 222: else
! 223: #endif
! 224: {
! 225: UInt32 count = _cutValue;
! 226: do
! 227: {
! 228: if(curMatch <= matchMinPos)
! 229: break;
! 230: Byte *pby1 = _buffer + curMatch;
! 231: UInt32 currentLen = kNumHashDirectBytes;
! 232: do
! 233: {
! 234: if (pby1[currentLen] != cur[currentLen])
! 235: break;
! 236: }
! 237: while(++currentLen != lenLimit);
! 238:
! 239: UInt32 delta = _pos - curMatch;
! 240: while (maxLen < currentLen)
! 241: distances[++maxLen] = delta - 1;
! 242: if(currentLen == lenLimit)
! 243: break;
! 244:
! 245: UInt32 cyclicPos = (delta <= _cyclicBufferPos) ?
! 246: (_cyclicBufferPos - delta):
! 247: (_cyclicBufferPos - delta + _cyclicBufferSize);
! 248:
! 249: curMatch = chain[cyclicPos];
! 250: }
! 251: while(--count != 0);
! 252: }
! 253: #ifdef HASH_ARRAY_2
! 254: #ifdef HASH_ARRAY_3
! 255: if (distances[4] < distances[3])
! 256: distances[3] = distances[4];
! 257: #endif
! 258: if (distances[3] < distances[2])
! 259: distances[2] = distances[3];
! 260: #endif
! 261: return maxLen;
! 262: }
! 263:
! 264: STDMETHODIMP_(void) CMatchFinderHC::DummyLongestMatch()
! 265: {
! 266: if (_streamPos - _pos < kNumHashBytes)
! 267: return;
! 268:
! 269: Byte *cur = _buffer + _pos;
! 270:
! 271: #ifdef HASH_ARRAY_2
! 272: UInt32 hash2Value;
! 273: #ifdef HASH_ARRAY_3
! 274: UInt32 hash3Value;
! 275: UInt32 hashValue = Hash(cur, hash2Value, hash3Value);
! 276: _hash[kHash3Offset + hash3Value] = _pos;
! 277: #else
! 278: UInt32 hashValue = Hash(cur, hash2Value);
! 279: #endif
! 280: _hash[kHash2Offset + hash2Value] = _pos;
! 281: #else
! 282: UInt32 hashValue = Hash(cur);
! 283: #endif
! 284:
! 285: _hash[kHashSizeSum + _cyclicBufferPos] = _hash[hashValue];
! 286: _hash[hashValue] = _pos;
! 287: }
! 288:
! 289: void CMatchFinderHC::Normalize()
! 290: {
! 291: UInt32 subValue = _pos - _cyclicBufferSize;
! 292: CIndex *items = _hash;
! 293: UInt32 numItems = kHashSizeSum + _cyclicBufferSize;
! 294: for (UInt32 i = 0; i < numItems; i++)
! 295: {
! 296: UInt32 value = items[i];
! 297: if (value <= subValue)
! 298: value = kEmptyHashValue;
! 299: else
! 300: value -= subValue;
! 301: items[i] = value;
! 302: }
! 303: ReduceOffsets(subValue);
! 304: }
! 305:
! 306: STDMETHODIMP CMatchFinderHC::MovePos()
! 307: {
! 308: if (++_cyclicBufferPos == _cyclicBufferSize)
! 309: _cyclicBufferPos = 0;
! 310: RINOK(CLZInWindow::MovePos());
! 311: if (_pos == kMaxValForNormalize)
! 312: Normalize();
! 313: return S_OK;
! 314: }
! 315:
! 316: STDMETHODIMP_(Byte) CMatchFinderHC::GetIndexByte(Int32 index)
! 317: { return CLZInWindow::GetIndexByte(index); }
! 318:
! 319: STDMETHODIMP_(UInt32) CMatchFinderHC::GetMatchLen(Int32 index,
! 320: UInt32 back, UInt32 limit)
! 321: { return CLZInWindow::GetMatchLen(index, back, limit); }
! 322:
! 323: STDMETHODIMP_(UInt32) CMatchFinderHC::GetNumAvailableBytes()
! 324: { return CLZInWindow::GetNumAvailableBytes(); }
! 325:
! 326: STDMETHODIMP_(const Byte *) CMatchFinderHC::GetPointerToCurrentPos()
! 327: { return CLZInWindow::GetPointerToCurrentPos(); }
! 328:
! 329: // IMatchFinderSetCallback
! 330: STDMETHODIMP CMatchFinderHC::SetCallback(IMatchFinderCallback *callback)
! 331: {
! 332: m_Callback = callback;
! 333: return S_OK;
! 334: }
! 335:
! 336: void CMatchFinderHC::BeforeMoveBlock()
! 337: {
! 338: if (m_Callback)
! 339: m_Callback->BeforeChangingBufferPos();
! 340: CLZInWindow::BeforeMoveBlock();
! 341: }
! 342:
! 343: void CMatchFinderHC::AfterMoveBlock()
! 344: {
! 345: if (m_Callback)
! 346: m_Callback->AfterChangingBufferPos();
! 347: CLZInWindow::AfterMoveBlock();
! 348: }
! 349:
! 350: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>