⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bintreemain.h

📁 sleuthit-2.09 一个磁盘的工具集
💻 H
字号:
// BinTreeMain.h#include "../../../../Common/Defs.h"#include "../../../../Common/CRC.h"#include "../../../../Common/Alloc.h"#include "BinTree.h"// #include <xmmintrin.h>// It's for prefetch// But prefetch doesn't give big gain in K8.namespace BT_NAMESPACE {#ifdef HASH_ARRAY_2  static const UInt32 kHash2Size = 1 << 10;  #define kNumHashDirectBytes 0  #ifdef HASH_ARRAY_3    static const UInt32 kNumHashBytes = 4;    static const UInt32 kHash3Size = 1 << 16;  #else    static const UInt32 kNumHashBytes = 3;  #endif  static const UInt32 kHashSize = 0;  static const UInt32 kMinMatchCheck = kNumHashBytes;  static const UInt32 kStartMaxLen = 1;#else  #ifdef HASH_ZIP     #define kNumHashDirectBytes 0    static const UInt32 kNumHashBytes = 3;    static const UInt32 kHashSize = 1 << 16;    static const UInt32 kMinMatchCheck = kNumHashBytes;    static const UInt32 kStartMaxLen = 1;  #else    #define kNumHashDirectBytes 2    static const UInt32 kNumHashBytes = 2;    static const UInt32 kHashSize = 1 << (8 * kNumHashBytes);    static const UInt32 kMinMatchCheck = kNumHashBytes + 1;    static const UInt32 kStartMaxLen = 1;  #endif#endif#ifdef HASH_ARRAY_2#ifdef HASH_ARRAY_3static const UInt32 kHash3Offset = kHash2Size;#endif#endifstatic const UInt32 kFixHashSize = 0    #ifdef HASH_ARRAY_2    + kHash2Size    #ifdef HASH_ARRAY_3    + kHash3Size    #endif    #endif    ;CMatchFinder::CMatchFinder():  _hash(0){}void CMatchFinder::FreeThisClassMemory(){  BigFree(_hash);  _hash = 0;}void CMatchFinder::FreeMemory(){  FreeThisClassMemory();  CLZInWindow::Free();}CMatchFinder::~CMatchFinder(){   FreeMemory();}STDMETHODIMP CMatchFinder::Create(UInt32 historySize, UInt32 keepAddBufferBefore,     UInt32 matchMaxLen, UInt32 keepAddBufferAfter){  if (historySize > kMaxValForNormalize - 256)  {    FreeMemory();    return E_INVALIDARG;  }  _cutValue =   #ifdef _HASH_CHAIN    8 + (matchMaxLen >> 2);  #else    16 + (matchMaxLen >> 1);  #endif  UInt32 sizeReserv = (historySize + keepAddBufferBefore +       matchMaxLen + keepAddBufferAfter) / 2 + 256;  if (CLZInWindow::Create(historySize + keepAddBufferBefore,       matchMaxLen + keepAddBufferAfter, sizeReserv))  {    _matchMaxLen = matchMaxLen;    UInt32 newCyclicBufferSize = historySize + 1;    if (_hash != 0 && newCyclicBufferSize == _cyclicBufferSize)      return S_OK;    FreeThisClassMemory();    _cyclicBufferSize = newCyclicBufferSize; // don't change it    UInt32 hs = kHashSize;    #ifdef HASH_ARRAY_2    hs = historySize - 1;    hs |= (hs >> 1);    hs |= (hs >> 2);    hs |= (hs >> 4);    hs |= (hs >> 8);    hs >>= 1;    hs |= 0xFFFF;    if (hs > (1 << 24))    {      #ifdef HASH_ARRAY_3      hs >>= 1;      #else      hs = (1 << 24) - 1;      #endif    }    _hashMask = hs;    hs++;    #endif    _hashSizeSum = hs + kFixHashSize;    UInt32 numItems = _hashSizeSum + _cyclicBufferSize    #ifndef _HASH_CHAIN     * 2    #endif    ;    size_t sizeInBytes = (size_t)numItems * sizeof(CIndex);    if (sizeInBytes / sizeof(CIndex) != numItems)      return E_OUTOFMEMORY;    _hash = (CIndex *)BigAlloc(sizeInBytes);    _son = _hash + _hashSizeSum;    if (_hash != 0)      return S_OK;  }  FreeMemory();  return E_OUTOFMEMORY;}static const UInt32 kEmptyHashValue = 0;STDMETHODIMP CMatchFinder::SetStream(ISequentialInStream *stream){  CLZInWindow::SetStream(stream);  return S_OK;}STDMETHODIMP CMatchFinder::Init(){  RINOK(CLZInWindow::Init());  for(UInt32 i = 0; i < _hashSizeSum; i++)    _hash[i] = kEmptyHashValue;  _cyclicBufferPos = 0;  ReduceOffsets(-1);  return S_OK;}STDMETHODIMP_(void) CMatchFinder::ReleaseStream(){   // ReleaseStream(); }#ifdef HASH_ARRAY_2#ifdef HASH_ARRAY_3#define HASH_CALC { \  UInt32 temp = CCRC::Table[cur[0]] ^ cur[1]; \  hash2Value = temp & (kHash2Size - 1); \  hash3Value = (temp ^ (UInt32(cur[2]) << 8)) & (kHash3Size - 1); \  hashValue = (temp ^ (UInt32(cur[2]) << 8) ^ (CCRC::Table[cur[3]] << 5)) & _hashMask; }  #else // no HASH_ARRAY_3#define HASH_CALC { \  UInt32 temp = CCRC::Table[cur[0]] ^ cur[1]; \  hash2Value = temp & (kHash2Size - 1); \  hashValue = (temp ^ (UInt32(cur[2]) << 8)) & _hashMask; }#endif // HASH_ARRAY_3#else // no HASH_ARRAY_2#ifdef HASH_ZIP inline UInt32 Hash(const Byte *pointer){  return ((UInt32(pointer[0]) << 8) ^ CCRC::Table[pointer[1]] ^ pointer[2]) & (kHashSize - 1);}#else // no HASH_ZIP inline UInt32 Hash(const Byte *pointer){  return pointer[0] ^ (UInt32(pointer[1]) << 8);}#endif // HASH_ZIP#endif // HASH_ARRAY_2STDMETHODIMP CMatchFinder::GetMatches(UInt32 *distances){  UInt32 lenLimit;  if (_pos + _matchMaxLen <= _streamPos)    lenLimit = _matchMaxLen;  else  {    lenLimit = _streamPos - _pos;    if(lenLimit < kMinMatchCheck)    {      distances[0] = 0;      return MovePos();     }  }  int offset = 1;  UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;  const Byte *cur = _buffer + _pos;  UInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize;  #ifdef HASH_ARRAY_2  UInt32 hash2Value;  #ifdef HASH_ARRAY_3  UInt32 hash3Value;  #endif  UInt32 hashValue;  HASH_CALC;  #else  UInt32 hashValue = Hash(cur);  #endif  UInt32 curMatch = _hash[kFixHashSize + hashValue];  #ifdef HASH_ARRAY_2  UInt32 curMatch2 = _hash[hash2Value];  #ifdef HASH_ARRAY_3  UInt32 curMatch3 = _hash[kHash3Offset + hash3Value];  #endif  _hash[hash2Value] = _pos;  if(curMatch2 > matchMinPos)    if (_buffer[curMatch2] == cur[0])    {      distances[offset++] = maxLen = 2;      distances[offset++] = _pos - curMatch2 - 1;    }  #ifdef HASH_ARRAY_3  _hash[kHash3Offset + hash3Value] = _pos;  if(curMatch3 > matchMinPos)    if (_buffer[curMatch3] == cur[0])    {      if (curMatch3 == curMatch2)        offset -= 2;      distances[offset++] = maxLen = 3;      distances[offset++] = _pos - curMatch3 - 1;      curMatch2 = curMatch3;    }  #endif  if (offset != 1 && curMatch2 == curMatch)  {    offset -= 2;    maxLen = kStartMaxLen;  }  #endif  _hash[kFixHashSize + hashValue] = _pos;  CIndex *son = _son;  #ifdef _HASH_CHAIN  son[_cyclicBufferPos] = curMatch;  #else  CIndex *ptr0 = son + (_cyclicBufferPos << 1) + 1;  CIndex *ptr1 = son + (_cyclicBufferPos << 1);  UInt32 len0, len1;  len0 = len1 = kNumHashDirectBytes;  #endif  #if kNumHashDirectBytes != 0  if(curMatch > matchMinPos)  {    if (_buffer[curMatch + kNumHashDirectBytes] != cur[kNumHashDirectBytes])    {      distances[offset++] = maxLen = kNumHashDirectBytes;      distances[offset++] = _pos - curMatch - 1;    }  }  #endif  UInt32 count = _cutValue;  while(true)  {    if(curMatch <= matchMinPos || count-- == 0)    {      #ifndef _HASH_CHAIN      *ptr0 = *ptr1 = kEmptyHashValue;      #endif      break;    }    UInt32 delta = _pos - curMatch;    UInt32 cyclicPos = (delta <= _cyclicBufferPos) ?        (_cyclicBufferPos - delta):        (_cyclicBufferPos - delta + _cyclicBufferSize);    CIndex *pair = son +     #ifdef _HASH_CHAIN      cyclicPos;    #else      (cyclicPos << 1);    #endif        // _mm_prefetch((const char *)pair, _MM_HINT_T0);        const Byte *pb = _buffer + curMatch;    UInt32 len =     #ifdef _HASH_CHAIN    kNumHashDirectBytes;    if (pb[maxLen] == cur[maxLen])    #else    MyMin(len0, len1);    #endif    if (pb[len] == cur[len])    {      while(++len != lenLimit)        if (pb[len] != cur[len])          break;      if (maxLen < len)      {        distances[offset++] = maxLen = len;        distances[offset++] = delta - 1;        if (len == lenLimit)        {          #ifndef _HASH_CHAIN          *ptr1 = pair[0];          *ptr0 = pair[1];          #endif          break;        }      }    }    #ifdef _HASH_CHAIN    curMatch = *pair;    #else    if (pb[len] < cur[len])    {      *ptr1 = curMatch;      ptr1 = pair + 1;      curMatch = *ptr1;      len1 = len;    }    else    {      *ptr0 = curMatch;      ptr0 = pair;      curMatch = *ptr0;      len0 = len;    }    #endif  }  distances[0] = offset - 1;  if (++_cyclicBufferPos == _cyclicBufferSize)    _cyclicBufferPos = 0;  RINOK(CLZInWindow::MovePos());  if (_pos == kMaxValForNormalize)    Normalize();  return S_OK;}STDMETHODIMP CMatchFinder::Skip(UInt32 num){  do  {  #ifdef _HASH_CHAIN  if (_streamPos - _pos < kNumHashBytes)  {    RINOK(MovePos());     continue;  }  #else  UInt32 lenLimit;  if (_pos + _matchMaxLen <= _streamPos)    lenLimit = _matchMaxLen;  else  {    lenLimit = _streamPos - _pos;    if(lenLimit < kMinMatchCheck)    {      RINOK(MovePos());      continue;    }  }  UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;  #endif  const Byte *cur = _buffer + _pos;  #ifdef HASH_ARRAY_2  UInt32 hash2Value;  #ifdef HASH_ARRAY_3  UInt32 hash3Value;  UInt32 hashValue;  HASH_CALC;  _hash[kHash3Offset + hash3Value] = _pos;  #else  UInt32 hashValue;  HASH_CALC;  #endif  _hash[hash2Value] = _pos;  #else  UInt32 hashValue = Hash(cur);  #endif  UInt32 curMatch = _hash[kFixHashSize + hashValue];  _hash[kFixHashSize + hashValue] = _pos;  #ifdef _HASH_CHAIN  _son[_cyclicBufferPos] = curMatch;  #else  CIndex *son = _son;  CIndex *ptr0 = son + (_cyclicBufferPos << 1) + 1;  CIndex *ptr1 = son + (_cyclicBufferPos << 1);  UInt32 len0, len1;  len0 = len1 = kNumHashDirectBytes;  UInt32 count = _cutValue;  while(true)  {    if(curMatch <= matchMinPos || count-- == 0)    {      *ptr0 = *ptr1 = kEmptyHashValue;      break;    }        UInt32 delta = _pos - curMatch;    UInt32 cyclicPos = (delta <= _cyclicBufferPos) ?      (_cyclicBufferPos - delta):      (_cyclicBufferPos - delta + _cyclicBufferSize);    CIndex *pair = son + (cyclicPos << 1);        // _mm_prefetch((const char *)pair, _MM_HINT_T0);        const Byte *pb = _buffer + curMatch;    UInt32 len = MyMin(len0, len1);        if (pb[len] == cur[len])    {      while(++len != lenLimit)        if (pb[len] != cur[len])          break;      if (len == lenLimit)      {        *ptr1 = pair[0];        *ptr0 = pair[1];        break;      }    }    if (pb[len] < cur[len])    {      *ptr1 = curMatch;      ptr1 = pair + 1;      curMatch = *ptr1;      len1 = len;    }    else    {      *ptr0 = curMatch;      ptr0 = pair;      curMatch = *ptr0;      len0 = len;    }  }  #endif  if (++_cyclicBufferPos == _cyclicBufferSize)    _cyclicBufferPos = 0;  RINOK(CLZInWindow::MovePos());  if (_pos == kMaxValForNormalize)    Normalize();  }  while(--num != 0);  return S_OK;}void CMatchFinder::Normalize(){  UInt32 subValue = _pos - _cyclicBufferSize;  CIndex *items = _hash;  UInt32 numItems = (_hashSizeSum + _cyclicBufferSize     #ifndef _HASH_CHAIN     * 2    #endif    );  for (UInt32 i = 0; i < numItems; i++)  {    UInt32 value = items[i];    if (value <= subValue)      value = kEmptyHashValue;    else      value -= subValue;    items[i] = value;  }  ReduceOffsets(subValue);}HRESULT CMatchFinder::MovePos(){  if (++_cyclicBufferPos == _cyclicBufferSize)    _cyclicBufferPos = 0;  RINOK(CLZInWindow::MovePos());  if (_pos == kMaxValForNormalize)    Normalize();  return S_OK;}STDMETHODIMP_(Byte) CMatchFinder::GetIndexByte(Int32 index)  { return CLZInWindow::GetIndexByte(index); }STDMETHODIMP_(UInt32) CMatchFinder::GetMatchLen(Int32 index,     UInt32 back, UInt32 limit)  { return CLZInWindow::GetMatchLen(index, back, limit); }STDMETHODIMP_(UInt32) CMatchFinder::GetNumAvailableBytes()  { return CLZInWindow::GetNumAvailableBytes(); }STDMETHODIMP_(const Byte *) CMatchFinder::GetPointerToCurrentPos()  { return CLZInWindow::GetPointerToCurrentPos(); }STDMETHODIMP_(Int32) CMatchFinder::NeedChangeBufferPos(UInt32 numCheckBytes)  { return CLZInWindow::NeedMove(numCheckBytes) ? 1: 0; }STDMETHODIMP_(void) CMatchFinder::ChangeBufferPos()  { CLZInWindow::MoveBlock();}#undef HASH_CALC#undef kNumHashDirectBytes }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -