77 lines
1.9 KiB
C
77 lines
1.9 KiB
C
#include "malloc.h"
|
|
#include "hash_table.h"
|
|
|
|
static uint32_t fnv_1(const uint8_t * buf, int length)
|
|
{
|
|
const uint32_t fnv_offset_basis = 0x811c9dc5;
|
|
const uint32_t fnv_prime = 0x01000193;
|
|
|
|
uint32_t hash = fnv_offset_basis;
|
|
|
|
for (int i = 0; i < length; i++) {
|
|
hash = hash * fnv_prime;
|
|
hash = hash ^ buf[i];
|
|
}
|
|
|
|
return hash;
|
|
}
|
|
|
|
void hash_table_init(int hash_table_length,
|
|
struct hash_table_entry * entry)
|
|
{
|
|
for (int i = 0; i < hash_table_length; i++) {
|
|
entry[i].key = nullptr;
|
|
entry[i].next = nullptr;
|
|
}
|
|
}
|
|
|
|
void hash_table_add(int hash_table_length,
|
|
struct hash_table_entry * entry,
|
|
const uint8_t * key,
|
|
int key_length,
|
|
void * value)
|
|
{
|
|
uint32_t hash = fnv_1(key, key_length) & (hash_table_length - 1);
|
|
struct hash_table_entry * e = &entry[hash];
|
|
|
|
while (e->next != nullptr) {
|
|
e = e->next;
|
|
}
|
|
|
|
if (e->key != nullptr) {
|
|
// allocate e from overflow
|
|
e->next = malloc_class_arena((sizeof (struct hash_table_entry)));
|
|
e = e->next;
|
|
}
|
|
|
|
e->key = key;
|
|
e->key_length = key_length;
|
|
e->value = value;
|
|
}
|
|
|
|
static inline bool key_equal(const uint8_t * a, const uint8_t * b, int length)
|
|
{
|
|
for (int i = 0; i < length; i++) {
|
|
if (a[i] != b[i])
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
struct hash_table_entry * hash_table_find(int hash_table_length,
|
|
struct hash_table_entry * entry,
|
|
const uint8_t * key,
|
|
int key_length)
|
|
{
|
|
uint32_t hash = fnv_1(key, key_length) & (hash_table_length - 1);
|
|
struct hash_table_entry * e = &entry[hash];
|
|
|
|
while (e != nullptr && e->key != nullptr) {
|
|
if (e->key_length == key_length && key_equal(e->key, key, key_length)) {
|
|
return e;
|
|
}
|
|
e = e->next;
|
|
}
|
|
return nullptr;
|
|
}
|