diff --git a/src/filesrch.c b/src/filesrch.c index ad0cf02a13026dfc7dd109b1ef025061d1e46ca0..9da6d20888307a02d92d68eaa72b0517ba0d7de5 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -842,6 +842,8 @@ lumpinfo_t *getdirectoryfiles(const char *path, UINT16 *nlmp, UINT16 *nfolders) if (strstr(fullname, path)) fullname += strlen(path) + 1; + size_t fullnamelength = strlen(fullname); + // Get the 8-character long lump name. trimname = strrchr(fullname, '/'); if (trimname) @@ -853,21 +855,30 @@ lumpinfo_t *getdirectoryfiles(const char *path, UINT16 *nlmp, UINT16 *nfolders) { char *dotpos = strrchr(trimname, '.'); if (dotpos == NULL) - dotpos = fullname + strlen(fullname); + dotpos = fullname + fullnamelength; strncpy(lump_p->name, trimname, min(8, dotpos - trimname)); // The name of the file, without the extension. lump_p->longname = Z_Calloc(dotpos - trimname + 1, PU_STATIC, NULL); strlcpy(lump_p->longname, trimname, dotpos - trimname + 1); + lump_p->longnamelength = strlen(lump_p->longname); } - else + else { lump_p->longname = Z_Calloc(1, PU_STATIC, NULL); + lump_p->longnamelength = 0; + } // The complete name of the file, with its extension, // excluding the path of the directory where it resides. lump_p->fullname = Z_StrDup(fullname); - lump_p->hash = quickncasehash(lump_p->name, 8); + + lump_p->hash.name = W_HashLumpName(lump_p->name); + lump_p->hash.fullname = W_HashLumpName(lump_p->fullname); + lump_p->hash.longname = W_HashLumpName(lump_p->longname); + + lump_p->namelength = strlen(lump_p->name); + lump_p->fullnamelength = fullnamelength; lump_p++; i++; diff --git a/src/g_game.c b/src/g_game.c index ab1ba8720a7777dbd345b50cda2256d8d8d2af66..5889c5d8c7dc7e9fe9ea46dc62d6fe96494d2370 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -855,30 +855,15 @@ const char *G_BuildClassicMapName(INT32 map) return mapname; } -static UINT32 G_HashMapNameString(const char *name, size_t name_length) +static UINT32 G_HashMapNameString(const char *name) { - UINT32 hash; - size_t i; - - char *buffer = malloc(name_length + 1); - if (buffer == NULL) - return 0; - - for (i = 0; i < name_length; i++) - buffer[i] = tolower(name[i]); - buffer[i] = '\0'; - - hash = FNV1a_HashString(buffer); - - free(buffer); - - return hash; + return FNV1a_HashLowercaseString(name); } static void G_MakeMapName(mapname_t *name, const char *string) { name->length = strlen(string); - name->hash = G_HashMapNameString(string, name->length); + name->hash = G_HashMapNameString(string); name->chars = Z_StrDup(string); strupr(name->chars); } @@ -918,13 +903,13 @@ UINT16 G_GetMapNumber(const char *name) { size_t name_length = strlen(name); - return MapIDForHashedString(name, name_length, G_HashMapNameString(name, name_length)); + return MapIDForHashedString(name, name_length, G_HashMapNameString(name)); } UINT16 G_GetMapNumberForNextMap(const char *name) { size_t name_length = strlen(name); - UINT32 name_hash = G_HashMapNameString(name, name_length); + UINT32 name_hash = G_HashMapNameString(name); for (UINT16 i = 0; i < NUM_NEXTMAPS; i++) { diff --git a/src/m_misc.c b/src/m_misc.c index 2cf260e949ec63c967d3b4982365085d96d97a13..ad0e8abd3df66a645d149d7bf022f247326fa173 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -2327,3 +2327,17 @@ UINT32 FNV1a_HashString(const char *message) return hash; } + +UINT32 FNV1a_HashLowercaseString(const char *message) +{ + UINT32 hash = FNV1A_OFFSET_BASIS; + + while (*message) + { + hash ^= tolower(*message); + hash *= FNV1A_PRIME; + message++; + } + + return hash; +} diff --git a/src/m_misc.h b/src/m_misc.h index e19b2f3163c9f1324074bb3182043bd928e98535..478e557a5525a81f5d077f64f9b71d8650a8c8b7 100644 --- a/src/m_misc.h +++ b/src/m_misc.h @@ -122,6 +122,7 @@ int M_RoundUp(double number); // Hashes some message using FNV-1a UINT32 FNV1a_Hash(const char *message, size_t size); UINT32 FNV1a_HashString(const char *message); +UINT32 FNV1a_HashLowercaseString(const char *message); #include "w_wad.h" extern char configfile[MAX_WADPATH]; diff --git a/src/w_wad.c b/src/w_wad.c index 06025b6b1ee4547b6cdaccf6b5788dd6453089c4..f800cb809e5b908f501ec80ad76ff51fd5316f80 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -319,6 +319,11 @@ static void W_InvalidateLumpnumCache(void) memset(lumpnumcache, 0, sizeof (lumpnumcache)); } +UINT32 W_HashLumpName(const char *name) +{ + return FNV1a_HashLowercaseString(name); +} + /** Detect a file type. * \todo Actually detect the wad/pkzip headers and whatnot, instead of just checking the extensions. */ @@ -343,18 +348,23 @@ static lumpinfo_t* ResGetLumpsStandalone (FILE* handle, UINT16* numlumps, const fseek(handle, 0, SEEK_END); lumpinfo->size = ftell(handle); fseek(handle, 0, SEEK_SET); - strcpy(lumpinfo->name, lumpname); - lumpinfo->hash = quickncasehash(lumpname, 8); + strlcpy(lumpinfo->name, lumpname, sizeof(lumpinfo->name)); + lumpinfo->namelength = strlen(lumpinfo->name); + lumpinfo->hash.name = W_HashLumpName(lumpname); // Allocate the lump's long name. - lumpinfo->longname = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL); + lumpinfo->longname = Z_Malloc((lumpinfo->namelength + 1) * sizeof(char), PU_STATIC, NULL); strcpy(lumpinfo->longname, lumpname); - lumpinfo->longname[8] = '\0'; + lumpinfo->longname[lumpinfo->namelength] = '\0'; + lumpinfo->longnamelength = lumpinfo->namelength; + lumpinfo->hash.longname = lumpinfo->hash.name; // Allocate the lump's full name. - lumpinfo->fullname = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL); + lumpinfo->fullname = Z_Malloc((lumpinfo->namelength + 1) * sizeof(char), PU_STATIC, NULL); strcpy(lumpinfo->fullname, lumpname); - lumpinfo->fullname[8] = '\0'; + lumpinfo->fullname[lumpinfo->namelength] = '\0'; + lumpinfo->fullnamelength = lumpinfo->namelength; + lumpinfo->hash.fullname = lumpinfo->hash.name; *numlumps = 1; return lumpinfo; @@ -443,17 +453,22 @@ static lumpinfo_t* ResGetLumpsWad (FILE* handle, UINT16* nlmp, const char* filen lump_p->compression = CM_NOCOMPRESSION; memset(lump_p->name, 0x00, 9); strncpy(lump_p->name, fileinfo->name, 8); - lump_p->hash = quickncasehash(lump_p->name, 8); + lump_p->namelength = strlen(lump_p->name); + lump_p->hash.name = W_HashLumpName(lump_p->name); // Allocate the lump's long name. lump_p->longname = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL); strncpy(lump_p->longname, fileinfo->name, 8); lump_p->longname[8] = '\0'; + lump_p->longnamelength = lump_p->namelength; + lump_p->hash.longname = lump_p->hash.name; // Allocate the lump's full name. lump_p->fullname = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL); strncpy(lump_p->fullname, fileinfo->name, 8); lump_p->fullname[8] = '\0'; + lump_p->fullnamelength = lump_p->namelength; + lump_p->hash.fullname = lump_p->hash.name; } free(fileinfov); *nlmp = numlumps; @@ -619,13 +634,18 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp) memset(lump_p->name, '\0', 9); // Making sure they're initialized to 0. Is it necessary? strncpy(lump_p->name, trimname, min(8, dotpos - trimname)); - lump_p->hash = quickncasehash(lump_p->name, 8); + lump_p->namelength = strlen(lump_p->name); + lump_p->hash.name = W_HashLumpName(lump_p->name); lump_p->longname = Z_Calloc(dotpos - trimname + 1, PU_STATIC, NULL); strlcpy(lump_p->longname, trimname, dotpos - trimname + 1); + lump_p->longnamelength = strlen(lump_p->longname); + lump_p->hash.longname = W_HashLumpName(lump_p->longname); lump_p->fullname = Z_Calloc(zentry.namelen + 1, PU_STATIC, NULL); strncpy(lump_p->fullname, fullname, zentry.namelen); + lump_p->fullnamelength = zentry.namelen; + lump_p->hash.fullname = W_HashLumpName(lump_p->fullname); switch(zentry.compression) { @@ -1230,13 +1250,15 @@ UINT16 W_CheckNumForNamePwad(const char *name, UINT16 wad, UINT16 startlump) UINT16 i; static char uname[8 + 1]; UINT32 hash; + size_t namelen; if (!TestValidLump(wad,0)) return INT16_MAX; strlcpy(uname, name, sizeof uname); strupr(uname); - hash = quickncasehash(uname, 8); + namelen = strlen(uname); + hash = W_HashLumpName(uname); // // scan forward @@ -1247,7 +1269,9 @@ UINT16 W_CheckNumForNamePwad(const char *name, UINT16 wad, UINT16 startlump) { lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump; for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++) - if (lump_p->hash == hash && !strncmp(lump_p->name, uname, sizeof(uname) - 1)) + if (lump_p->namelength == namelen + && lump_p->hash.name == hash + && !strncmp(lump_p->name, uname, sizeof(uname) - 1)) return i; } @@ -1264,13 +1288,12 @@ UINT16 W_CheckNumForNamePwad(const char *name, UINT16 wad, UINT16 startlump) UINT16 W_CheckNumForLongNamePwad(const char *name, UINT16 wad, UINT16 startlump) { UINT16 i; - static char uname[256 + 1]; if (!TestValidLump(wad,0)) return INT16_MAX; - strlcpy(uname, name, sizeof uname); - strupr(uname); + size_t namelen = strlen(name); + UINT32 hash = W_HashLumpName(name); // // scan forward @@ -1281,7 +1304,9 @@ UINT16 W_CheckNumForLongNamePwad(const char *name, UINT16 wad, UINT16 startlump) { lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump; for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++) - if (!strcmp(lump_p->longname, uname)) + if (lump_p->longnamelength == namelen + && lump_p->hash.name == hash + && !stricmp(lump_p->longname, name)) return i; } @@ -1490,49 +1515,6 @@ lumpnum_t W_CheckNumForLongName(const char *name) } } -// Look for valid map data through all added files in descendant order. -// Get a map marker for WADs, and a standalone WAD file lump inside PK3s. -// TODO: Make it search through cache first, maybe...? -lumpnum_t W_CheckNumForMap(const char *name) -{ - UINT32 hash = quickncasehash(name, 8); - UINT16 lumpNum, end; - UINT32 i; - lumpinfo_t *p; - for (i = numwadfiles - 1; i < numwadfiles; i--) - { - if (wadfiles[i]->type == RET_WAD) - { - for (lumpNum = 0; lumpNum < wadfiles[i]->numlumps; lumpNum++) - { - p = wadfiles[i]->lumpinfo + lumpNum; - if (p->hash == hash && !strncmp(name, p->name, 8)) - return (i<<16) + lumpNum; - } - } - else if (W_FileHasFolders(wadfiles[i])) - { - lumpNum = W_CheckNumForFolderStartPK3("maps/", i, 0); - if (lumpNum != INT16_MAX) - end = W_CheckNumForFolderEndPK3("maps/", i, lumpNum); - else - continue; - // Now look for the specified map. - for (; lumpNum < end; lumpNum++) - { - p = wadfiles[i]->lumpinfo + lumpNum; - if (p->hash == hash && !strnicmp(name, p->name, 8)) - { - const char *extension = strrchr(p->fullname, '.'); - if (!(extension && stricmp(extension, ".wad"))) - return (i<<16) + lumpNum; - } - } - } - } - return LUMPERROR; -} - // // W_GetNumForName // diff --git a/src/w_wad.h b/src/w_wad.h index a5b5eee700b26817a7f95a36ab2498f21dad43fc..02868f92f8f475cc2b8baab4f8418137d7402c29 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -66,13 +66,25 @@ typedef struct { unsigned long position; // filelump_t filepos unsigned long disksize; // filelump_t size + char name[9]; // filelump_t name[] e.g. "LongEntr" - UINT32 hash; char *longname; // e.g. "LongEntryName" char *fullname; // e.g. "Folder/Subfolder/LongEntryName.extension" char *diskpath; // path to the file e.g. "/usr/games/srb2/Addon/Folder/Subfolder/LongEntryName.extension" + // NOTE: This is NULL if the WAD type != RET_FOLDER + + size_t namelength; // length of name + size_t longnamelength; // length of longname + size_t fullnamelength; // length of fullname + size_t size; // real (uncompressed) size compmethod compression; // lump compression method + + struct { + UINT32 name; // hash of name + UINT32 longname; // hash of longname + UINT32 fullname; // hash of fullname + } hash; } lumpinfo_t; // ========================================================================= @@ -168,6 +180,8 @@ void W_InitMultipleFiles(addfilelist_t *list); INT32 W_IsPathToFolderValid(const char *path); char *W_GetFullFolderPath(const char *path); +UINT32 W_HashLumpName(const char *name); + const char *W_CheckNameForNumPwad(UINT16 wad, UINT16 lump); const char *W_CheckNameForNum(lumpnum_t lumpnum); @@ -186,7 +200,6 @@ const char *W_GetFilenameFromFullname(const char *path); void W_GetFolderLumpsPwad(const char *name, UINT16 wad, UINT32 **list, UINT16 *list_capacity, UINT16 *numlumps); void W_GetFolderLumps(const char *name, UINT32 **list, UINT16 *list_capacity, UINT16 *numlumps); -lumpnum_t W_CheckNumForMap(const char *name); lumpnum_t W_CheckNumForName(const char *name); lumpnum_t W_CheckNumForLongName(const char *name); lumpnum_t W_GetNumForName(const char *name); // like W_CheckNumForName but I_Error on LUMPERROR