struct hashtable {
unsigned int tablelength;
+ unsigned int flags;
struct entry **table;
unsigned int entrycount;
unsigned int loadlimit;
};
/*
-Credit for primes table: Aaron Krowne
- http://br.endernet.org/~akrowne/
- http://planetmath.org/encyclopedia/GoodHashTablePrimes.html
-*/
+ * Credit for primes table: Aaron Krowne
+ * https://planetmath.org/goodhashtableprimes
+ */
static const unsigned int primes[] = {
-53, 97, 193, 389,
+11, 23, 53, 97, 193, 389,
769, 1543, 3079, 6151,
12289, 24593, 49157, 98317,
196613, 393241, 786433, 1572869,
struct hashtable *
create_hashtable(unsigned int minsize,
unsigned int (*hashf) (void*),
- int (*eqf) (void*,void*))
+ int (*eqf) (void*,void*),
+ unsigned int flags)
{
struct hashtable *h;
unsigned int pindex, size = primes[0];
goto err1;
h->tablelength = size;
+ h->flags = flags;
h->primeindex = pindex;
h->entrycount = 0;
h->hashfn = hashf;
*pE = e->next;
h->entrycount--;
v = e->v;
- free(e->k);
+ if (h->flags & HASHTABLE_FREE_KEY)
+ free(e->k);
free(e);
return v;
}
}
/*****************************************************************************/
-/* destroy */
-void
-hashtable_destroy(struct hashtable *h, int free_values)
+int
+hashtable_iterate(struct hashtable *h,
+ int (*func)(const void *k, void *v, void *arg), void *arg)
{
+ int ret;
unsigned int i;
struct entry *e, *f;
struct entry **table = h->table;
- if (free_values)
+
+ for (i = 0; i < h->tablelength; i++)
{
- for (i = 0; i < h->tablelength; i++)
+ e = table[i];
+ while (e)
{
- e = table[i];
- while (NULL != e)
- { f = e; e = e->next; free(f->k); free(f->v); free(f); }
+ f = e;
+ e = e->next;
+ ret = func(f->k, f->v, arg);
+ if (ret)
+ return ret;
}
}
- else
+
+ return 0;
+}
+
+/*****************************************************************************/
+/* destroy */
+void
+hashtable_destroy(struct hashtable *h)
+{
+ unsigned int i;
+ struct entry *e, *f;
+ struct entry **table = h->table;
+
+ for (i = 0; i < h->tablelength; i++)
{
- for (i = 0; i < h->tablelength; i++)
+ e = table[i];
+ while (NULL != e)
{
- e = table[i];
- while (NULL != e)
- { f = e; e = e->next; free(f->k); free(f); }
+ f = e;
+ e = e->next;
+ if (h->flags & HASHTABLE_FREE_KEY)
+ free(f->k);
+ if (h->flags & HASHTABLE_FREE_VALUE)
+ free(f->v);
+ free(f);
}
}
free(h->table);
* @param minsize minimum initial size of hashtable
* @param hashfunction function for hashing keys
* @param key_eq_fn function for determining key equality
+ * @param flags flags HASHTABLE_*
* @return newly created hashtable or NULL on failure
*/
+/* Let hashtable_destroy() free the entries' values. */
+#define HASHTABLE_FREE_VALUE (1U << 0)
+/* Let hashtable_remove() and hashtable_destroy() free the entries' keys. */
+#define HASHTABLE_FREE_KEY (1U << 1)
+
struct hashtable *
create_hashtable(unsigned int minsize,
unsigned int (*hashfunction) (void*),
- int (*key_eq_fn) (void*,void*));
+ int (*key_eq_fn) (void*,void*),
+ unsigned int flags
+);
/*****************************************************************************
* hashtable_insert
unsigned int
hashtable_count(struct hashtable *h);
+/*****************************************************************************
+ * hashtable_iterate
+
+ * @name hashtable_iterate
+ * @param h the hashtable
+ * @param func function to call for each entry
+ * @param arg user supplied parameter for func
+ * @return 0 if okay, non-zero return value of func (and iteration
+ * was aborted)
+ *
+ * Iterates over all entries in the hashtable and calls func with the
+ * key, value, and the user supplied parameter.
+ * func returning a non-zero value will abort the iteration. In case func is
+ * removing an entry other than itself from the hashtable, it must return a
+ * non-zero value in order to abort the iteration. Inserting entries is
+ * allowed, but it is undefined whether func will be called for those new
+ * entries during this iteration.
+ */
+int
+hashtable_iterate(struct hashtable *h,
+ int (*func)(const void *k, void *v, void *arg), void *arg);
+
/*****************************************************************************
* hashtable_destroy
* @name hashtable_destroy
* @param h the hashtable
- * @param free_values whether to call 'free' on the remaining values
*/
void
-hashtable_destroy(struct hashtable *h, int free_values);
+hashtable_destroy(struct hashtable *h);
#endif /* __HASHTABLE_CWC22_H__ */
.enoent = check_store_enoent,
};
- reachable = create_hashtable(16, hash_from_key_fn, keys_equal_fn);
+ /* Don't free values (they are all void *1) */
+ reachable = create_hashtable(16, hash_from_key_fn, keys_equal_fn,
+ HASHTABLE_FREE_KEY);
if (!reachable) {
log("check_store: ENOMEM");
return;
clean_store(reachable);
log("Checking store complete.");
- hashtable_destroy(reachable, 0 /* Don't free values (they are all
- (void *)1) */);
+ hashtable_destroy(reachable);
}