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