MCPcopy Create free account
hub / github.com/diasurgical/devilution / DefragmentHashTable

Function DefragmentHashTable

3rdParty/StormLib/src/SBaseFileTable.cpp:682–735  ·  view source on GitHub ↗

Defragment the file table so it does not contain any gaps Note: As long as all values of all TMPQHash::dwBlockIndex are not HASH_ENTRY_FREE, the startup search index does not matter. Hash table is circular, so as long as there is no terminator, all entries will be found.

Source from the content-addressed store, hash-verified

680// Hash table is circular, so as long as there is no terminator,
681// all entries will be found.
682static TMPQHash * DefragmentHashTable(
683 TMPQArchive * ha,
684 TMPQHash * pHashTable,
685 TMPQBlock * pBlockTable)
686{
687 TMPQHeader * pHeader = ha->pHeader;
688 TMPQHash * pHashTableEnd = pHashTable + pHeader->dwHashTableSize;
689 TMPQHash * pSource = pHashTable;
690 TMPQHash * pTarget = pHashTable;
691 DWORD dwFirstFreeEntry;
692 DWORD dwNewTableSize;
693
694 // Sanity checks
695 assert(pHeader->wFormatVersion == MPQ_FORMAT_VERSION_1);
696 assert(pHeader->HiBlockTablePos64 == 0);
697
698 // Parse the hash table and move the entries to the begin of it
699 for(pSource = pHashTable; pSource < pHashTableEnd; pSource++)
700 {
701 // Check whether this is a valid hash table entry
702 if(IsValidHashEntry1(ha, pSource, pBlockTable))
703 {
704 // Copy the hash table entry back
705 if(pSource > pTarget)
706 pTarget[0] = pSource[0];
707
708 // Move the target
709 pTarget++;
710 }
711 }
712
713 // Calculate how many entries in the hash table we really need
714 dwFirstFreeEntry = (DWORD)(pTarget - pHashTable);
715 dwNewTableSize = GetNearestPowerOfTwo(dwFirstFreeEntry);
716
717 // Fill the rest with entries that look like deleted
718 pHashTableEnd = pHashTable + dwNewTableSize;
719 pSource = pHashTable + dwFirstFreeEntry;
720 memset(pSource, 0xFF, (dwNewTableSize - dwFirstFreeEntry) * sizeof(TMPQHash));
721
722 // Mark the block indexes as deleted
723 for(; pSource < pHashTableEnd; pSource++)
724 pSource->dwBlockIndex = HASH_ENTRY_DELETED;
725
726 // Free some of the space occupied by the hash table
727 if(dwNewTableSize < pHeader->dwHashTableSize)
728 {
729 pHashTable = STORM_REALLOC(TMPQHash, pHashTable, dwNewTableSize);
730 ha->pHeader->BlockTableSize64 = dwNewTableSize * sizeof(TMPQHash);
731 ha->pHeader->dwHashTableSize = dwNewTableSize;
732 }
733
734 return pHashTable;
735}
736
737static int BuildFileTableFromBlockTable(
738 TMPQArchive * ha,

Callers 1

Calls 2

IsValidHashEntry1Function · 0.85
GetNearestPowerOfTwoFunction · 0.85

Tested by

no test coverage detected