Added generic hashmaps and 2 examples using them

This commit is contained in:
cannoli-fruit 2026-07-11 14:58:42 -04:00
commit 0b34fb93a6
3 changed files with 164 additions and 0 deletions

106
lazy.h
View file

@ -2,6 +2,7 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdint.h>
#define LZ_STR_FMT "%.*s"
#define LZ_STR_PRINTF(slc) (int)slc.cnt, slc.data
@ -18,6 +19,10 @@ void lz_drop_left(Lz_Slc *src, size_t n);
void lz_drop_right(Lz_Slc *src, size_t n);
void lz_split_slc(Lz_Slc *src, char delim, Lz_Slc *dst);
void lz_split_slc_typ(Lz_Slc *src, int (*classfunc)(int), Lz_Slc *dst);
size_t lz_hm_hash_void_set(void *hmdat, size_t e_size, size_t cap,
void *key, size_t k_size);
size_t lz_hm_hash_void_get(void *hmdat, size_t e_size, size_t cap,
void *key, size_t k_size);
Lz_Slc lz_cstr_to_slc(char *dat);
char *lz_cstr_dup(const char *s);
@ -85,8 +90,109 @@ char *lz_cstr_dup(const char *s);
typedef Lz_DA(char) Lz_SB;
#define Lz_HM_Pair(K_t, V_t) struct {\
size_t exists;\
K_t key;\
V_t val;\
}
#define Lz_HM(K_t, V_t) struct {\
size_t cap;\
size_t cnt;\
size_t valsize;\
size_t entrysize;\
size_t tmphash;\
V_t defval;\
K_t tmpkey;\
V_t tmpval;\
Lz_HM_Pair(K_t, V_t) *data;\
}
#define lz_hm_init(hm) do {\
(hm).cap = 256;\
(hm).cnt = 0;\
(hm).valsize = sizeof((*(hm).data).val);\
(hm).entrysize = sizeof(*(hm).data);\
(hm).data = malloc((hm).cap*(hm).entrysize);\
} while (0)
#define lz_hm_hash_set(hm, k) (\
(hm).tmpkey = k,\
lz_hm_hash_void_set((hm).data, (hm).entrysize,(hm.cap),\
&(hm).tmpkey, sizeof((hm).tmpkey))\
)
#define lz_hm_hash_get(hm, k) (\
(hm).tmpkey = k,\
lz_hm_hash_void_get((hm).data, (hm).entrysize,(hm.cap),\
&(hm).tmpkey, sizeof((hm).tmpkey))\
)
#define lz_hm_exists(hm, k) (\
(hm).tmphash = lz_hm_hash_get(hm, k),\
((hm).tmphash != (size_t)-1)\
)
#define lz_hm_get(hm, k) (\
(hm).tmphash = lz_hm_hash_get(hm, k),\
((hm).tmphash == (size_t)-1) ? (hm).defval : ((hm).data[(hm).tmphash].val)\
)
#define lz_hm_add(hm, k, v) do {\
size_t idx = lz_hm_hash_set(hm, k);\
(hm).data[idx].key = k;\
(hm).data[idx].val = v;\
} while(0)
#ifdef LAZY_IMPL
size_t lz_hm_hash_void_get(void *hmdat, size_t e_size, size_t cap,
void *key, size_t k_size) {
size_t hash = 0;
for (size_t i = 0; i < k_size; ++i) {
size_t b = (size_t)(((uint8_t*)key)[i]);
hash += b*31415 + 9265; //bytewise hash
hash %= cap;
}
for (size_t i = 0; i < cap; ++i) {
size_t localhash = (hash + i) % cap;
size_t structOffset = e_size*localhash;
void *pairStruct = (hmdat + structOffset);
void *structKey = pairStruct + sizeof(size_t);
int diff = memcmp(structKey, key, k_size);
if (diff == 0) {
return localhash;
}
size_t istaken = *((size_t*)pairStruct);
if (!istaken) {
return (size_t)-1;
}
}
assert(0 && "Overflown Hashmap");
return 0;
}
size_t lz_hm_hash_void_set(void *hmdat, size_t e_size, size_t cap,
void *key, size_t k_size) {
size_t hash = 0;
for (size_t i = 0; i < k_size; ++i) {
size_t b = (size_t)(((uint8_t*)key)[i]);
hash += b*31415 + 9265; //bytewise hash
hash %= cap;
}
for (size_t i = 0; i < cap; ++i) {
size_t localhash = (hash + i) % cap;
size_t structOffset = e_size*localhash;
void *pairStruct = (hmdat + structOffset);
size_t istaken = *((size_t*)pairStruct);
if (!istaken) return localhash;
}
return (size_t)-1;
}
// Horribly enough, strdup is a gnu extension
// Here's a portable implementation
char *lz_cstr_dup(const char *s) {