diff options
author | Nayd <dnpd.dd@gmail.com> | 2015-01-11 22:12:49 +0000 |
---|---|---|
committer | Nayd <dnpd.dd@gmail.com> | 2015-01-11 23:02:19 +0000 |
commit | 31e3dc2e75459f681480ae09641f1087096dfd69 (patch) | |
tree | 70685fc84efd01d450f8bc06a4cb266e6478b694 /dep/CascLib/src/CascOpenFile.cpp | |
parent | 8bbd9133d57fc34b77544cbdd59526ed9ccaa607 (diff) |
Dep/CascLib: Update to https://github.com/ladislav-zezula/CascLib/commit/5d3789af3435534c288c2145e158d422651c7fe1
Closes #13866
Diffstat (limited to 'dep/CascLib/src/CascOpenFile.cpp')
-rw-r--r-- | dep/CascLib/src/CascOpenFile.cpp | 191 |
1 files changed, 73 insertions, 118 deletions
diff --git a/dep/CascLib/src/CascOpenFile.cpp b/dep/CascLib/src/CascOpenFile.cpp index e7cdb9aa107..e5a9855f97f 100644 --- a/dep/CascLib/src/CascOpenFile.cpp +++ b/dep/CascLib/src/CascOpenFile.cpp @@ -69,115 +69,47 @@ PCASC_ENCODING_ENTRY FindEncodingEntry(TCascStorage * hs, PQUERY_KEY pEncodingKe } // Also used in CascSearchFile -PCASC_ROOT_ENTRY FindFirstRootEntry(TCascStorage * hs, const char * szFileName, size_t * PtrIndex) +PCASC_ROOT_ENTRY FindRootEntry(TCascStorage * hs, const char * szFileName, DWORD * PtrTableIndex) { - PCASC_ROOT_ENTRY pFoundEntry = NULL; PCASC_ROOT_ENTRY pRootEntry; ULONGLONG FileNameHash; + DWORD TableIndex; uint32_t dwHashHigh = 0; uint32_t dwHashLow = 0; - size_t StartEntry = 0; - size_t MidlEntry = 0; - size_t EndEntry = hs->nRootEntries; // Calculate the HASH value of the normalized file name hashlittle2(szFileName, strlen(szFileName), &dwHashHigh, &dwHashLow); FileNameHash = ((ULONGLONG)dwHashHigh << 0x20) | dwHashLow; - // Perform binary search - while(StartEntry < EndEntry) - { - // Calculate the middle of the interval - MidlEntry = StartEntry + ((EndEntry - StartEntry) / 2); - pRootEntry = hs->ppRootEntries[MidlEntry]; + // Get the first table index + TableIndex = (DWORD)(FileNameHash & (hs->RootTable.TableSize - 1)); + assert(hs->RootTable.ItemCount < hs->RootTable.TableSize); - // Did we find it? + // Search the proper entry + for(;;) + { + // Does the has match? + pRootEntry = hs->RootTable.TablePtr + TableIndex; if(pRootEntry->FileNameHash == FileNameHash) { - pFoundEntry = pRootEntry; - break; + if(PtrTableIndex != NULL) + PtrTableIndex[0] = TableIndex; + return pRootEntry; } - // Move the interval to the left or right - (FileNameHash < pRootEntry->FileNameHash) ? EndEntry = MidlEntry : StartEntry = MidlEntry + 1; - } + // If the entry is free, the file is not there + if(pRootEntry->FileNameHash == 0 && pRootEntry->SumValue == 0) + return NULL; - // Move the pointer back to the first entry with that hash - if(pFoundEntry != NULL) - { - while(MidlEntry > 0 && hs->ppRootEntries[MidlEntry - 1]->FileNameHash == FileNameHash) - { - pFoundEntry = hs->ppRootEntries[MidlEntry - 1]; - MidlEntry--; - } + // Move to the next entry + TableIndex = (DWORD)((TableIndex + 1) & (hs->RootTable.TableSize - 1)); } - - // Return what we found - if(PtrIndex != NULL) - *PtrIndex = MidlEntry; - return pFoundEntry; -} - -// Check the root directory for that hash -PCASC_ROOT_ENTRY FindRootEntryLocale(TCascStorage * hs, char * szFileName, DWORD Locale) -{ - PCASC_ROOT_ENTRY pThatEntry = NULL; - PCASC_ROOT_ENTRY pENUSEntry = NULL; - PCASC_ROOT_ENTRY pENGBEntry = NULL; - PCASC_ROOT_ENTRY pAnyEntry = NULL; - PCASC_ROOT_ENTRY pEndEntry = NULL; - PCASC_ROOT_ENTRY pRootEntry = NULL; - ULONGLONG FileNameHash; - size_t EntryIndex = 0; - size_t EndEntry = hs->nRootEntries; - - // Find a root entry with the given name hash - pRootEntry = FindFirstRootEntry(hs, szFileName, &EntryIndex); - if(pRootEntry != NULL) - { - // Rememeber the file name hash - pEndEntry = hs->pRootEntries + hs->nRootEntries; - FileNameHash = pRootEntry->FileNameHash; - - // Find all suitable root entries - while(EntryIndex < EndEntry) - { - // Get the root entry - pRootEntry = hs->ppRootEntries[EntryIndex++]; - if(pRootEntry->FileNameHash != FileNameHash) - break; - - // If a locale has been given, check it - if(pThatEntry == NULL && Locale != 0 && (Locale & pRootEntry->Locales)) - pThatEntry = pRootEntry; - if(pENUSEntry == NULL && (pRootEntry->Locales & CASC_LOCALE_ENUS)) - pENUSEntry = pRootEntry; - if(pENGBEntry == NULL && (pRootEntry->Locales & CASC_LOCALE_ENGB)) - pENGBEntry = pRootEntry; - if(pAnyEntry == NULL) - pAnyEntry = pRootEntry; - - // Move to the next one - pRootEntry++; - } - - // Return the key by priority - if(pThatEntry != NULL) - return pThatEntry; - if(pENGBEntry != NULL) - return pENGBEntry; - if(pENUSEntry != NULL) - return pENUSEntry; - } - - // Return whatever we got - return pAnyEntry; } static TCascFile * CreateFileHandle(TCascStorage * hs, PCASC_INDEX_ENTRY pIndexEntry) { ULONGLONG FileOffsMask = ((ULONGLONG)1 << hs->KeyMapping[0].SegmentBits) - 1; - ULONGLONG FileOffset = ConvertBytesToInteger_5(pIndexEntry->FileOffset); + ULONGLONG FileOffset = ConvertBytesToInteger_5(pIndexEntry->FileOffsetBE); TCascFile * hf; // Allocate the CASC file structure @@ -190,12 +122,13 @@ static TCascFile * CreateFileHandle(TCascStorage * hs, PCASC_INDEX_ENTRY pIndexE hf->HeaderOffset = (DWORD)(FileOffset & FileOffsMask); hf->szClassName = "TCascFile"; - // Copy the compressed file size - hf->CompressedSize = ConvertBytesToInteger_4_LE(pIndexEntry->FileSize) - 0x1E; + // Copy the file size. Note that for all files except ENCODING, + // this is the compressed file size + hf->CompressedSize = ConvertBytesToInteger_4_LE(pIndexEntry->FileSizeLE); // For now, we set the file size to be equal to compressed size - // This is used when loading the "encoding" file, which does not - // have entry in the encoding itself + // This is used when loading the ENCODING file, which does not + // have entry in the encoding table hf->FileSize = hf->CompressedSize; // Increment the number of references to the archive @@ -206,10 +139,9 @@ static TCascFile * CreateFileHandle(TCascStorage * hs, PCASC_INDEX_ENTRY pIndexE return hf; } -static bool OpenFileByIndexKey(TCascStorage * hs, PQUERY_KEY pIndexKey, DWORD dwFlags, HANDLE * phFile) +static bool OpenFileByIndexKey(TCascStorage * hs, PQUERY_KEY pIndexKey, DWORD dwFlags, TCascFile ** ppCascFile) { PCASC_INDEX_ENTRY pIndexEntry; - TCascFile * hf = NULL; int nError = ERROR_SUCCESS; CASCLIB_UNUSED(dwFlags); @@ -222,43 +154,53 @@ static bool OpenFileByIndexKey(TCascStorage * hs, PQUERY_KEY pIndexKey, DWORD dw // Create the file handle structure if(nError == ERROR_SUCCESS) { - hf = CreateFileHandle(hs, pIndexEntry); - *phFile = (HANDLE)hf; - if(hf == NULL) + ppCascFile[0] = CreateFileHandle(hs, pIndexEntry); + if(ppCascFile[0] == NULL) nError = ERROR_FILE_NOT_FOUND; } +#ifdef CASCLIB_TEST + if(nError == ERROR_SUCCESS && ppCascFile[0] != NULL) + { + ppCascFile[0]->FileSize_IdxEntry = ConvertBytesToInteger_4_LE(pIndexEntry->FileSizeLE); + } +#endif + if(nError != ERROR_SUCCESS) SetLastError(nError); return (nError == ERROR_SUCCESS); } -static bool OpenFileByEncodingKey(TCascStorage * hs, PQUERY_KEY pEncodingKey, DWORD dwFlags, HANDLE * phFile) +static bool OpenFileByEncodingKey(TCascStorage * hs, PQUERY_KEY pEncodingKey, DWORD dwFlags, TCascFile ** ppCascFile) { PCASC_ENCODING_ENTRY pEncodingEntry; QUERY_KEY IndexKey; - TCascFile * hf = NULL; - int nError = ERROR_SUCCESS; // Find the encoding entry pEncodingEntry = FindEncodingEntry(hs, pEncodingKey, NULL); if(pEncodingEntry == NULL) - nError = ERROR_FILE_NOT_FOUND; + { + SetLastError(ERROR_FILE_NOT_FOUND); + return false; + } // Prepare the file index and open the file by index // Note: We don't know what to do if there is more than just one index key // We always take the first file present. Is that correct? -// IndexKey.pbData = pEncodingEntry->EncodingKey + (MD5_HASH_SIZE * pEncodingEntry->KeyCount); -// assert(pEncodingEntry->KeyCount == 1); IndexKey.pbData = pEncodingEntry->EncodingKey + MD5_HASH_SIZE; IndexKey.cbData = MD5_HASH_SIZE; - if(OpenFileByIndexKey(hs, &IndexKey, dwFlags, phFile)) + if(OpenFileByIndexKey(hs, &IndexKey, dwFlags, ppCascFile)) { - // Fix the file size from the encoding key - hf = IsValidFileHandle(*phFile); - if(hf != NULL) + // Check if the file handle was created + if(ppCascFile[0] != NULL) { - hf->FileSize = ConvertBytesToInteger_4(pEncodingEntry->FileSizeBytes); + // Fill-in the file size. For all files except ENCODING, + // this overrides the value stored in the index entry. + ppCascFile[0]->FileSize = ConvertBytesToInteger_4(pEncodingEntry->FileSizeBE); + +#ifdef CASCLIB_TEST + ppCascFile[0]->FileSize_EncEntry = ConvertBytesToInteger_4(pEncodingEntry->FileSizeBE); +#endif return true; } } @@ -289,7 +231,7 @@ bool WINAPI CascOpenFileByIndexKey(HANDLE hStorage, PQUERY_KEY pIndexKey, DWORD } // Use the internal function to open the file - return OpenFileByIndexKey(hs, pIndexKey, dwFlags, phFile); + return OpenFileByIndexKey(hs, pIndexKey, dwFlags, (TCascFile **)phFile); } bool WINAPI CascOpenFileByEncodingKey(HANDLE hStorage, PQUERY_KEY pEncodingKey, DWORD dwFlags, HANDLE * phFile) @@ -312,12 +254,12 @@ bool WINAPI CascOpenFileByEncodingKey(HANDLE hStorage, PQUERY_KEY pEncodingKey, } // Use the internal function fo open the file - return OpenFileByEncodingKey(hs, pEncodingKey, dwFlags, phFile); + return OpenFileByEncodingKey(hs, pEncodingKey, dwFlags, (TCascFile **)phFile); } bool WINAPI CascOpenFile(HANDLE hStorage, const char * szFileName, DWORD dwLocale, DWORD dwFlags, HANDLE * phFile) { - CASC_ROOT_KEY_INFO EncodingKeyInfo; + PCASC_ROOT_ENTRY_MNDX pRootEntryMndx = NULL; PCASC_ROOT_ENTRY pRootEntry; PCASC_PACKAGE pPackage; TCascStorage * hs; @@ -326,6 +268,8 @@ bool WINAPI CascOpenFile(HANDLE hStorage, const char * szFileName, DWORD dwLocal char * szFileName2; int nError = ERROR_SUCCESS; + CASCLIB_UNUSED(dwLocale); + // Validate the storage handle hs = IsValidStorageHandle(hStorage); if(hs == NULL) @@ -360,11 +304,11 @@ bool WINAPI CascOpenFile(HANDLE hStorage, const char * szFileName, DWORD dwLocal while(szStrippedName[0] == '/') szStrippedName++; - nError = SearchMndxInfo(hs->pMndxInfo, szStrippedName, (DWORD)(pPackage - hs->pPackages->Packages), &EncodingKeyInfo); + nError = SearchMndxInfo(hs->pMndxInfo, szStrippedName, (DWORD)(pPackage - hs->pPackages->Packages), &pRootEntryMndx); if(nError == ERROR_SUCCESS) { // Prepare the encoding key - EncodingKey.pbData = EncodingKeyInfo.EncodingKey; + EncodingKey.pbData = pRootEntryMndx->EncodingKey; EncodingKey.cbData = MD5_HASH_SIZE; } } @@ -376,23 +320,27 @@ bool WINAPI CascOpenFile(HANDLE hStorage, const char * szFileName, DWORD dwLocal else { // Convert the file name to lowercase + slashes - NormalizeFileName_UpperBkSlash(szFileName2); + NormalizeFileName_UpperBkSlash(szFileName2, szFileName2); // Check the root directory for that hash - pRootEntry = FindRootEntryLocale(hs, szFileName2, dwLocale); - nError = (pRootEntry != NULL) ? ERROR_SUCCESS : ERROR_FILE_NOT_FOUND; + pRootEntry = FindRootEntry(hs, szFileName2, NULL); if(pRootEntry != NULL) { // Prepare the root key - EncodingKey.pbData = pRootEntry->EncodingKey; + EncodingKey.pbData = (LPBYTE)pRootEntry->EncodingKey; EncodingKey.cbData = MD5_HASH_SIZE; + nError = ERROR_SUCCESS; + } + else + { + nError = ERROR_FILE_NOT_FOUND; } } // Use the root key to find the file in the encoding table entry if(nError == ERROR_SUCCESS) { - if(!OpenFileByEncodingKey(hs, &EncodingKey, dwFlags, phFile)) + if(!OpenFileByEncodingKey(hs, &EncodingKey, dwFlags, (TCascFile **)phFile)) { assert(GetLastError() != ERROR_SUCCESS); nError = GetLastError(); @@ -400,11 +348,18 @@ bool WINAPI CascOpenFile(HANDLE hStorage, const char * szFileName, DWORD dwLocal } // Delete the file name copy - delete [] szFileName2; + CASC_FREE(szFileName2); } else nError = ERROR_NOT_ENOUGH_MEMORY; +#ifdef CASCLIB_TEST + if(phFile[0] != NULL && pRootEntryMndx != NULL) + { + ((TCascFile *)(phFile[0]))->FileSize_RootEntry = pRootEntryMndx->FileSize; + } +#endif + if(nError != ERROR_SUCCESS) SetLastError(nError); return (nError == ERROR_SUCCESS); |