X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Flibgame%2Fhash.c;h=b3595ad4ce4517f8f4b50ab5a7ee847ae1513422;hb=edaa850fd2d2cae7ec31961fae3d56487e710c71;hp=101ec1214a30aae2faddd478c24f53321d401832;hpb=1fd06503004016a245257a08748473d749559586;p=rocksndiamonds.git diff --git a/src/libgame/hash.c b/src/libgame/hash.c index 101ec121..b3595ad4 100644 --- a/src/libgame/hash.c +++ b/src/libgame/hash.c @@ -268,6 +268,29 @@ hashtable_change(struct hashtable *h, void *k, void *v) return 0; } +/*****************************************************************************/ +int /* checks if key exists */ +hashtable_exists(struct hashtable *h, void *k) +{ + struct entry *e; + unsigned int hashvalue, index; + + hashvalue = hash(h, k); + index = indexFor(h->tablelength, hashvalue); + e = h->table[index]; + + while (e != NULL) + { + /* Check hash value to short circuit heavier comparison */ + if ((hashvalue == e->h) && (h->eqfn(k, e->k))) + return 1; + + e = e->next; + } + + return 0; +} + /*****************************************************************************/ void * /* returns value associated with key */ hashtable_search(struct hashtable *h, void *k) @@ -400,18 +423,24 @@ hashtable_iterator(struct hashtable *h) /* key - return the key of the (key, value) pair at the current position */ void * -hashtable_iterator_key(struct hashtable_itr *i) +hashtable_iterator_key(struct hashtable_itr *itr) { - return i->e->k; + if (itr == NULL || itr->e == NULL) + return NULL; + + return itr->e->k; } /*****************************************************************************/ /* value - return the value of the (key, value) pair at the current position */ void * -hashtable_iterator_value(struct hashtable_itr *i) +hashtable_iterator_value(struct hashtable_itr *itr) { - return i->e->v; + if (itr == NULL || itr->e == NULL) + return NULL; + + return itr->e->v; } /*****************************************************************************/ @@ -460,3 +489,110 @@ hashtable_iterator_advance(struct hashtable_itr *itr) return -1; } + +/*****************************************************************************/ +/* call function for all hashtable entries */ +void +hashtable_foreach(struct hashtable *h, hashtable_fn fn, void *userdata) +{ + if (h == NULL) + return; + + if (hashtable_count(h) == 0) + return; + + struct hashtable_itr *itr = hashtable_iterator(h); + + do + { + fn(hashtable_iterator_key(itr), hashtable_iterator_value(itr), userdata); + } + while (hashtable_iterator_advance(itr)); + + free(itr); +} + +/*****************************************************************************/ +/* call function for all hashtable entries and remove them, if function returned 1 */ +unsigned int +hashtable_foreach_remove(struct hashtable *h, hashtable_remove_fn fn, void *userdata) +{ + if (h == NULL) + return 0; + + if (hashtable_count(h) == 0) + return 0; + + struct hashtable *remove = create_hashtable(h->hashfn, h->eqfn, NULL, NULL); + struct hashtable_itr *itr = hashtable_iterator(h); + + do + { + if (fn(hashtable_iterator_key(itr), hashtable_iterator_value(itr), userdata)) + hashtable_insert(remove, hashtable_iterator_key(itr), "1"); + } + while (hashtable_iterator_advance(itr)); + + free(itr); + + unsigned int num_removed = 0; + + if (hashtable_count(remove) > 0) + { + struct hashtable_itr *itr_remove = hashtable_iterator(remove); + + do + { + hashtable_remove(h, hashtable_iterator_key(itr_remove)); + num_removed++; + } + while (hashtable_iterator_advance(itr_remove)); + + free(itr_remove); + } + + hashtable_destroy(remove); + + return num_removed; +} + +/*****************************************************************************/ +/* remove_all hashtable entries */ +unsigned int +hashtable_remove_all(struct hashtable *h) +{ + /* TODO: this function should directly remove all hashtable entries */ + + if (h == NULL) + return 0; + + if (hashtable_count(h) == 0) + return 0; + + struct hashtable *remove = create_hashtable(h->hashfn, h->eqfn, NULL, NULL); + struct hashtable_itr *itr = hashtable_iterator(h); + + do + { + hashtable_insert(remove, hashtable_iterator_key(itr), "1"); + } + while (hashtable_iterator_advance(itr)); + + free(itr); + + struct hashtable_itr *itr_remove = hashtable_iterator(remove); + unsigned int num_removed = 0; + + do + { + hashtable_remove(h, hashtable_iterator_key(itr_remove)); + num_removed++; + } + while (hashtable_iterator_advance(itr_remove)); + + free(itr_remove); + + hashtable_destroy(remove); + + return num_removed; +}