diff options
Diffstat (limited to 'libhashtable/libhashtable.c')
-rw-r--r-- | libhashtable/libhashtable.c | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/libhashtable/libhashtable.c b/libhashtable/libhashtable.c new file mode 100644 index 0000000..c4ac2d3 --- /dev/null +++ b/libhashtable/libhashtable.c @@ -0,0 +1,115 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "hashtable.h" + +/* +struct entry {//linked list node. + char *original; + char *target; + struct entry *prev;// doubly linked list. why? + struct entry *next; +}; + +struct hitem {//dunno why I don't just have this as a linked list. + struct entry *ll; +}; + +struct hashtable { + int kl;//number of keys in the table + struct hitem **bucket; + int *keys; +}; +*/ + +unsigned short hash(char *v) {//maybe use a seeded rand()? :) Thanks FreeArtMan + unsigned short h=0; + h=((*v)<<8)+(v?*(v+1):0); + srand(h); + return rand(); +} + +void inittable(struct hashtable *ht,int tsize) { + int i; + ht->bucket=malloc(sizeof(char *)*tsize); + ht->kl=0; + ht->keys=malloc(sizeof(int *)*tsize); + if(!ht) { + fprintf(stderr,"malloc error 6 in hash table.\n"); + return; + } + for(i=0;i<tsize;i++) { + ht->bucket[i]=0; + } +} + +//this seems too complicated. +int ht_setkey(struct hashtable *ht,char *key,char *value) { + unsigned short h=hash(key); + struct entry *tmp; + int i; + for(i=0;i<ht->kl;i++) { + if(ht->keys[i]==h) break; + } + ht->keys[i]=h; + ht->kl=(ht->kl)>i+1?ht->kl:i+1; + if(!ht->bucket[h]) { //empty bucket! + //add this to the list of used buckets so we can easily + //use that list later for stuff. + if(!(ht->bucket[h]=malloc(sizeof(struct hitem)))) return 1; + ht->bucket[h]->ll=0; + //we now have a valid hashtable entry and a NULL ll in it. + //don't bother with the new ll entry yet... + } + if((tmp=ll_getentry(ht->bucket[h]->ll,key)) != NULL) { + //we found this alias in the ll. now to replace the value + free(tmp->target); + if(!(tmp->target=strdup(value))) return 2; + return 0; + } + if(ht->bucket[h]->ll == NULL) { + if(!(ht->bucket[h]->ll=malloc(sizeof(struct entry)))) return 3; + ht->bucket[h]->ll->next=0; + ht->bucket[h]->ll->prev=0; + if(!(ht->bucket[h]->ll->original=strdup(key))) return 4; + if(!(ht->bucket[h]->ll->target=strdup(value))) return 5; + } else { + //go to the end and add another entry to the ll. + for(tmp=ht->bucket[h]->ll;tmp->next;tmp=tmp->next); + if(!(tmp->next=malloc(sizeof(struct entry)))) return 6; + tmp->next->prev=tmp; + tmp=tmp->next; + if(!(tmp->original=strdup(key))) return 7; + if(!(tmp->target=strdup(value))) return 8; + tmp->next=0; + } + return 0; +} + +struct entry *ll_getentry(struct entry *start,char *msg) { + struct entry *m; + if(!msg) return NULL; + if(!start) return NULL; + for(m=start;m;m=m->next) { + if(!strncmp(msg,m->original,strlen(m->original)) && (msg[strlen(m->original)]==' ' || msg[strlen(m->original)] == 0)) {//this allows !c to get called when using !c2 if !c2 is defined after !c. >_> + return m; + } + } + return NULL; +} + +struct entry *ht_getentry(struct hashtable *ht,char *key) { + unsigned short h=hash(key); + if(!ht->bucket[h]) return NULL; + return ht->bucket[h]->ll; +} + +struct entry *ht_getnode(struct hashtable *ht,char *msg) { + return ll_getentry(ht_getentry(ht,msg),msg); +} + +//you'll probably want to use me. +char *ht_getvalue(struct hashtable *ht,char *msg) { + struct entry *tmp=ll_getentry(ht_getentry(ht,msg),msg); + return tmp?tmp->target:0; +} |