]> git.datanom.net - hashtable.git/blobdiff - hashtable.c
almost complete
[hashtable.git] / hashtable.c
index f5569fb8a5f15953a9efd82895e300a782a1374e..aa301326d732e42dbfcc85e2bf6f58d409abef69 100644 (file)
@@ -3,62 +3,78 @@
 #include <stdlib.h>
 #include "hashtable.h"
 
-typedef struct _Set {
-       uint64_t key;
+typedef struct _Node {
+       void* key;
        void* data;
-} Set;
+       struct _Node* next;
+} Node;
 
-typedef struct _Hashtable {
+struct _Hashtable {
        uint32_t size;
        HashFunc hash;
        EqualFunc compare;
-       Set** sets;
-} Hashtable;
+       FreeFunc free;
+       Node** nodes;
+};
+
+typedef struct {
+       Hashtable* table;
+       void* dummy2;
+       void* dummy3;
+       int64_t pos;
+} RealIter;
 
 static uint32_t hash_table_index(Hashtable* ht, const void* key) {
        return (ht->hash(key) % ht->size);
 }
 
 Hashtable* hash_table_create(HashFunc hf, EqualFunc ef) {
-       return hash_table_create_full(hf, ef, TABLESIZE);
+       return hash_table_create_full(hf, ef, TABLESIZE, NULL);
+}
+
+Hashtable* hash_table_create_notify(HashFunc hf, EqualFunc ef, FreeFunc ff) {
+       return hash_table_create_full(hf, ef, TABLESIZE, ff);
 }
 
