src/rbtab.c

Go to the documentation of this file.
00001 /*
00002  * htab.c - table hashing routines 
00003  */
00004 
00005 #include "copyright.h"
00006 #include "config.h"
00007 
00008 #include "db.h"
00009 #include "externs.h"
00010 #include "htab.h"
00011 #include "alloc.h"
00012 
00013 #include "mudconf.h"
00014 
00015 struct string_dict_entry {
00016         char *key;
00017         void *data;
00018 };
00019 
00020 static int hrbtab_compare(char *left, char *right, void *arg)
00021 {
00022         return strcasecmp(left, right);
00023 }
00024 
00025 void hashinit(RBTAB * htab, int size)
00026 {
00027         memset(htab, 0, sizeof(RBTAB));
00028         htab->tree = rb_init((void *)hrbtab_compare, NULL);
00029         htab->last = NULL;
00030 }
00031 
00032 /*
00033  * ---------------------------------------------------------------------------
00034  * * hashreset: Reset hash table stats.
00035  */
00036 
00037 void hashreset(RBTAB * htab)
00038 {
00039         htab->checks = 0;
00040         htab->scans = 0;
00041         htab->hits = 0;
00042 }
00043 
00044 /*
00045  * ---------------------------------------------------------------------------
00046  * * hashfind: Look up an entry in a hash table and return a pointer to its
00047  * * hash data.
00048  */
00049 
00050 void *hashfind(char *str, RBTAB * htab)
00051 {
00052         int hval, numchecks;
00053         struct string_dict_entry *ent;
00054 
00055         htab->checks++;
00056         ent = rb_find(htab->tree, str);
00057         if(ent) {
00058                 return ent->data;
00059         } else
00060                 return (void *)ent;
00061 }
00062 
00063 /*
00064  * ---------------------------------------------------------------------------
00065  * * hashadd: Add a new entry to a hash table.
00066  */
00067 
00068 int hashadd(char *str, void *hashdata, RBTAB * htab)
00069 {
00070         struct string_dict_entry *ent = malloc(sizeof(struct string_dict_entry));
00071 
00072         if(rb_exists(htab->tree, str))
00073                 return (-1);
00074 
00075         ent->key = strdup(str);
00076         ent->data = hashdata;
00077 
00078         rb_insert(htab->tree, ent->key, ent);
00079         return 0;
00080 
00081 }
00082 
00083 /*
00084  * ---------------------------------------------------------------------------
00085  * * hashdelete: Remove an entry from a hash table.
00086  */
00087 
00088 void hashdelete(char *str, RBTAB * htab)
00089 {
00090         struct string_dict_entry *ent = NULL;
00091 
00092         if(!rb_exists(htab->tree, str)) {
00093                 return;
00094         }
00095         ent = rb_delete(htab->tree, str);
00096 
00097         if(ent) {
00098                 if(ent->key)
00099                         free(ent->key);
00100                 free(ent);
00101         }
00102 
00103         return;
00104 }
00105 
00106 /*
00107  * ---------------------------------------------------------------------------
00108  * * hashflush: free all the entries in a hashtable.
00109  */
00110 
00111 static int nuke_hash_ent(void *key, void *data, int depth, void *arg)
00112 {
00113         struct string_dict_entry *ent = (struct string_dict_entry *) data;
00114         free(ent->key);
00115         free(ent);
00116         return 1;
00117 }
00118 
00119 void hashflush(RBTAB * htab, int size)
00120 {
00121         rb_walk(htab->tree, WALK_POSTORDER, nuke_hash_ent, NULL);
00122         rb_destroy(htab->tree);
00123         htab->tree = rb_init((void *)hrbtab_compare, NULL);
00124         if(htab->last)
00125                 free(htab->last);
00126         htab->last = NULL;
00127 }
00128 
00129 /*
00130  * ---------------------------------------------------------------------------
00131  * * hashrepl: replace the data part of a hash entry.
00132  */
00133 
00134 int hashrepl(char *str, void *hashdata, RBTAB * htab)
00135 {
00136         struct string_dict_entry *ent;
00137 
00138         ent = rb_find(htab->tree, str);
00139         if(!ent)
00140                 return 0;
00141 
00142         ent->data = hashdata;
00143         return 1;
00144 }
00145 
00146 struct hashreplstat {
00147         void *old;
00148         void *new;
00149 };
00150 
00151 static int hashreplall_cb(void *key, void *data, int depth, void *arg)
00152 {
00153         struct string_dict_entry *ent = (struct string_dict_entry *) data;
00154         struct hashreplstat *repl = (struct hashreplstat *) arg;
00155 
00156         if(ent->data == repl->old) {
00157                 ent->data = repl->new;
00158         }
00159         return 1;
00160 }
00161 
00162 void hashreplall(void *old, void *new, RBTAB * htab)
00163 {
00164         struct hashreplstat repl = { old, new };
00165 
00166         rb_walk(htab->tree, WALK_INORDER, hashreplall_cb, &repl);
00167 }
00168 
00169 /*
00170  * ---------------------------------------------------------------------------
00171  * * hashinfo: return an mbuf with hashing stats
00172  */
00173 
00174 char *hashinfo(const char *tab_name, RBTAB * htab)
00175 {
00176         char *buff;
00177 
00178         buff = alloc_mbuf("hashinfo");
00179         sprintf(buff, "%-15s %8d", tab_name, rb_size(htab->tree));
00180         return buff;
00181 }
00182 
00183 /*
00184  * Returns the key for the first hash entry in 'htab'. 
00185  */
00186 
00187 void *hash_firstentry(RBTAB * htab)
00188 {
00189         struct string_dict_entry *ent;
00190 
00191         if(htab->last)
00192                 free(htab->last);
00193 
00194         ent = rb_search(htab->tree, SEARCH_FIRST, NULL);
00195         if(ent) {
00196                 htab->last = strdup(ent->key);
00197                 return ent->data;
00198         }
00199         htab->last = NULL;
00200 
00201         return NULL;
00202 }
00203 
00204 void *hash_nextentry(RBTAB * htab)
00205 {
00206         struct string_dict_entry *ent;
00207 
00208         if(!htab->last) {
00209                 return hash_firstentry(htab);
00210         }
00211 
00212         ent = rb_search(htab->tree, SEARCH_GT, htab->last);
00213         free(htab->last);
00214 
00215         if(ent) {
00216                 htab->last = strdup(ent->key);
00217                 return ent->data;
00218         } else {
00219                 htab->last = NULL;
00220                 return NULL;
00221         }
00222 }
00223 
00224 char *hash_firstkey(RBTAB * htab)
00225 {
00226         struct string_dict_entry *ent;
00227         if(htab->last)
00228                 free(htab->last);
00229 
00230         ent = rb_search(htab->tree, SEARCH_FIRST, NULL);
00231         if(ent) {
00232                 htab->last = strdup(ent->key);
00233                 return ent->key;
00234         }
00235         htab->last = NULL;
00236 
00237         return NULL;
00238 }
00239 
00240 char *hash_nextkey(RBTAB * htab)
00241 {
00242         struct string_dict_entry *ent;
00243 
00244         if(!htab->last) {
00245                 return hash_firstkey(htab);
00246         }
00247 
00248         ent = rb_search(htab->tree, SEARCH_NEXT, htab->last);
00249         free(htab->last);
00250 
00251         if(ent) {
00252                 htab->last = strdup(ent->key);
00253                 return ent->key;
00254         } else {
00255                 htab->last = NULL;
00256                 return NULL;
00257         }
00258 }

Generated on Mon May 28 04:25:25 2007 for BattletechMUX by  doxygen 1.4.7