aboutsummaryrefslogtreecommitdiff
path: root/dep/CascLib/src/CascOpenFile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dep/CascLib/src/CascOpenFile.cpp')
-rw-r--r--dep/CascLib/src/CascOpenFile.cpp191
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);