153 lines
2.2 KiB
C
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;
|
|
}
|