-Hashtable* hash_table_create_full(HashFunc hf, EqualFunc ef, uint32_t size) {
+Hashtable* hash_table_create_full(HashFunc hf, EqualFunc ef, uint32_t size, FreeFunc ff) {
        Hashtable* ht = malloc(sizeof(*ht));
        ht->size = size;
        ht->hash = hf;
        ht->compare = ef;
-       ht->sets = calloc(sizeof(Set*), ht->size);
+       if (ff) {
+               ht->free = ff;
+       } else {
+               ht->free = free;
+       }
+       ht->nodes = calloc(sizeof(Node*), ht->size);
        return ht;
 }
 
 void hash_table_destroy(Hashtable* ht) {
        for (uint32_t i = 0; i < ht->size; i++) {
-               if (ht->sets[i] != NULL) {
-                       Set* tmp = ht->sets[i];
-                       if (tmp != NULL) {
-                               Set* set = tmp;
-                               free(set->data);
-                               free(set);
-                       }
-                       ht->sets[i] = NULL;
+               while (ht->nodes[i]) {
+                       Node* node = ht->nodes[i];
+                       ht->nodes[i] = ht->nodes[i]->next;
+                       ht->free(node->data);
+                       free(node);
                }
        }
        hash_table_print(ht);
-       free(ht->sets);
+       free(ht->nodes);
        free(ht);
 }
 
 void hash_table_print(Hashtable* ht) {
        printf("Start Table\n");
        for (uint32_t i = 0; i < ht->size; i++) {
-               if (ht->sets[i] == NULL) {
+               if (ht->nodes[i] == NULL) {
                        //printf("\t%i\t---\n", i);
                } else {
                        printf("\t%i\t\n", i);
-                       Set* tmp = ht->sets[i];
-                       if (tmp != NULL) {
-                               printf("\"%ju\" - (%p)", tmp->key, tmp->data);
+                       Node* node = ht->nodes[i];
+                       while (node != NULL) {
+                               printf("\"%p\" - (%p)", node->key, node->data);
+                               node = node->next;
                        }
                        printf("\n");
                }
@@ -70,19 +86,16 @@ bool hash_table_insert(Hashtable* ht, const void* key, void* obj) {
        if (key == NULL || obj == NULL || ht == NULL) return false;
 
        // implement chaning
-       void* found = hash_table_lookup(ht, key);
-       if (found != NULL) {
-               printf("[%s:%s] - %s: Missing chaining\n", (const char*) found, (const char*) key, (const char*) obj);
-               return false;
-       }
+       if (hash_table_lookup(ht, key) != NULL) return false;
 
        uint32_t index = hash_table_index(ht, key);
 
-       Set* set = malloc(sizeof(*set));
-       set->data = obj;
-       set->key = index;
+       Node* node = malloc(sizeof(*node));
+       node->data = obj;
+       node->key = (void*)key;
 
-       ht->sets[index] = set;
+       node->next = ht->nodes[index];
+       ht->nodes[index] = node;
        return true;
 }
 
@@ -90,30 +103,153 @@ void* hash_table_lookup(Hashtable* ht, const void* key) {
        if (key == NULL || ht == NULL) return false;
        uint64_t index = hash_table_index(ht, key);
 
-       Set* set = ht->sets[index];
-       if (set == NULL) return NULL;
-       //printf("find: %p -> found: %p\n", key, set->data);
+       Node* node = ht->nodes[index];
+       while (node != NULL && ht->compare(node->data, key) == false) {
+               node = node->next;
+       }
+
+       if (node == NULL) return NULL;
+       printf("find: %p -> found: %p\n", key, node->data);
 
-       if (ht->compare(set->data, key))
-               return set->data;
-       else
-               return NULL;
+       return node->data;
 }
 
 void* hash_table_delete(Hashtable* ht, const void* key) {
        if (key == NULL || ht == NULL) return false;
        uint64_t index = hash_table_index(ht, key);
 
-       Set* tmp = ht->sets[index];
-       if (tmp != NULL && ht->compare((void*)tmp->key, (void*)index) == false) return NULL;
-       // just in case
-       if (tmp == NULL) return NULL;
+       Node* node = ht->nodes[index];
+       Node* prev = NULL;
+       while (node != NULL && ht->compare(node->data, key) == false) {
+               prev = node;
+               node = node->next;
+       }
+
+       if (node == NULL) return NULL;
+       if (prev == NULL) {
+               ht->nodes[index] = node->next;
+       } else{
+               prev->next = node->next;
+       }
 
-       void* result = tmp->data;
-       free(tmp);
+       void* result = node->data;
+       free(node);
        return result;
 }
 
+List* hash_table_keys(Hashtable* ht) {
+       List *keys, *head;
+       keys = head = NULL;
+
+       if (ht != NULL) {
+               for (uint32_t i = 0; i < ht->size; i++) {
+                       if (ht->nodes[i] != NULL) {
+                               Node* node = ht->nodes[i];
+                               while (node != NULL) {
+                                       if (head == NULL) {
+                                               head = calloc(sizeof(List*), 1);
+                                               keys = head;
+                                       }
+                                       else {
+                                               head->next = calloc(sizeof(List*), 1);
+                                               head = head->next;
+                                       }
+                                       head->data = ht->nodes[i]->key;
+                                       node = node->next;
+                               }
+                       }
+               }
+       }
+
+       return keys;
+}
+
+List* hash_table_values(Hashtable* ht) {
+       List *values, *head;
+       values = head = NULL;
+
+       if (ht != NULL) {
+               for (uint32_t i = 0; i < ht->size; i++) {
+                       if (ht->nodes[i] != NULL) {
+                               Node* node = ht->nodes[i];
+                               while (node != NULL) {
+                                       if (head == NULL) {
+                                               head = calloc(sizeof(List*), 1);
+                                               values = head;
+                                       }
+                                       else {
+                                               head->next = calloc(sizeof(List*), 1);
+                                               head = head->next;
+                                       }
+                                       head->data = ht->nodes[i]->data;
+                                       node = node->next;
+                               }
+                       }
+               }
+       }
+
+       return values;
+}
+
+void hash_table_list_free(List* list) {
+       while (list != NULL) {
+               List* prev = list;
+               list = list->next;
+               free(prev);
+       }
+}
+
+void hash_table_foreach(Hashtable* ht, ForeachFunc ff, void* userdata) {
+       if (ht != NULL) {
+               for (uint32_t i = 0; i < ht->size; i++) {
+                       if (ht->nodes[i] != NULL) {
+                               Node* node = ht->nodes[i];
+                               while (node != NULL) {
+                                       ff(node->key, node->data, userdata);
+                                       node = node->next;
+                               }
+                       }
+               }
+       }
+}
+
+void hash_table_iter_init (HashtableIter* iter, Hashtable* ht) {
+       RealIter* ri = (RealIter*) iter;
+
+       if (ri != NULL && ht != NULL) {
+               ri->table = ht;
+               ri->pos = -1;
+       }
+}
+
+bool hash_table_iter_next(HashtableIter* iter, void** key, void** value) {
+       RealIter* ri = (RealIter*) iter;
+       Node* node;
+       int64_t pos;
+
+       if (ri != NULL) {
+               pos = ri->pos;
+
+               do {
+                       pos++;
+                       if (pos >= ri->table->size) {
+                               ri->pos = pos;
+                               return false;
+                       }
+                       node = ri->table->nodes[pos];
+               } while (node == NULL);
+
+               if (key != NULL)
+                       *key = node->key;
+               if (value != NULL)
+                       *value = node->data;
+
+               ri->pos = pos;
+               return true;
+       }
+       return false;
+}
+
 uint64_t int_hash(const void* key) {
        return *(uint64_t*) key;
 }
This page took 0.040206 seconds and 5 git commands to generate.