feat: add hmapHashString and hmapInit
This commit is contained in:
1 parent
b6fbdb51aa
commit
8df641fbf7
1 file changed
+123
+123
@@ -0,0 +1,123 @@
|
||||
#include "hmap.h"
|
||||
#include "heap.h"
|
||||
#include "string.h"
|
||||
#include "klib.h"
|
||||
|
||||
uint64 hmapHashString(const char* key)
|
||||
{
|
||||
uint64 hash = 1469598103934665603UL; /* FNV-1a 64-bit offset basis */
|
||||
for (const unsigned char* p = (const unsigned char*)key; *p; p++) {
|
||||
hash ^= (uint64)*p;
|
||||
hash *= 1099511628211UL; /* FNV-1a 64-bit prime */
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
bool hmapInit(Hmap* h, usize bucketCount)
|
||||
{
|
||||
if (bucketCount == 0)
|
||||
bucketCount = 16;
|
||||
|
||||
h->buckets = (HmapEntry**)kmalloc(bucketCount * sizeof(HmapEntry*));
|
||||
if (!h->buckets)
|
||||
return false;
|
||||
|
||||
for (usize i = 0; i < bucketCount; i++)
|
||||
h->buckets[i] = nullptr;
|
||||
h->bucketCount = bucketCount;
|
||||
h->count = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
void hmapFree(Hmap* h)
|
||||
{
|
||||
for (usize i = 0; i < h->bucketCount; i++) {
|
||||
HmapEntry* entry = h->buckets[i];
|
||||
while (entry) {
|
||||
HmapEntry* next = entry->next;
|
||||
kfree(entry->key);
|
||||
kfree(entry);
|
||||
entry = next;
|
||||
}
|
||||
}
|
||||
kfree(h->buckets);
|
||||
h->buckets = nullptr;
|
||||
h->bucketCount = 0;
|
||||
h->count = 0;
|
||||
}
|
||||
|
||||
static HmapEntry** findSlot(const Hmap* h, const char* key)
|
||||
{
|
||||
usize bucket = hmapHashString(key) % h->bucketCount;
|
||||
HmapEntry** slot = &h->buckets[bucket];
|
||||
while (*slot && strcmp((*slot)->key, key) != 0)
|
||||
slot = &(*slot)->next;
|
||||
return slot;
|
||||
}
|
||||
|
||||
bool hmapSet(Hmap* h, const char* key, void* value)
|
||||
{
|
||||
HmapEntry** slot = findSlot(h, key);
|
||||
if (*slot) {
|
||||
(*slot)->value = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
HmapEntry* entry = (HmapEntry*)kmalloc(sizeof(HmapEntry));
|
||||
if (!entry)
|
||||
return false;
|
||||
|
||||
usize keyLen = strlen(key);
|
||||
entry->key = (char*)kmalloc(keyLen + 1);
|
||||
if (!entry->key) {
|
||||
kfree(entry);
|
||||
return false;
|
||||
}
|
||||
strcpy(entry->key, key);
|
||||
entry->value = value;
|
||||
entry->next = nullptr;
|
||||
|
||||
*slot = entry;
|
||||
h->count++;
|
||||
return true;
|
||||
}
|
||||
|
||||
void* hmapGet(const Hmap* h, const char* key)
|
||||
{
|
||||
HmapEntry** slot = findSlot(h, key);
|
||||
return *slot ? (*slot)->value : nullptr;
|
||||
}
|
||||
|
||||
bool hmapHas(const Hmap* h, const char* key)
|
||||
{
|
||||
return *findSlot(h, key) != nullptr;
|
||||
}
|
||||
|
||||
bool hmapRemove(Hmap* h, const char* key)
|
||||
{
|
||||
HmapEntry** slot = findSlot(h, key);
|
||||
if (!*slot)
|
||||
return false;
|
||||
|
||||
HmapEntry* entry = *slot;
|
||||
*slot = entry->next;
|
||||
kfree(entry->key);
|
||||
kfree(entry);
|
||||
h->count--;
|
||||
return true;
|
||||
}
|
||||
|
||||
usize hmapCount(const Hmap* h)
|
||||
{
|
||||
return h->count;
|
||||
}
|
||||
|
||||
void hmapForEach(const Hmap* h, bool (*visit)(const char* key, void* value, void* userData), void* userData)
|
||||
{
|
||||
for (usize i = 0; i < h->bucketCount; i++) {
|
||||
for (HmapEntry* entry = h->buckets[i]; entry; entry = entry->next) {
|
||||
if (!visit(entry->key, entry->value, userData))
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user