summaryrefslogtreecommitdiff
path: root/src/gib_hash.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gib_hash.c')
-rw-r--r--src/gib_hash.c144
1 files changed, 144 insertions, 0 deletions
diff --git a/src/gib_hash.c b/src/gib_hash.c
new file mode 100644
index 0000000..c839222
--- /dev/null
+++ b/src/gib_hash.c
@@ -0,0 +1,144 @@
+/* gib_hash.c
+
+Copyright (C) 1999,2000 Paul Duncan.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies of the Software and its documentation and acknowledgment shall be
+given in the documentation and software packages that this Software was
+used.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include "gib_hash.h"
+#include "gib_utils.h"
+
+gib_hash_node *gib_hash_node_new(char *key, void *data)
+{
+ gib_hash_node *node = malloc(sizeof(gib_hash_node));
+ node->key = strdup(key);
+ GIB_LIST(node)->data = data;
+ GIB_LIST(node)->next = NULL;
+ GIB_LIST(node)->prev = NULL;
+ return node;
+
+}
+
+void gib_hash_node_free(gib_hash_node *node)
+{
+ free(node->key);
+ free(node);
+ return;
+}
+
+void gib_hash_node_free_and_data(gib_hash_node *node)
+{
+ free(node->list.data);
+ gib_hash_node_free(node);
+ return;
+}
+
+gib_hash *gib_hash_new()
+{
+ gib_hash *hash = malloc(sizeof(gib_hash));
+ hash->base = gib_hash_node_new("__gib_hash_new",NULL);
+ return hash;
+}
+
+void gib_hash_free(gib_hash *hash)
+{
+ /* free hash keys as it's not taken care of by gib_list_free */
+ gib_list *i;
+ for (i = GIB_LIST(hash->base); i; i = i->next)
+ free(GIB_HASH_NODE(i)->key);
+
+ gib_list_free(GIB_LIST(hash->base));
+ free(hash);
+ return;
+}
+
+void gib_hash_free_and_data(gib_hash *hash)
+{
+ /* free hash keys as it's not taken care of by gib_list_free */
+ gib_list *i;
+ for (i = GIB_LIST(hash->base); i; i = i->next)
+ free(GIB_HASH_NODE(i)->key);
+
+ gib_list_free_and_data(GIB_LIST(hash->base));
+ free(hash);
+ return;
+}
+
+static unsigned char gib_hash_find_callback(gib_list *list, void *data)
+{
+ gib_hash_node *node = GIB_HASH_NODE(list);
+ char *key = (char*) data;
+
+ /* strncasecmp causes simliar keys like key1 and key11 clobber eachother */
+ return !strcasecmp(node->key, key);
+}
+
+void gib_hash_set(gib_hash *hash, char *key, void *data)
+{
+ gib_list *l;
+ gib_hash_node *n;
+
+ n = GIB_HASH_NODE(gib_list_find(GIB_LIST(hash->base),
+ gib_hash_find_callback,
+ key));
+ if (n) {
+ GIB_LIST(n)->data = data;
+ } else {
+ /* not using gib_list_add_end here as that would nest the
+ data one level, doing manual insert instead */
+ n = gib_hash_node_new(key,data);
+ l = gib_list_last(GIB_LIST(hash->base));
+
+ GIB_LIST(n)->next = NULL;
+ GIB_LIST(n)->prev = l;
+
+ if (l)
+ l->next = GIB_LIST(n);
+ }
+}
+
+void *gib_hash_get(gib_hash *hash, char *key)
+{
+ gib_list *n = gib_list_find(GIB_LIST(hash->base),gib_hash_find_callback,key);
+ return n?n->data:NULL;
+}
+
+void gib_hash_remove(gib_hash *hash, char *key)
+{
+ gib_list *n = gib_list_find(GIB_LIST(hash->base), gib_hash_find_callback, key);
+ if (n) {
+ gib_list_unlink(GIB_LIST(hash->base), n);
+ gib_hash_node_free(GIB_HASH_NODE(n->data));
+ }
+
+ return;
+}
+
+void gib_hash_foreach(gib_hash *hash, void (*foreach_cb)(gib_hash_node *node, void *data), void *data)
+{
+ gib_hash_node *i, *next;
+ for (i=hash->base; i; i=next) {
+ next = GIB_HASH_NODE(GIB_LIST(i)->next);
+ foreach_cb(i,data);
+ }
+ return;
+}
+