+/**
+ * hashtable.c - A basic hashtable implementation
+ *
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "llist.h"
+#include "hashtable.h"
+
+#define SIZE 128
+
+typedef struct
+{
+ void* key;
+ void* data;
+}
+HTEntry;
+
+/**
+ * Simple hash function used
+ */
+int hash(char* key, int ht_size)
+{
+ int h = 0;
+
+ // basic modulo hash
+ for (size_t i = 0; i < strlen(key); i++)
+ {
+ h = (31 * h + key[i]) % ht_size;
+ }
+
+ return h;
+}
+
+/**
+ * Compare function for searching a bucket
+ */
+int compare(void* data, void* arg)
+{
+ char* key = arg;
+ HTEntry* entry = data;
+ return strcmp(entry->key, key);
+}
+
+/**
+ * Delete HT entry from bucket
+ */
+int delete_entry(void* data, void* arg)
+{
+ (void) arg;
+ HTEntry* entry = data;
+ free(entry);
+ return 0;
+}
+
+/**
+ * Create a new hashtable
+ */
+HT* ht_create(void)
+{
+ HT* ht = malloc(sizeof(HT));
+
+ ht->size = SIZE;
+ ht->entries = 0;
+ ht->store = malloc(ht->size * sizeof(LL*));
+
+ for (int i = 0; i < ht->size; i++)
+ {
+ ht->store[i] = ll_create();
+ }
+
+ return ht;
+}
+
+/**
+ * Add a new key value pair to a hashtable
+ */
+int ht_put(HT* ht, char* key, void* data)
+{
+ int addr = hash(key, ht->size);
+
+ LL* bucket = ht->store[addr];
+
+ HTEntry* entry = malloc(sizeof(HTEntry));
+ entry->key = strdup(key);
+ entry->data = data;
+
+ ll_push(bucket, entry);
+
+ ht->entries++;
+
+ return 0;
+}
+
+/**
+ * Get a value from a hashtable with a key
+ */
+void* ht_get(HT* ht, char* key)
+{
+ int addr = hash(key, ht->size);
+
+ LL* bucket = ht->store[addr];
+
+ HTEntry* entry = ll_search(bucket, compare, (void*) key);
+
+ if (entry == NULL)
+ {
+ return NULL;
+ }
+
+ return entry->data;
+}
+
+/**
+ * Delete a key value pair from a hashtable
+ */
+void* ht_delete(HT* ht, char* key)
+{
+ int addr = hash(key, ht->size);
+
+ LL* bucket = ht->store[addr];
+
+ HTEntry* entry = ll_delete(bucket, compare, key);
+
+ if (entry == NULL)
+ {
+ return NULL;
+ }
+
+ ht->entries--;
+
+ return entry->data;
+}
+
+
+/**
+ * Destroy/free an entire hashtable
+ */
+int ht_free(HT* ht)
+{
+ for (int i = 0; i < ht->size; i++)
+ {
+ LL* bucket = ht->store[i];
+ ll_loop(bucket, delete_entry, NULL);
+ ll_free(bucket);
+ }
+
+ free(ht);
+
+ return 0;
+}