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:
Bill Currie 2001-03-05 05:11:26 +00:00
parent aad21e3c00
commit f40b361fb3
8 changed files with 78 additions and 50 deletions

View file

@ -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);

View file

@ -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;

View file

@ -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++)

View file

@ -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;

View file

@ -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);
}
/*

View file

@ -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

View file

@ -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;

View file

@ -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);