added functions to iterate through hash table and remove hash entries
[rocksndiamonds.git] / src / libgame / hash.c
index 101ec1214a30aae2faddd478c24f53321d401832..2b856f6810df38cc739c62e7b2695b5586b1cc69 100644 (file)
@@ -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)
@@ -460,3 +483,106 @@ 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);
+
+  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;
+}
+
+/*****************************************************************************/
+/* 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;
+}