pico-http/hashtable/hashtable.c
Andrew Gundersen 9904bd2212 init commit
2022-05-02 08:00:44 -05:00

153 lines
2.2 KiB
C

/**
* 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;
}