w_wad: replace unordered_map with verstable hashmap for lumpnumcache + convert back to C from C++
Thanks Alug! 014a22e933
This commit is contained in:
parent
7ec95f7d96
commit
569404dfe1
6 changed files with 2189 additions and 51 deletions
|
|
@ -1667,6 +1667,10 @@ freely, subject to the following restrictions:
|
|||
- stb_vorbis + stb_rect_pack
|
||||
Copyright (c) 2017 Sean Barrett
|
||||
https://github.com/nothings/stb
|
||||
- Verstable
|
||||
Copyright (c) 2026 Jackson Allan
|
||||
https://github.com/JacksonAllan/Verstable
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ add_executable(BLANKART MACOSX_BUNDLE WIN32
|
|||
v_video.c
|
||||
s_sound.c
|
||||
sounds.c
|
||||
w_wad.cpp
|
||||
w_wad.c
|
||||
filesrch.c
|
||||
mserv.c
|
||||
http-mserv.c
|
||||
|
|
|
|||
|
|
@ -1370,6 +1370,7 @@ static void I_Fork(void)
|
|||
INT32 I_StartupSystem(void)
|
||||
{
|
||||
int SDLlinked = SDL_GetVersion();
|
||||
W_Startup();
|
||||
I_StartupConsole();
|
||||
#ifdef NEWSIGNALHANDLER
|
||||
// This is useful when debugging. It lets GDB attach to
|
||||
|
|
|
|||
2119
src/verstable.h
Normal file
2119
src/verstable.h
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -90,34 +90,29 @@ typedef struct
|
|||
#define LUMPNUMCACHESIZE 2048 // should be reasonable ig
|
||||
#define LUMPNUMCACHENAME 32
|
||||
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#define NAME lumpnum_map
|
||||
#define KEY_TY char *
|
||||
#define KEY_GET_CONST
|
||||
#define VAL_TY lumpnum_t
|
||||
#define HASH_FN vt_hash_string
|
||||
#define CMPR_FN vt_cmpr_string
|
||||
#define KEY_DTOR_FN free
|
||||
#include "verstable.h"
|
||||
|
||||
struct LumpnumNameHash
|
||||
{
|
||||
std::size_t operator()(const std::string& str) const
|
||||
{
|
||||
// hopefully this is fast enough but should be
|
||||
return static_cast<std::size_t>(HASH32(str.c_str(), str.length()));
|
||||
}
|
||||
};
|
||||
#define NAME folder_map
|
||||
#define KEY_TY char *
|
||||
#define KEY_GET_CONST
|
||||
#define VAL_TY UINT16
|
||||
#define HASH_FN vt_hash_string
|
||||
#define CMPR_FN vt_cmpr_string
|
||||
#define KEY_DTOR_FN free
|
||||
#include "verstable.h"
|
||||
|
||||
struct LumpnumStringEquals
|
||||
{
|
||||
bool operator()(const std::string& str1, const std::string& str2) const
|
||||
{
|
||||
//return fastcmp(str1.c_str(), str2.c_str());
|
||||
return str1 == str2;
|
||||
}
|
||||
};
|
||||
static lumpnum_map lumpnumcache;
|
||||
|
||||
static std::unordered_map<std::string, lumpnum_t, LumpnumNameHash, LumpnumStringEquals> lumpnumcache(LUMPNUMCACHESIZE);
|
||||
|
||||
// gotta wrap this in a struct due to external C linkage
|
||||
struct FolderCache {
|
||||
std::unordered_map<std::string, UINT16, LumpnumNameHash, LumpnumStringEquals> map;
|
||||
};
|
||||
typedef struct FolderCache {
|
||||
folder_map map;
|
||||
} FolderCache;
|
||||
|
||||
//===========================================================================
|
||||
// GLOBALS
|
||||
|
|
@ -132,6 +127,8 @@ wadfile_t *wadfiles[MAX_WADFILES]; // 0 to numwadfiles-1 are valid
|
|||
// being ejected
|
||||
void W_Shutdown(void)
|
||||
{
|
||||
lumpnum_map_cleanup(&lumpnumcache);
|
||||
|
||||
while (numwadfiles--)
|
||||
{
|
||||
wadfile_t *wad = wadfiles[numwadfiles];
|
||||
|
|
@ -147,14 +144,24 @@ void W_Shutdown(void)
|
|||
}
|
||||
}
|
||||
|
||||
delete wad->startfolders;
|
||||
delete wad->endfolders;
|
||||
folder_map_cleanup(&wad->startfolders->map);
|
||||
free(wad->startfolders);
|
||||
folder_map_cleanup(&wad->endfolders->map);
|
||||
free(wad->endfolders);
|
||||
|
||||
Z_Free(wad->lumpinfo);
|
||||
Z_Free(wad);
|
||||
}
|
||||
}
|
||||
|
||||
// the lumpnum cache needs to be initialized before use
|
||||
// call this as early as possible!
|
||||
void W_Startup(void)
|
||||
{
|
||||
lumpnum_map_init(&lumpnumcache);
|
||||
lumpnum_map_reserve(&lumpnumcache, LUMPNUMCACHESIZE);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// LUMP BASED ROUTINES
|
||||
//===========================================================================
|
||||
|
|
@ -457,7 +464,7 @@ boolean W_MakeFileHash(const char *filename, boolean openwad, UINT64 *ret)
|
|||
// Invalidates the cache of lump numbers. Call this whenever a wad is added.
|
||||
FUNCINLINE static ATTRINLINE void W_InvalidateLumpnumCache(void)
|
||||
{
|
||||
lumpnumcache.clear();
|
||||
lumpnum_map_clear(&lumpnumcache);
|
||||
}
|
||||
|
||||
FUNCINLINE static ATTRINLINE UINT32 W_HashLumpName(const char *name, size_t len)
|
||||
|
|
@ -656,7 +663,7 @@ static lumpinfo_t* ResGetLumpsWad (FILE* handle, UINT16* nlmp, const char* filen
|
|||
namelen = strlen(trimname);
|
||||
|
||||
// Allocate the lump's long and full name (save on memory).
|
||||
lump_p->longname = lump_p->fullname = static_cast<char*>(Z_Calloc(namelen * sizeof(char), PU_STATIC, NULL));
|
||||
lump_p->longname = lump_p->fullname = (char*)Z_Calloc(namelen * sizeof(char), PU_STATIC, NULL);
|
||||
strncpy(lump_p->longname, trimname, namelen);
|
||||
lump_p->longname[namelen-1] = '\0';
|
||||
lump_p->hash.longname = lump_p->hash.fullname = W_HashLumpName(lump_p->longname, strlen(lump_p->longname));
|
||||
|
|
@ -785,7 +792,7 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp)
|
|||
// Look for central directory end signature near end of file.
|
||||
// Contains entry number (number of lumps), and central directory start offset.
|
||||
fseek(handle, 0, SEEK_END);
|
||||
if (!ResFindSignature(handle, pat_end, std::max<long>(0, ftell(handle) - (22 + 65536))))
|
||||
if (!ResFindSignature(handle, pat_end, (long)max(0, ftell(handle) - (22 + 65536))))
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "Missing central directory\n");
|
||||
return NULL;
|
||||
|
|
@ -844,7 +851,7 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp)
|
|||
dotpos = fullname + strlen(fullname); // Watch for files without extension.
|
||||
|
||||
memset(lump_p->name, '\0', 9); // Making sure they're initialized to 0. Is it necessary?
|
||||
strncpy(lump_p->name, trimname, std::min<size_t>(8, dotpos - trimname));
|
||||
strncpy(lump_p->name, trimname, (size_t)min(8, dotpos - trimname));
|
||||
lump_p->namelength = strlen(lump_p->name);
|
||||
lump_p->hash.name = W_HashLumpName(lump_p->name, lump_p->namelength);
|
||||
|
||||
|
|
@ -1049,8 +1056,10 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup, boole
|
|||
fseek(handle, 0, SEEK_END);
|
||||
wadfile->filesize = (unsigned)ftell(handle);
|
||||
wadfile->type = type;
|
||||
wadfile->startfolders = new FolderCache();
|
||||
wadfile->endfolders = new FolderCache();
|
||||
wadfile->startfolders = (FolderCache *)malloc(sizeof(FolderCache));
|
||||
folder_map_init(&wadfile->startfolders->map);
|
||||
wadfile->endfolders = (FolderCache *)malloc(sizeof(FolderCache));
|
||||
folder_map_init(&wadfile->endfolders->map);
|
||||
|
||||
// already generated, just copy it over
|
||||
wadfile->hash = filehash;
|
||||
|
|
@ -1391,9 +1400,9 @@ UINT16 W_CheckNumForFolderStartPK3(const char *name, UINT16 wad, UINT16 startlum
|
|||
size_t namelen;
|
||||
lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump;
|
||||
|
||||
auto it = wadfiles[wad]->startfolders->map.find(name);
|
||||
if (it != wadfiles[wad]->startfolders->map.end())
|
||||
return it->second;
|
||||
folder_map_itr it = folder_map_get(&wadfiles[wad]->startfolders->map, name);
|
||||
if (!folder_map_is_end(it))
|
||||
return it.data->val;
|
||||
|
||||
namelen = strlen(name);
|
||||
|
||||
|
|
@ -1405,12 +1414,12 @@ UINT16 W_CheckNumForFolderStartPK3(const char *name, UINT16 wad, UINT16 startlum
|
|||
if (lump_p->fullnamelength == namelen)
|
||||
i++;
|
||||
|
||||
wadfiles[wad]->startfolders->map[name] = i;
|
||||
folder_map_insert(&wadfiles[wad]->startfolders->map, strdup(name), i);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
wadfiles[wad]->startfolders->map[name] = INT16_MAX;
|
||||
folder_map_insert(&wadfiles[wad]->startfolders->map, strdup(name), INT16_MAX);
|
||||
return INT16_MAX;
|
||||
}
|
||||
|
||||
|
|
@ -1423,9 +1432,9 @@ UINT16 W_CheckNumForFolderEndPK3(const char *name, UINT16 wad, UINT16 startlump)
|
|||
size_t namelen;
|
||||
lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump;
|
||||
|
||||
auto it = wadfiles[wad]->endfolders->map.find(name);
|
||||
if (it != wadfiles[wad]->endfolders->map.end())
|
||||
return it->second;
|
||||
folder_map_itr it = folder_map_get(&wadfiles[wad]->endfolders->map, name);
|
||||
if (!folder_map_is_end(it))
|
||||
return it.data->val;
|
||||
|
||||
namelen = strlen(name);
|
||||
|
||||
|
|
@ -1435,7 +1444,7 @@ UINT16 W_CheckNumForFolderEndPK3(const char *name, UINT16 wad, UINT16 startlump)
|
|||
break;
|
||||
}
|
||||
|
||||
wadfiles[wad]->endfolders->map[name] = i;
|
||||
folder_map_insert(&wadfiles[wad]->endfolders->map, strdup(name), i);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
|
@ -1458,16 +1467,16 @@ UINT16 W_CheckNumForFullNamePK3(const char *name, UINT16 wad, UINT16 startlump)
|
|||
|
||||
FUNCINLINE static ATTRINLINE lumpnum_t CheckLumpInCache(const char *name)
|
||||
{
|
||||
auto it = lumpnumcache.find(name);
|
||||
if (it != lumpnumcache.end())
|
||||
return it->second;
|
||||
lumpnum_map_itr it = lumpnum_map_get(&lumpnumcache, name);
|
||||
if (!lumpnum_map_is_end(it))
|
||||
return it.data->val;
|
||||
|
||||
return LUMPERROR;
|
||||
}
|
||||
|
||||
FUNCINLINE static ATTRINLINE void AddLumpToCache(lumpnum_t lumpnum, const char *name)
|
||||
{
|
||||
lumpnumcache.emplace(name, lumpnum);
|
||||
lumpnum_map_insert(&lumpnumcache, strdup(name), lumpnum);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -1498,12 +1507,16 @@ lumpnum_t W_CheckNumForName(const char *name)
|
|||
break; //found it
|
||||
}
|
||||
|
||||
if (check == INT16_MAX) return LUMPERROR;
|
||||
if (check == INT16_MAX)
|
||||
{
|
||||
return LUMPERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Update the cache.
|
||||
lumpnum_t lumpnum = (i << 16) | check;
|
||||
lumpnumcache.insert({name, lumpnum});
|
||||
AddLumpToCache(lumpnum, name);
|
||||
|
||||
return lumpnum;
|
||||
}
|
||||
}
|
||||
|
|
@ -2461,7 +2474,7 @@ W_VerifyPK3 (FILE *fp, lumpchecklist_t *checklist, boolean status)
|
|||
fseek(fp, 0, SEEK_END);
|
||||
file_size = ftell(fp);
|
||||
|
||||
if (!ResFindSignature(fp, pat_end, std::max<long>(0, ftell(fp) - (22 + 65536))))
|
||||
if (!ResFindSignature(fp, pat_end, (long)max(0, ftell(fp) - (22 + 65536))))
|
||||
return true;
|
||||
|
||||
fseek(fp, -4, SEEK_CUR);
|
||||
|
|
@ -2502,7 +2515,7 @@ W_VerifyPK3 (FILE *fp, lumpchecklist_t *checklist, boolean status)
|
|||
dotpos = fullname + strlen(fullname); // Watch for files without extension.
|
||||
|
||||
memset(lumpname, '\0', 9); // Making sure they're initialized to 0. Is it necessary?
|
||||
strncpy(lumpname, trimname,std::min<size_t>(8, dotpos - trimname));
|
||||
strncpy(lumpname, trimname,(size_t)min(8, dotpos - trimname));
|
||||
|
||||
if (! W_VerifyName(lumpname, checklist, status))
|
||||
verified = false;
|
||||
|
|
@ -152,6 +152,7 @@ extern wadfile_t *wadfiles[MAX_WADFILES];
|
|||
|
||||
// =========================================================================
|
||||
|
||||
void W_Startup(void);
|
||||
void W_Shutdown(void);
|
||||
|
||||
// Opens a WAD file. Returns the FILE * handle for the file, or NULL if not found or could not be opened
|
||||
|
|
|
|||
Loading…
Reference in a new issue