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