diff options
Diffstat (limited to 'src/hash.c')
-rw-r--r-- | src/hash.c | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/src/hash.c b/src/hash.c new file mode 100644 index 0000000..447601e --- /dev/null +++ b/src/hash.c @@ -0,0 +1,97 @@ +/* hash.c - Alpine Package Keeper (APK) + * + * Copyright (C) 2005-2008 Natanael Copa <n@tanael.org> + * Copyright (C) 2008 Timo Teräs <timo.teras@iki.fi> + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. See http://www.gnu.org/ for details. + */ + +#include "apk_defines.h" +#include "apk_hash.h" + +unsigned long apk_hash_string(const char *str) +{ + unsigned long hash = 5381; + int c; + + while ((c = *str++) != 0) + hash = hash * 33 + c; + + return hash; +} + +unsigned long apk_hash_csum(const void *ptr) +{ + return *(const unsigned long *) ptr; +} + +void apk_hash_init(struct apk_hash *h, const struct apk_hash_ops *ops, + int num_buckets) +{ + h->ops = ops; + h->buckets = apk_hash_array_resize(NULL, num_buckets); + h->num_items = 0; +} + +void apk_hash_free(struct apk_hash *h) +{ + apk_hash_foreach(h, (apk_hash_enumerator_f) h->ops->delete_item, NULL); + free(h->buckets); +} + +int apk_hash_foreach(struct apk_hash *h, apk_hash_enumerator_f e, void *ctx) +{ + apk_hash_node *pos, *n; + ptrdiff_t offset = h->ops->node_offset; + int i, r; + + for (i = 0; i < h->buckets->num; i++) { + hlist_for_each_safe(pos, n, &h->buckets->item[i]) { + r = e(((void *) pos) - offset, ctx); + if (r != 0) + return r; + } + } + + return 0; +} + +apk_hash_item apk_hash_get(struct apk_hash *h, apk_hash_key key) +{ + ptrdiff_t offset = h->ops->node_offset; + unsigned long hash; + apk_hash_node *pos; + apk_hash_item item; + apk_hash_key itemkey; + + hash = h->ops->hash_key(key) % h->buckets->num; + hlist_for_each(pos, &h->buckets->item[hash]) { + item = ((void *) pos) - offset; + itemkey = h->ops->get_key(item); + if (h->ops->compare(key, itemkey) == 0) + return item; + } + + return NULL; +} + +void apk_hash_insert(struct apk_hash *h, apk_hash_item item) +{ + apk_hash_key key; + unsigned long hash; + apk_hash_node *node; + + key = h->ops->get_key(item); + hash = h->ops->hash_key(key) % h->buckets->num; + node = (apk_hash_node *) (item + h->ops->node_offset); + hlist_add_head(node, &h->buckets->item[hash]); + h->num_items++; +} + +void apk_hash_delete(struct apk_hash *h, apk_hash_key key) +{ +} + |