+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "hashtable.h"
+
+typedef struct _Set {
+ uint64_t key;
+ void* data;
+} Set;
+
+typedef struct _Hashtable {
+ uint32_t size;
+ HashFunc hash;
+ EqualFunc compare;
+ Set** sets;
+} Hashtable;
+
+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);
+}
+
+Hashtable* hash_table_create_full(HashFunc hf, EqualFunc ef, uint32_t size) {
+ Hashtable* ht = malloc(sizeof(*ht));
+ ht->size = size;
+ ht->hash = hf;
+ ht->compare = ef;
+ ht->sets = calloc(sizeof(Set*), 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;
+ }
+ }
+ hash_table_print(ht);
+ free(ht->sets);
+ 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) {
+ //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);
+ }
+ printf("\n");
+ }
+ }
+ printf("End Table\n");
+}
+
+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;
+ }
+
+ uint32_t index = hash_table_index(ht, key);
+
+ Set* set = malloc(sizeof(*set));
+ set->data = obj;
+ set->key = index;
+
+ ht->sets[index] = set;
+ return true;
+}
+
+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);
+
+ if (ht->compare(set->data, key))
+ return set->data;
+ else
+ return NULL;
+}
+
+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;
+
+ void* result = tmp->data;
+ free(tmp);
+ return result;
+}
+
+uint64_t int_hash(const void* key) {
+ return *(uint64_t*) key;
+}
+
+uint64_t str_hash(const void* key) {
+ const signed char* p;
+ uint64_t h = 5381;
+
+ for (p = key; *p != '\0'; p++) {
+ h = (h << 5) + h + *p;
+ }
+
+ return h;
+}
+
+uint64_t ptr_hash(const void* key) {
+ return (uint64_t)key;
+}
+
+bool int_equal(const void* a, const void* b) {
+ return *((const int*) a) == *((const int*) b);
+}
+
+bool str_equal(const void* a, const void* b) {
+ const char *string1 = (const char*) a;
+ const char *string2 = (const char*) b;
+
+ return strcmp (string1, string2) == 0;
+}
+
+bool ptr_equal(const void* a, const void* b) {
+ return a == b;
+}
+