113 lines
2.9 KiB
C
113 lines
2.9 KiB
C
#include <stdint.h>
|
|
#include <stddef.h>
|
|
#include <stdbool.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "hash.h"
|
|
|
|
static uint64_t hashtable_hash(const char *key)
|
|
{
|
|
#define FNV_OFFSET 14695981039346656037UL
|
|
#define FNV_PRIME 1099511628211UL
|
|
|
|
uint64_t hash = FNV_OFFSET;
|
|
for (const char *p = key; *p; p++) {
|
|
hash ^= (uint64_t)(unsigned char)(*p);
|
|
hash *= FNV_PRIME;
|
|
}
|
|
return hash;
|
|
}
|
|
|
|
void hashtable_init (HashTable *t, size_t capacity)
|
|
{
|
|
memset(t, 0, sizeof(*t));
|
|
|
|
t->capacity = capacity;
|
|
t->buckets = malloc(t->capacity * sizeof(*t->buckets));
|
|
|
|
for (int i = 0; i < t->capacity; i++) {
|
|
t->buckets[i] = NULL;
|
|
}
|
|
}
|
|
|
|
void hashtable_deinit (HashTable *t)
|
|
{
|
|
for (int i = 0; i < t->capacity; i++) {
|
|
if (t->buckets[i] != NULL) {
|
|
if (t->buckets[i]->key != NULL) {
|
|
free((void *)t->buckets[i]->key);
|
|
}
|
|
free(t->buckets[i]);
|
|
}
|
|
}
|
|
free(t->buckets);
|
|
}
|
|
|
|
HashEntry * hashtable_new (const char *key, void *value, size_t sz)
|
|
{
|
|
HashEntry *e = malloc(sizeof(*e));
|
|
e->key = malloc(strlen(key)+1);
|
|
e->value = malloc(sz);
|
|
e->sz = sz;
|
|
strcpy((char*)e->key, key);
|
|
memcpy(e->value, value, e->sz);
|
|
return e;
|
|
}
|
|
|
|
void * hashtable_get (HashTable *t, const char *key)
|
|
{
|
|
uint64_t hash = hashtable_hash(key);
|
|
size_t index = (size_t)(hash % t->capacity);
|
|
|
|
for (int i = index; i < t->capacity; i++) {
|
|
if (t->buckets[i] != NULL && t->buckets[i]->key != NULL && strcmp(t->buckets[i]->key, key) == 0) {
|
|
return t->buckets[i]->value;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
bool hashtable_check (HashTable *t, const char *key)
|
|
{
|
|
return hashtable_get(t, key) != NULL;
|
|
}
|
|
|
|
void hashtable_set (HashTable *t, const char *key, void *value, size_t sz)
|
|
{
|
|
uint64_t hash = hashtable_hash(key);
|
|
size_t index = (size_t)(hash % t->capacity);
|
|
|
|
for (int i = index; i < t->capacity; i++) {
|
|
if (t->buckets[i] == NULL) {
|
|
HashEntry *e = hashtable_new(key, value, sz);
|
|
t->buckets[i] = e;
|
|
break;
|
|
} else if (t->buckets[i] != NULL && t->buckets[i]->key != NULL && strcmp(t->buckets[i]->key, key) == 0) {
|
|
t->buckets[i]->sz = sz;
|
|
t->buckets[i]->value = value;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool hashtable_delete (HashTable *t, const char *key)
|
|
{
|
|
uint64_t hash = hashtable_hash(key);
|
|
size_t index = (size_t)(hash % t->capacity);
|
|
|
|
for (int i = index; i < t->capacity; i++) {
|
|
if (t->buckets[i] != NULL && t->buckets[i]->key != NULL && strcmp(t->buckets[i]->key, key) == 0) {
|
|
HashEntry *e = t->buckets[i];
|
|
free((void*)e->key);
|
|
free((void*)e->value);
|
|
free((void*)e);
|
|
t->buckets[i] = NULL;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|