/* SillyMUD Distribution V1.1b (c) 1993 SillyMUD Developement See license.doc for distribution terms. SillyMUD is based on DIKUMUD */ #include <stdio.h> #include "protos.h" #define HASH_KEY(ht,key) ( (((unsigned int)(key)) * 17) % (ht)->table_size ) void init_hash_table(struct hash_header *ht, int rec_size, int table_size) { ht->rec_size = rec_size; ht->table_size = table_size; ht->buckets = (void*)calloc(sizeof(struct hash_link**), table_size); ht->keylist = (void*)malloc(sizeof(ht->keylist)*(ht->klistsize=128)); ht->klistlen = 0; } void init_world(struct room_data *room_db[]) { bzero(room_db, sizeof(struct room_data *) * WORLD_SIZE); /* zero out the world */ } void destroy_hash_table(struct hash_header *ht, void (*gman)()) { int i; struct hash_link *scan, *temp; for (i=0; i<ht->table_size; i++) for (scan = ht->buckets[i]; scan; ) { temp = scan->next; (*gman)(scan->data); free(scan); scan = temp; } free(ht->buckets); free(ht->keylist); } void _hash_enter(struct hash_header *ht, int key, void *data) { /* precondition: there is no entry for <key> yet */ struct hash_link *temp; int i; temp = (struct hash_link *)malloc(sizeof(struct hash_link)); temp->key = key; temp->next = ht->buckets[HASH_KEY(ht,key)]; temp->data = data; ht->buckets[HASH_KEY(ht,key)] = temp; if (ht->klistlen >= ht->klistsize) { ht->keylist = (void*)realloc(ht->keylist,sizeof(*ht->keylist)* (ht->klistsize*=2)); } for (i=ht->klistlen; i>=0; i--) { if (ht->keylist[i-1]<key) { ht->keylist[i] = key; break; } ht->keylist[i] = ht->keylist[i-1]; } ht->klistlen++; } struct room_data *room_find( struct room_data *room_db[], int key) { return((key<WORLD_SIZE&&key>-1)?room_db[key]:0); } void *hash_find(struct hash_header *ht, int key) { struct hash_link *scan; scan = ht->buckets[HASH_KEY(ht,key)]; while (scan && scan->key != key) scan = scan->next; return scan ? scan->data : NULL; } int room_enter(struct room_data *rb[], int key, struct room_data *rm) { struct room_data *temp; temp = room_find(rb, key); if (temp) return(0); rb[key] = rm; return(1); } int hash_enter(struct hash_header *ht, int key, void *data) { void *temp; temp = hash_find(ht, key); if (temp) return 0; _hash_enter(ht, key, data); return 1; } struct room_data *room_find_or_create(struct room_data *rb[], int key) { struct room_data *rv; rv = room_find(rb, key); if (rv) return rv; rv = (struct room_data *)malloc(sizeof(struct room_data)); rb[key] = rv; return rv; } void *hash_find_or_create(struct hash_header *ht, int key) { void *rval; rval = hash_find(ht, key); if (rval) return rval; rval = (void*)malloc(ht->rec_size); _hash_enter(ht,key,rval); return rval; } int room_remove(struct room_data *rb[], int key) { struct room_data *tmp; tmp = room_find(rb, key); if (tmp) { rb[key] = 0; free(tmp); } return(0); } void *hash_remove(struct hash_header *ht, int key) { struct hash_link **scan; scan = ht->buckets +HASH_KEY(ht,key); while (*scan && (*scan)->key != key) scan = &(*scan)->next; if (*scan) { int i; struct hash_link *temp, *aux; temp = (*scan)->data; aux = *scan; *scan = aux->next; free(aux); for (i=0; i<ht->klistlen; i++) if (ht->keylist[i]==key) break; if (i<ht->klistlen) { bcopy(ht->keylist+i+1, ht->keylist+i, (ht->klistlen-i)*sizeof(*ht->keylist)); ht->klistlen--; } return temp; } return NULL; } void room_iterate(struct room_data *rb[], void (*func)(), void *cdata) { register int i; for (i=0; i<WORLD_SIZE; i++) { struct room_data *temp; temp = room_find(rb, i); if (temp) { (*func)(i, temp, cdata); } } } void hash_iterate(struct hash_header *ht, void (*func)(), void *cdata) { int i; for (i=0; i<ht->klistlen; i++) { void *temp; register int key; key = ht->keylist[i]; temp = hash_find(ht, key); (*func)(key, temp, cdata); if (ht->keylist[i]!=key) /* They must have deleted this room */ i--; /* Hit this slot again. */ } }