Annotation of elwix/tools/oldlzma/SRC/7zip/Compress/LZ/BinTree/BinTreeMain.h, revision 1.1.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>