mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 15:22:04 +00:00
hash.[ch]:
slight api change: the getkey and free functions now take a user data parameter (which is an aditional parameter to Hash_New. cmd.c, cvar.c, quakefs.c: clean up the resulting errors. pr_edict.c: use hash tables for lookups of function, global and field definitions. should speed things up a bit, ESPECIALLY when type checking is enabled.
This commit is contained in:
parent
aad21e3c00
commit
f40b361fb3
8 changed files with 78 additions and 50 deletions
|
@ -40,13 +40,16 @@ typedef struct hashlink_s {
|
|||
|
||||
typedef struct hashtab_s {
|
||||
size_t tab_size;
|
||||
char *(*get_key)(void*);
|
||||
void (*free_ele)(void*);
|
||||
void *user_data;
|
||||
char *(*get_key)(void*,void*);
|
||||
void (*free_ele)(void*,void*);
|
||||
hashlink_t *tab[ZERO_LENGTH_ARRAY];
|
||||
} hashtab_t;
|
||||
|
||||
hashtab_t *Hash_NewTable (int tsize, char *(*gk)(void*), void (*f)(void*));
|
||||
hashtab_t *Hash_NewTable (int tsize, char *(*gk)(void*,void*),
|
||||
void (*f)(void*,void*), void *ud);
|
||||
void Hash_DelTable (hashtab_t *tab);
|
||||
void Hash_FlushTable (hashtab_t *tab);
|
||||
int Hash_Add (hashtab_t *tab, void *ele);
|
||||
void *Hash_Find (hashtab_t *tab, const char *key);
|
||||
int Hash_Del (hashtab_t *tab, const char *key);
|
||||
|
|
|
@ -181,6 +181,11 @@ typedef struct {
|
|||
|
||||
struct progs_s {
|
||||
dprograms_t *progs;
|
||||
|
||||
struct hashtab_s *function_hash;
|
||||
struct hashtab_s *global_hash;
|
||||
struct hashtab_s *field_hash;
|
||||
|
||||
dfunction_t *pr_functions;
|
||||
char *pr_strings;
|
||||
int pr_stringsize;
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "console.h"
|
||||
#include "crc.h"
|
||||
#include "cvar.h"
|
||||
#include "hash.h"
|
||||
#include "progs.h"
|
||||
#include "qdefs.h"
|
||||
#include "qendian.h"
|
||||
|
@ -188,15 +189,7 @@ ED_FieldAtOfs (progs_t * pr, int ofs)
|
|||
ddef_t *
|
||||
ED_FindField (progs_t * pr, char *name)
|
||||
{
|
||||
ddef_t *def;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pr->progs->numfielddefs; i++) {
|
||||
def = &pr->pr_fielddefs[i];
|
||||
if (!strcmp (PR_GetString (pr, def->s_name), name))
|
||||
return def;
|
||||
}
|
||||
return NULL;
|
||||
return Hash_Find (pr->field_hash, name);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -216,15 +209,7 @@ ED_GetFieldIndex (progs_t *pr, char *name)
|
|||
ddef_t *
|
||||
PR_FindGlobal (progs_t * pr, const char *name)
|
||||
{
|
||||
ddef_t *def;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pr->progs->numglobaldefs; i++) {
|
||||
def = &pr->pr_globaldefs[i];
|
||||
if (!strcmp (PR_GetString (pr, def->s_name), name))
|
||||
return def;
|
||||
}
|
||||
return NULL;
|
||||
return Hash_Find (pr->global_hash, name);
|
||||
}
|
||||
|
||||
eval_t *
|
||||
|
@ -245,15 +230,7 @@ PR_GetGlobalPointer (progs_t *pr, const char *name)
|
|||
dfunction_t *
|
||||
ED_FindFunction (progs_t * pr, char *name)
|
||||
{
|
||||
dfunction_t *func;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pr->progs->numfunctions; i++) {
|
||||
func = &pr->pr_functions[i];
|
||||
if (!strcmp (PR_GetString (pr, func->s_name), name))
|
||||
return func;
|
||||
}
|
||||
return NULL;
|
||||
return Hash_Find (pr->function_hash, name);
|
||||
}
|
||||
|
||||
eval_t *
|
||||
|
@ -940,6 +917,22 @@ ED_LoadFromFile (progs_t * pr, char *data)
|
|||
Con_DPrintf ("%i entities inhibited\n", inhibit);
|
||||
}
|
||||
|
||||
static char *
|
||||
function_get_key (void *f, void *_pr)
|
||||
{
|
||||
progs_t *pr = (progs_t*)_pr;
|
||||
dfunction_t *func = (dfunction_t*)f;
|
||||
return PR_GetString (pr, func->s_name);
|
||||
}
|
||||
|
||||
static char *
|
||||
var_get_key (void *d, void *_pr)
|
||||
{
|
||||
progs_t *pr = (progs_t*)_pr;
|
||||
ddef_t *def = (ddef_t*)d;
|
||||
return PR_GetString (pr, def->s_name);
|
||||
}
|
||||
|
||||
/*
|
||||
PR_LoadProgs
|
||||
*/
|
||||
|
@ -992,6 +985,22 @@ PR_LoadProgs (progs_t * pr, char *progsname)
|
|||
|
||||
pr->pr_edictareasize = 0;
|
||||
|
||||
if (pr->function_hash) {
|
||||
Hash_FlushTable (pr->function_hash);
|
||||
} else {
|
||||
pr->function_hash = Hash_NewTable (1021, function_get_key, 0, pr);
|
||||
}
|
||||
if (pr->global_hash) {
|
||||
Hash_FlushTable (pr->global_hash);
|
||||
} else {
|
||||
pr->global_hash = Hash_NewTable (1021, var_get_key, 0, pr);
|
||||
}
|
||||
if (pr->field_hash) {
|
||||
Hash_FlushTable (pr->field_hash);
|
||||
} else {
|
||||
pr->field_hash = Hash_NewTable (1021, var_get_key, 0, pr);
|
||||
}
|
||||
|
||||
// byte swap the lumps
|
||||
for (i = 0; i < pr->progs->numstatements; i++) {
|
||||
pr->pr_statements[i].op = LittleShort (pr->pr_statements[i].op);
|
||||
|
@ -1010,12 +1019,14 @@ PR_LoadProgs (progs_t * pr, char *progsname)
|
|||
pr->pr_functions[i].numparms =
|
||||
LittleLong (pr->pr_functions[i].numparms);
|
||||
pr->pr_functions[i].locals = LittleLong (pr->pr_functions[i].locals);
|
||||
Hash_Add (pr->function_hash, &pr->pr_functions[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < pr->progs->numglobaldefs; i++) {
|
||||
pr->pr_globaldefs[i].type = LittleShort (pr->pr_globaldefs[i].type);
|
||||
pr->pr_globaldefs[i].ofs = LittleShort (pr->pr_globaldefs[i].ofs);
|
||||
pr->pr_globaldefs[i].s_name = LittleLong (pr->pr_globaldefs[i].s_name);
|
||||
Hash_Add (pr->global_hash, &pr->pr_globaldefs[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < pr->progs->numfielddefs; i++) {
|
||||
|
@ -1024,6 +1035,7 @@ PR_LoadProgs (progs_t * pr, char *progsname)
|
|||
PR_Error (pr, "PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
|
||||
pr->pr_fielddefs[i].ofs = LittleShort (pr->pr_fielddefs[i].ofs);
|
||||
pr->pr_fielddefs[i].s_name = LittleLong (pr->pr_fielddefs[i].s_name);
|
||||
Hash_Add (pr->field_hash, &pr->pr_fielddefs[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < pr->progs->numglobals; i++)
|
||||
|
|
|
@ -965,7 +965,7 @@ char *
|
|||
PR_GetString (progs_t * pr, int num)
|
||||
{
|
||||
if (num < 0) {
|
||||
Con_DPrintf("GET:%d == %s\n", num, pr->pr_strtbl[-num]);
|
||||
//Con_DPrintf("GET:%d == %s\n", num, pr->pr_strtbl[-num]);
|
||||
return pr->pr_strtbl[-num];
|
||||
}
|
||||
return pr->pr_strings + num;
|
||||
|
|
|
@ -821,7 +821,7 @@ Cmd_CmdList_f (void)
|
|||
}
|
||||
|
||||
static void
|
||||
cmd_alias_free (void *_a)
|
||||
cmd_alias_free (void *_a, void *unused)
|
||||
{
|
||||
cmdalias_t *a = (cmdalias_t*)_a;
|
||||
free (a->value);
|
||||
|
@ -829,14 +829,14 @@ cmd_alias_free (void *_a)
|
|||
}
|
||||
|
||||
static char *
|
||||
cmd_alias_get_key (void *_a)
|
||||
cmd_alias_get_key (void *_a, void *unused)
|
||||
{
|
||||
cmdalias_t *a = (cmdalias_t*)_a;
|
||||
return a->name;
|
||||
}
|
||||
|
||||
static char *
|
||||
cmd_get_key (void *c)
|
||||
cmd_get_key (void *c, void *unused)
|
||||
{
|
||||
cmd_function_t *cmd = (cmd_function_t*)c;
|
||||
return cmd->name;
|
||||
|
@ -851,8 +851,8 @@ cmd_get_key (void *c)
|
|||
void
|
||||
Cmd_Init_Hash (void)
|
||||
{
|
||||
cmd_hash = Hash_NewTable (1021, cmd_get_key, 0);
|
||||
cmd_alias_hash = Hash_NewTable (1021, cmd_alias_get_key, cmd_alias_free);
|
||||
cmd_hash = Hash_NewTable (1021, cmd_get_key, 0, 0);
|
||||
cmd_alias_hash = Hash_NewTable (1021, cmd_alias_get_key, cmd_alias_free, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -420,7 +420,7 @@ Cvar_CvarList_f (void)
|
|||
}
|
||||
|
||||
static void
|
||||
cvar_free (void *c)
|
||||
cvar_free (void *c, void *unused)
|
||||
{
|
||||
cvar_t *cvar = (cvar_t*)c;
|
||||
free (cvar->name);
|
||||
|
@ -429,14 +429,14 @@ cvar_free (void *c)
|
|||
}
|
||||
|
||||
static char *
|
||||
cvar_get_key (void *c)
|
||||
cvar_get_key (void *c, void *unused)
|
||||
{
|
||||
cvar_t *cvar = (cvar_t*)c;
|
||||
return cvar->name;
|
||||
}
|
||||
|
||||
static void
|
||||
calias_free (void *c)
|
||||
calias_free (void *c, void *unused)
|
||||
{
|
||||
cvar_alias_t *calias = (cvar_alias_t*)c;
|
||||
free (calias->name);
|
||||
|
@ -444,7 +444,7 @@ calias_free (void *c)
|
|||
}
|
||||
|
||||
static char *
|
||||
calias_get_key (void *c)
|
||||
calias_get_key (void *c, void *unused)
|
||||
{
|
||||
cvar_alias_t *calias = (cvar_alias_t*)c;
|
||||
return calias->name;
|
||||
|
@ -453,8 +453,8 @@ calias_get_key (void *c)
|
|||
void
|
||||
Cvar_Init_Hash (void)
|
||||
{
|
||||
cvar_hash = Hash_NewTable (1021, cvar_get_key, cvar_free);
|
||||
calias_hash = Hash_NewTable (1021, calias_get_key, calias_free);
|
||||
cvar_hash = Hash_NewTable (1021, cvar_get_key, cvar_free, 0);
|
||||
calias_hash = Hash_NewTable (1021, calias_get_key, calias_free, 0);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -53,12 +53,14 @@ hash (const char *str)
|
|||
}
|
||||
|
||||
hashtab_t *
|
||||
Hash_NewTable (int tsize, char *(*gk)(void*), void (*f)(void*))
|
||||
Hash_NewTable (int tsize, char *(*gk)(void*,void*), void (*f)(void*,void*),
|
||||
void *ud)
|
||||
{
|
||||
hashtab_t *tab = calloc (1, (size_t)&((hashtab_t*)0)->tab[tsize]);
|
||||
if (!tab)
|
||||
return 0;
|
||||
tab->tab_size = tsize;
|
||||
tab->user_data = ud;
|
||||
tab->get_key = gk;
|
||||
tab->free_ele = f;
|
||||
return tab;
|
||||
|
@ -66,6 +68,13 @@ Hash_NewTable (int tsize, char *(*gk)(void*), void (*f)(void*))
|
|||
|
||||
void
|
||||
Hash_DelTable (hashtab_t *tab)
|
||||
{
|
||||
Hash_FlushTable (tab);
|
||||
free (tab);
|
||||
}
|
||||
|
||||
void
|
||||
Hash_FlushTable (hashtab_t *tab)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -73,18 +82,17 @@ Hash_DelTable (hashtab_t *tab)
|
|||
while (tab->tab[i]) {
|
||||
hashlink_t *t = tab->tab[i]->next;
|
||||
if (tab->free_ele)
|
||||
tab->free_ele (&tab->tab[i]->data);
|
||||
tab->free_ele (&tab->tab[i]->data, tab->user_data);
|
||||
free (tab->tab[i]);
|
||||
tab->tab[i] = t;
|
||||
}
|
||||
}
|
||||
free (tab);
|
||||
}
|
||||
|
||||
int
|
||||
Hash_Add (hashtab_t *tab, void *ele)
|
||||
{
|
||||
unsigned long h = hash (tab->get_key(ele));
|
||||
unsigned long h = hash (tab->get_key(ele, tab->user_data));
|
||||
size_t ind = h % tab->tab_size;
|
||||
hashlink_t *lnk = malloc (sizeof (hashlink_t));
|
||||
|
||||
|
@ -107,7 +115,7 @@ Hash_Find (hashtab_t *tab, const char *key)
|
|||
hashlink_t *lnk = tab->tab[ind];
|
||||
|
||||
while (lnk) {
|
||||
if (strequal (key, tab->get_key (lnk->data)))
|
||||
if (strequal (key, tab->get_key (lnk->data, tab->user_data)))
|
||||
return lnk->data;
|
||||
lnk = lnk->next;
|
||||
}
|
||||
|
@ -122,7 +130,7 @@ Hash_Del (hashtab_t *tab, const char *key)
|
|||
hashlink_t *lnk = tab->tab[ind];
|
||||
|
||||
while (lnk) {
|
||||
if (strequal (key, tab->get_key (lnk->data))) {
|
||||
if (strequal (key, tab->get_key (lnk->data, tab->user_data))) {
|
||||
if (lnk->next)
|
||||
lnk->next->prev = lnk->prev;
|
||||
*lnk->prev = lnk->next;
|
||||
|
|
|
@ -729,7 +729,7 @@ COM_LoadStackFile (char *path, void *buffer, int bufsize)
|
|||
}
|
||||
|
||||
static char *
|
||||
pack_get_key (void *_p)
|
||||
pack_get_key (void *_p, void *unused)
|
||||
{
|
||||
packfile_t *p = (packfile_t *) _p;
|
||||
|
||||
|
@ -772,7 +772,7 @@ COM_LoadPackFile (char *packfile)
|
|||
Sys_Error ("%s has %i files", packfile, numpackfiles);
|
||||
|
||||
newfiles = calloc (1, numpackfiles * sizeof (packfile_t));
|
||||
hash = Hash_NewTable (1021, pack_get_key, 0);
|
||||
hash = Hash_NewTable (1021, pack_get_key, 0, 0);
|
||||
|
||||
Qseek (packhandle, header.dirofs, SEEK_SET);
|
||||
Qread (packhandle, info, header.dirlen);
|
||||
|
|
Loading…
Reference in a new issue