diff --git a/include/QF/csqc.h b/include/QF/csqc.h index b6bfdda63..8ff3eaa3a 100644 --- a/include/QF/csqc.h +++ b/include/QF/csqc.h @@ -47,6 +47,8 @@ void Cvar_Progs_Init (struct progs_s *pr); void File_Progs_Init (struct progs_s *pr); +void Hash_Progs_Init (struct progs_s *pr); + void InputLine_Progs_Init (struct progs_s *pr); void InputLine_Progs_SetDraw (struct progs_s *pr, void (*draw)(struct inputline_s*)); diff --git a/libs/gamecode/builtins/Makefile.am b/libs/gamecode/builtins/Makefile.am index 92c0203df..1b9a78680 100644 --- a/libs/gamecode/builtins/Makefile.am +++ b/libs/gamecode/builtins/Makefile.am @@ -10,5 +10,6 @@ libQFgamecode_builtins_la_SOURCES= pr_cmds.c libQFcsqc_la_LDFLAGS= -version-info 1:0:0 libQFcsqc_la_SOURCES=\ - bi_cbuf.c bi_cmd.c bi_cvar.c bi_file.c bi_init.c bi_inputline.c \ + bi_cbuf.c bi_cmd.c bi_cvar.c bi_file.c bi_hash.c bi_init.c \ + bi_inputline.c \ bi_qfile.c bi_qfs.c bi_string.c bi_strhash.c diff --git a/libs/gamecode/builtins/bi_hash.c b/libs/gamecode/builtins/bi_hash.c new file mode 100644 index 000000000..9bb1f358f --- /dev/null +++ b/libs/gamecode/builtins/bi_hash.c @@ -0,0 +1,328 @@ +/* + bi_hash.c + + QuakeC hash table api + + Copyright (C) 2002 Bill Currie + + Author: Bill Currie + Date: 2003/4/7 + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +static __attribute__ ((unused)) const char rcsid[] = + "$Id$"; + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#include + +#include "QF/csqc.h" +#include "QF/hash.h" +#include "QF/progs.h" + +typedef struct bi_hashtab_s { + struct bi_hashtab_s *next; + struct bi_hashtab_s **prev; + progs_t *pr; + hashtab_t *tab; + func_t gk; + func_t gh; + func_t cmp; + func_t f; + pointer_t ud; +} bi_hashtab_t; + +typedef struct { + bi_hashtab_t *tabs; +} hash_resources_t; + +static const char * +bi_get_key (void *key, void *_ht) +{ + bi_hashtab_t *ht = (bi_hashtab_t *)_ht; + P_INT (ht->pr, 0) = (long) (key); + P_INT (ht->pr, 1) = ht->ud; + PR_ExecuteProgram (ht->pr, ht->gk); + return G_STRING (ht->pr, OFS_RETURN); +} + +static unsigned long +bi_get_hash (void *key, void *_ht) +{ + bi_hashtab_t *ht = (bi_hashtab_t *)_ht; + P_INT (ht->pr, 0) = (long) (key); + P_INT (ht->pr, 1) = ht->ud; + PR_ExecuteProgram (ht->pr, ht->gh); + return R_INT (ht->pr); +} + +static int +bi_compare (void *key1, void *key2, void *_ht) +{ + bi_hashtab_t *ht = (bi_hashtab_t *)_ht; + P_INT (ht->pr, 0) = (long) (key1); + P_INT (ht->pr, 1) = (long) (key2); + P_INT (ht->pr, 2) = ht->ud; + PR_ExecuteProgram (ht->pr, ht->cmp); + return R_INT (ht->pr); +} + +static void +bi_free (void *key, void *_ht) +{ + bi_hashtab_t *ht = (bi_hashtab_t *)_ht; + P_INT (ht->pr, 0) = (long) (key); + P_INT (ht->pr, 1) = ht->ud; + PR_ExecuteProgram (ht->pr, ht->f); +} + +static void +bi_Hash_NewTable (progs_t *pr) +{ + hash_resources_t *res = PR_Resources_Find (pr, "Hash"); + int tsize = P_INT (pr, 0); + const char *(*gk)(void*,void*); + void (*f)(void*,void*); + bi_hashtab_t *ht; + + ht = PR_Zone_Malloc (pr, sizeof (bi_hashtab_t)); + ht->pr = pr; + ht->gk = P_FUNCTION (pr, 1); + ht->f = P_FUNCTION (pr, 2); + ht->ud = P_INT (pr, 3); // don't convert pointer for speed reasons + + ht->next = res->tabs; + ht->prev = &res->tabs; + if (ht->next) + ht->next->prev = &ht->next; + + gk = ht->gk ? bi_get_key : 0; + f = ht->f ? bi_free : 0; + ht->tab = Hash_NewTable (tsize, gk, f, ht); + RETURN_POINTER (pr, ht); +} + +static void +bi_Hash_SetHashCompare (progs_t *pr) +{ + bi_hashtab_t *ht = &G_STRUCT (pr, bi_hashtab_t, 0); + unsigned long (*gh)(void*,void*); + int (*cmp)(void*,void*,void*); + + ht->gh = P_FUNCTION (pr, 1); + ht->cmp = P_FUNCTION (pr, 2); + gh = ht->gh ? bi_get_hash : 0; + cmp = ht->cmp ? bi_compare : 0; + Hash_SetHashCompare (ht->tab, gh, cmp); +} + +static void +bi_Hash_DelTable (progs_t *pr) +{ + bi_hashtab_t *ht = &G_STRUCT (pr, bi_hashtab_t, 0); + + Hash_DelTable (ht->tab); + *ht->prev = ht->next; + PR_Zone_Free (pr, ht); +} + +static void +bi_Hash_FlushTable (progs_t *pr) +{ + bi_hashtab_t *ht = &G_STRUCT (pr, bi_hashtab_t, 0); + + Hash_FlushTable (ht->tab); +} + +static void +bi_Hash_Add (progs_t *pr) +{ + bi_hashtab_t *ht = &G_STRUCT (pr, bi_hashtab_t, 0); + + R_INT (pr) = Hash_Add (ht->tab, (void *) P_INT (pr, 1)); +} + +static void +bi_Hash_AddElement (progs_t *pr) +{ + bi_hashtab_t *ht = &G_STRUCT (pr, bi_hashtab_t, 0); + + R_INT (pr) = Hash_Add (ht->tab, (void *) P_INT (pr, 1)); +} + +static void +bi_Hash_Find (progs_t *pr) +{ + bi_hashtab_t *ht = &G_STRUCT (pr, bi_hashtab_t, 0); + + R_INT (pr) = (long) Hash_Find (ht->tab, P_STRING (pr, 1)); +} + +static void +bi_Hash_FindElement (progs_t *pr) +{ + bi_hashtab_t *ht = &G_STRUCT (pr, bi_hashtab_t, 0); + + R_INT (pr) = (long) Hash_FindElement (ht->tab, (void *) P_INT (pr, 1)); +} + +static void +bi_Hash_FindList (progs_t *pr) +{ + bi_hashtab_t *ht = &G_STRUCT (pr, bi_hashtab_t, 0); + void **list, **l; + pr_type_t *pr_list; + int count; + + list = Hash_FindList (ht->tab, P_STRING (pr, 1)); + for (count = 1, l = list; *l; l++) + count++; + pr_list = PR_Zone_Malloc (pr, count * sizeof (pr_type_t)); + for (count = 0, l = list; *l; l++) + pr_list[count++].integer_var = (long) *l; + free (list); + RETURN_POINTER (pr, pr_list); +} + +static void +bi_Hash_FindElementList (progs_t *pr) +{ + bi_hashtab_t *ht = &G_STRUCT (pr, bi_hashtab_t, 0); + void **list, **l; + pr_type_t *pr_list; + int count; + + list = Hash_FindElementList (ht->tab, (void *) P_INT (pr, 1)); + for (count = 1, l = list; *l; l++) + count++; + pr_list = PR_Zone_Malloc (pr, count * sizeof (pr_type_t)); + for (count = 0, l = list; *l; l++) + pr_list[count++].integer_var = (long) *l; + free (list); + RETURN_POINTER (pr, pr_list); +} + +static void +bi_Hash_Del (progs_t *pr) +{ + bi_hashtab_t *ht = &G_STRUCT (pr, bi_hashtab_t, 0); + + R_INT (pr) = (long) Hash_Del (ht->tab, P_STRING (pr, 1)); +} + +static void +bi_Hash_DelElement (progs_t *pr) +{ + bi_hashtab_t *ht = &G_STRUCT (pr, bi_hashtab_t, 0); + + R_INT (pr) = (long) Hash_DelElement (ht->tab, (void *) P_INT (pr, 1)); +} + +static void +bi_Hash_Free (progs_t *pr) +{ + bi_hashtab_t *ht = &G_STRUCT (pr, bi_hashtab_t, 0); + + Hash_Free (ht->tab, (void *) P_INT (pr, 1)); +} + +static void +bi_Hash_String (progs_t *pr) +{ + R_INT (pr) = Hash_String (P_STRING (pr, 0)); +} + +static void +bi_Hash_Buffer (progs_t *pr) +{ + R_INT (pr) = Hash_Buffer (P_POINTER (pr, 0), P_INT (pr, 1)); +} + +static void +bi_Hash_GetList (progs_t *pr) +{ + bi_hashtab_t *ht = &G_STRUCT (pr, bi_hashtab_t, 0); + void **list, **l; + pr_type_t *pr_list; + int count; + + list = Hash_GetList (ht->tab); + for (count = 1, l = list; *l; l++) + count++; + pr_list = PR_Zone_Malloc (pr, count * sizeof (pr_type_t)); + for (count = 0, l = list; *l; l++) + pr_list[count++].integer_var = (long) *l; + free (list); + RETURN_POINTER (pr, pr_list); +} + +static void +bi_Hash_Stats (progs_t *pr) +{ + bi_hashtab_t *ht = &G_STRUCT (pr, bi_hashtab_t, 0); + + Hash_Stats (ht->tab); +} + +static void +bi_hash_clear (progs_t *pr, void *data) +{ + hash_resources_t *res = (hash_resources_t *) data; + bi_hashtab_t *ht; + + for (ht = res->tabs; ht; ht = ht->next) + Hash_DelTable (ht->tab); + res->tabs = 0; +} + +void +Hash_Progs_Init (progs_t *pr) +{ + hash_resources_t *res = malloc (sizeof (hash_resources_t)); + res->tabs = 0; + + PR_Resources_Register (pr, "Hash", res, bi_hash_clear); + PR_AddBuiltin (pr, "Hash_NewTable", bi_Hash_NewTable, -1); + PR_AddBuiltin (pr, "Hash_SetHashCompare", bi_Hash_SetHashCompare, -1); + PR_AddBuiltin (pr, "Hash_DelTable", bi_Hash_DelTable, -1); + PR_AddBuiltin (pr, "Hash_FlushTable", bi_Hash_FlushTable, -1); + PR_AddBuiltin (pr, "Hash_Add", bi_Hash_Add, -1); + PR_AddBuiltin (pr, "Hash_AddElement", bi_Hash_AddElement, -1); + PR_AddBuiltin (pr, "Hash_Find", bi_Hash_Find, -1); + PR_AddBuiltin (pr, "Hash_FindElement", bi_Hash_FindElement, -1); + PR_AddBuiltin (pr, "Hash_FindList", bi_Hash_FindList, -1); + PR_AddBuiltin (pr, "Hash_FindElementList", bi_Hash_FindElementList, -1); + PR_AddBuiltin (pr, "Hash_Del", bi_Hash_Del, -1); + PR_AddBuiltin (pr, "Hash_DelElement", bi_Hash_DelElement, -1); + PR_AddBuiltin (pr, "Hash_Free", bi_Hash_Free, -1); + PR_AddBuiltin (pr, "Hash_String", bi_Hash_String, -1); + PR_AddBuiltin (pr, "Hash_Buffer", bi_Hash_Buffer, -1); + PR_AddBuiltin (pr, "Hash_GetList", bi_Hash_GetList, -1); + PR_AddBuiltin (pr, "Hash_Stats", bi_Hash_Stats, -1); +} diff --git a/libs/gamecode/builtins/bi_init.c b/libs/gamecode/builtins/bi_init.c index 9a4f20503..756daf002 100644 --- a/libs/gamecode/builtins/bi_init.c +++ b/libs/gamecode/builtins/bi_init.c @@ -35,8 +35,10 @@ static __attribute__ ((unused)) const char rcsid[] = #include "QF/progs.h" static void (*const cbuf_progs_init)(progs_t *) = Cbuf_Progs_Init; -static void (*const cvar_progs_init)(progs_t *) = Cvar_Progs_Init; static void (*const cmd_progs_init)(progs_t *) = Cmd_Progs_Init; +static void (*const cvar_progs_init)(progs_t *) = Cvar_Progs_Init; +static void (*const file_progs_init)(progs_t *) = File_Progs_Init; +static void (*const hash_progs_init)(progs_t *) = Hash_Progs_Init; static void (*const inputline_progs_init)(progs_t *) = InputLine_Progs_Init; static void (*const qfile_progs_init)(progs_t *, int) = QFile_Progs_Init; static void (*const qfs_progs_init)(progs_t *) = QFS_Progs_Init; diff --git a/ruamoko/include/hash.h b/ruamoko/include/hash.h new file mode 100644 index 000000000..2eca3e649 --- /dev/null +++ b/ruamoko/include/hash.h @@ -0,0 +1,25 @@ +#ifndef __ruamoko_hash_h +#define __ruamoko_hash_h + +struct _hashtab_t = {}; +typedef _hashtab_t [] hashtab_t; + +hashtab_t () Hash_NewTable; +void () Hash_SetHashCompare; +void () Hash_DelTable; +void () Hash_FlushTable; +integer () Hash_Add; +integer () Hash_AddElement; +(void []) () Hash_Find; +(void []) () Hash_FindElement; +(void [][]) () Hash_FindList; +(void [][]) () Hash_FindElementList; +(void []) () Hash_Del; +(void []) () Hash_DelElement; +void () Hash_Free; +integer () Hash_String; +integer () Hash_Buffer; +(void [][]) () Hash_GetList; +void () Hash_Stats; + +#endif __ruamoko_hash_h diff --git a/ruamoko/lib/Makefile.am b/ruamoko/lib/Makefile.am index 513e3887f..30e354a30 100644 --- a/ruamoko/lib/Makefile.am +++ b/ruamoko/lib/Makefile.am @@ -27,9 +27,9 @@ EXTRA_LIBRARIES= $(ruamoko_libs) $(QFCC) $(QCFLAGS) $(QCPPFLAGS) -c -o $@ $< libr_a_SOURCES=\ - crudefile.r debug.r entities.r infokey.r math.r message.r nq_message.r \ - physics.r qfile.r qw_message.r qw_physics.r qw_sys.r sound.r string.r \ - system.r Object.r Array.r Entity.r Point.r Size.r Rect.r + crudefile.r debug.r hash.r entities.r infokey.r math.r message.r \ + nq_message.r physics.r qfile.r qw_message.r qw_physics.r qw_sys.r sound.r \ + string.r system.r Object.r Array.r Entity.r Point.r Size.r Rect.r libr_a_AR=$(PAK) -cf libgui_a_SOURCES=\ diff --git a/ruamoko/lib/hash.r b/ruamoko/lib/hash.r new file mode 100644 index 000000000..85756041c --- /dev/null +++ b/ruamoko/lib/hash.r @@ -0,0 +1,19 @@ +#include "hash.h" + +hashtab_t () Hash_NewTable = #0; +void () Hash_SetHashCompare = #0; +void () Hash_DelTable = #0; +void () Hash_FlushTable = #0; +integer () Hash_Add = #0; +integer () Hash_AddElement = #0; +(void []) () Hash_Find = #0; +(void []) () Hash_FindElement = #0; +(void [][]) () Hash_FindList = #0; +(void [][]) () Hash_FindElementList = #0; +(void []) () Hash_Del = #0; +(void []) () Hash_DelElement = #0; +void () Hash_Free = #0; +integer () Hash_String = #0; +integer () Hash_Buffer = #0; +(void [][]) () Hash_GetList = #0; +void () Hash_Stats = #0;