Add primitives, hash map and dynamic array

This commit is contained in:
Hugo Mårdbrink 2025-04-17 09:53:37 +02:00
commit 2f19f82116
10 changed files with 384 additions and 0 deletions

View file

@ -0,0 +1,36 @@
#include <htd/primitives/primitives.h>
#include <htd/data_structure/dynamic_array.h>
#include <stdlib.h>
#include <memory.h>
const usize GROWTH_FACTOR = 2;
const usize START_LEN = 32;
void dynarr_init(DynamicArray* arr, usize data_size) {
arr->data_size = data_size;
arr->len = 0;
arr->capacity = START_LEN;
arr->data = (void*)malloc(arr->capacity * arr->data_size);
}
void* dynarr_at(DynamicArray* arr, usize idx) {
return &((u8*)arr->data)[arr->data_size * idx];
}
void dynarr_push(DynamicArray* arr, void* data) {
if (arr->len >= arr->capacity) {
arr->capacity *= GROWTH_FACTOR;
arr->data = (void*)realloc(arr->data, arr->capacity * arr->data_size);
}
memcpy(&((u8*)arr->data)[arr->data_size * arr->len], data, arr->data_size);
arr->len++;
}
void dynarr_free(DynamicArray* arr) {
free(arr->data);
arr->data = NULL;
arr->capacity = 0;
arr->len = 0;
}

View file

@ -0,0 +1,142 @@
#include <htd/primitives/primitives.h>
#include <htd/data_structure/hash_map.h>
#include <stdlib.h>
#include <memory.h>
const usize START_LEN = 16;
const usize GROWTH_FACTOR = 2;
usize hash(const u8* key, usize len) {
const u8 *data = (const u8*)key;
u32 h = 0x811c9dc5;
const u32 c1 = 0xcc9e2d51;
const u32 c2 = 0x1b873593;
const usize nblocks = len / 4;
for (usize i = 0; i < nblocks; i++) {
u32 k = *((u32*)data);
data += 4;
k *= c1;
k = (k << 15) | (k >> 17);
k *= c2;
h ^= k;
h = (h << 13) | (h >> 19);
h = h * 5 + 0xe6546b64;
}
const usize tail_size = len & 3;
u32 k1 = 0;
if (tail_size > 0) {
for (usize i = 0; i < tail_size; ++i) {
k1 ^= data[i] << (i * 8);
}
k1 *= c1;
k1 = (k1 << 15) | (k1 >> 17);
k1 *= c2;
h ^= k1;
}
h ^= len;
h = h ^ (h >> 16);
h *= 0x85ebca6b;
h = h ^ (h >> 13);
h *= 0xc2b2ae35;
h = h ^ (h >> 16);
return h;
}
void hmap_init(HashMap* hmap, usize key_size, usize val_size) {
hmap->len = 0;
hmap->capacity = START_LEN;
hmap->key_size = key_size;
hmap->val_size = val_size;
hmap->table = (HashMapEntry*)malloc(sizeof(HashMapEntry) * hmap->capacity);
for (usize i = 0; i < hmap->capacity; ++i) {
hmap->table[i].key = NULL;
hmap->table[i].val = NULL;
}
}
void resize(HashMap* hmap) {
usize old_capacity = hmap->capacity;
HashMapEntry* old_table = (HashMapEntry*)malloc(sizeof(HashMapEntry) * old_capacity);
memcpy(old_table, hmap->table, sizeof(HashMapEntry) * old_capacity);
hmap->capacity *= GROWTH_FACTOR;
hmap->table = (HashMapEntry*)realloc(hmap->table, sizeof(HashMapEntry) * hmap->capacity);
for (usize i = 0; i < hmap->capacity; i++) {
hmap->table[i].key = NULL;
hmap->table[i].val = NULL;
}
// Reset length, re-adding
hmap->len = 0;
for (usize i = 0; i < old_capacity; i++) {
if (old_table[i].key != NULL) {
hmap_put(hmap, old_table[i].key, old_table[i].val);
free(old_table[i].key);
free(old_table[i].val);
}
}
free(old_table);
}
void hmap_put(HashMap* hmap, const void* key, const void* val) {
if (hmap->len >= hmap->capacity) {
resize(hmap);
}
usize idx = hash(key, hmap->key_size) % hmap->capacity;
while (hmap->table[idx].key != NULL) {
if (memcmp(hmap->table[idx].key, key, hmap->key_size) == 0) {
free(hmap->table[idx].val);
hmap->table[idx].val = malloc(hmap->val_size);
memcpy(hmap->table[idx].val, val, hmap->val_size);
return;
}
idx = (idx + 1) % hmap->capacity;
}
hmap->table[idx].key = malloc(hmap->key_size);
memcpy(hmap->table[idx].key, key, hmap->key_size);
hmap->table[idx].val = malloc(hmap->val_size);
memcpy(hmap->table[idx].val, val, hmap->val_size);
hmap->len++;
}
void* hmap_get(HashMap* hmap, const void* key) {
usize idx = hash(key, hmap->key_size) % hmap->capacity;
while (hmap->table[idx].key != NULL) {
if (memcmp(hmap->table[idx].key, key, hmap->key_size) == 0) {
return hmap->table[idx].val;
}
idx = (idx + 1) % hmap->capacity;
}
return NULL;
}
void hmap_free(HashMap* hmap) {
for (usize i = 0; i < hmap->capacity; ++i) {
if (hmap->table[i].key != NULL) {
free(hmap->table[i].key);
free(hmap->table[i].val);
}
}
free(hmap->table);
hmap->table = NULL;
hmap->capacity = 0;
hmap->len = 0;
}