/* ** hash.c for elsh ** ** Started on Fri Jan 24 20:26:18 2003 mayhem ** Last update Sun Jun 29 11:47:50 2003 mayhem */ #include "libhash.h" /* Initialize the hash table */ int hash_init(hash_t *h, int size) { HASHALLOC(h->ent, size * sizeof(hashent_t), -1); h->size = size; return (0); } /* Destroy a hash table */ void hash_destroy(hash_t *h) { free(h->ent); } /* Add an entry to the hash table */ int hash_add(hash_t *h, char *key, void *data) { hashent_t *actual; hashent_t *new; char *backup; u_int index; new = NULL; for (index = 0, backup = key; *backup; backup++) index += *backup; index %= h->size; if (h->ent[index].key == NULL) { h->ent[index].key = key; h->ent[index].data = data; } else { HASHALLOC(new, sizeof(hashent_t), -1); new->key = key; new->data = data; actual = h->ent + index; while (actual->next) actual = actual->next; actual->next = new; } return (0); } /* Delete an entry from the hash table */ int hash_del(hash_t *h, char *key) { hashent_t *actual; hashent_t *todel; /* Check the first entry for this hash */ actual = hash_get_head(h, key); if (actual->key != NULL && !strcmp(actual->key, key)) { if (actual->next) { todel = actual->next; *actual = *actual->next; free(todel); } else bzero(actual, sizeof (hashent_t)); return (0); } /* Looking for the good entry in the list for this hash value */ while (actual->next != NULL && actual->next->key != NULL && strcmp(actual->next->key, key)) actual = actual->next; /* Not found */ if (!actual->next) return (-1); /* Found */ todel = actual->next; actual->next = actual->next->next; free(todel); return (0); } /* Retrieve the metadata for a given key */ void *hash_get(hash_t *h, char *key) { hashent_t *actual; actual = hash_get_head(h, key); while (actual != NULL && actual->key != NULL && strcmp(actual->key, key)) actual = actual->next; return (actual != NULL ? actual->data : NULL); } /* Change the metadata for an existing entry, giving its key */ int hash_set(hash_t *h, char *key, void *data) { hashent_t *ent; ent = hash_get_ent(h, key); if (!ent) return (-1); ent->data = data; return (0); } /* Retrieve the -entry- for a given key */ hashent_t *hash_get_ent(hash_t *h, char *key) { hashent_t *actual; actual = hash_get_head(h, key); while (actual != NULL && actual->key != NULL && strcmp(actual->key, key)) actual = actual->next; return (actual); } /* Retreive a Hash entry head giving the key */ hashent_t *hash_get_head(hash_t *h, char *backup) { u_int index; for (index = 0; *backup; backup++) index += *backup; return (&h->ent[index % h->size]); } /* XXX: comment it and pleaze check realloc return values ;> */ char** hash_get_keys(hash_t *h, int* n) { int j,i=1; char** keys=NULL; hashent_t* entry; for (j=0; j < h->size; j++) { entry=&h->ent[j]; while ((entry!=NULL)&&(entry->key!=NULL)) { /* ** XXX: create __DEBUG_GETKEYS__ at the beginning of ** elfsh.h instead of using __DEBUG__ */ #if __DEBUG__ printf ("key = %s\n",entry->key); #endif keys=realloc(keys,i*sizeof(char*)); keys[i-1]=entry->key; entry=entry->next; i++; } } keys=realloc(keys,i*sizeof(char*)); keys[i-1]=NULL; *n = i-1; return keys; } /* Print the hash table (DEBUG PURPOSE) */ void hash_print(hash_t *h) { hashent_t *actual; int index; puts(".::. Printing hash .::. "); for (index = 0; index < h->size; index++) { for (actual = &h->ent[index]; actual != NULL && actual->key != NULL; actual = actual->next) printf(" ENT [%u] key = %s ; data = %p ; next = %p\n", index, actual->key, actual->data, actual->next); } }