Implemented hashmap deletion with tombstones

This commit is contained in:
cannoli-fruit 2026-07-15 13:59:45 -04:00
commit f22c7c1a73
3 changed files with 169 additions and 36 deletions

169
lazy.h
View file

@ -20,20 +20,26 @@ typedef struct {
} Lz_Slc;
#endif
void lz_trim_left_typ(Lz_Slc *src, int (*classfunc)(int));
void lz_trim_right_typ(Lz_Slc *src, int (*classfunc)(int));
void lz_trim_typ(Lz_Slc *src, int (*classfunc)(int));
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);
void lz_slc_trim_left_typ(Lz_Slc *src, int (*classfunc)(int));
void lz_slc_trim_right_typ(Lz_Slc *src, int (*classfunc)(int));
void lz_slc_trim_typ(Lz_Slc *src, int (*classfunc)(int));
void lz_slc_drop_left(Lz_Slc *src, size_t n);
void lz_slc_drop_right(Lz_Slc *src, size_t n);
void lz_slc_split(Lz_Slc *src, char delim, Lz_Slc *dst);
void lz_slc_split_typ(Lz_Slc *src, int (*classfunc)(int), Lz_Slc *dst);
size_t lz_hm_hash_raw_bytes(size_t cap, void *key, size_t k_s);
size_t lz_hm_hash_void_get(size_t cap, _Bool *exists, void *key,
void *keys, size_t k_s);
size_t lz_hm_hash_void_set(size_t cap, _Bool *exists, void* key, size_t k_s);
size_t lz_hm_hash_void_get(size_t cap, _Bool *exists, _Bool *tombstones,
void *key, void *keys, size_t k_s);
size_t lz_hm_hash_void_set(size_t cap, _Bool *exists,
_Bool *tombstones, void* key, size_t k_s);
Lz_Slc lz_cstr_to_slc(char *dat);
char *lz_cstr_dup(const char *s);
double lz_slc_atof(Lz_Slc *src);
int lz_slc_atoi(Lz_Slc *src);
long lz_slc_atol(Lz_Slc *src);
long long lz_slc_atoll(Lz_Slc *src);
#ifndef Lz_DA
#define Lz_DA(T) struct {T *data; size_t cnt; size_t cap; }
#endif
@ -129,6 +135,12 @@ char *lz_cstr_dup(const char *s);
typedef Lz_DA(char) Lz_SB;
#endif
double lz_sb_atof(Lz_SB *src);
int lz_sb_atoi(Lz_SB *src);
long lz_sb_atol(Lz_SB *src);
long long lz_sb_atoll(Lz_SB *src);
#ifndef Lz_HM
#define Lz_HM(K_t, V_t) struct {\
size_t cap;\
@ -138,6 +150,7 @@ typedef Lz_DA(char) Lz_SB;
K_t tmpkey;\
V_t tmpval;\
_Bool *exists;\
_Bool *tombstones;\
K_t *keys;\
V_t *vals;\
}
@ -149,21 +162,24 @@ typedef Lz_DA(char) Lz_SB;
(hm).cnt = 0;\
(hm).keys = malloc((hm).cap*sizeof(*(hm).keys));\
(hm).vals = malloc((hm).cap*sizeof(*(hm).vals));\
(hm).exists = malloc((hm).cap*sizeof(_Bool));\
(hm).exists = calloc((hm).cap,sizeof(_Bool));\
(hm).tombstones = calloc((hm).cap,sizeof(_Bool));\
} while (0)
#endif
#ifndef lz_hm_hash_set
#define lz_hm_hash_set(hm, k) (\
(hm).tmpkey = k,\
lz_hm_hash_void_set((hm).cap, (hm).exists, &(hm).tmpkey, sizeof(*(hm).keys))\
lz_hm_hash_void_set((hm).cap, (hm).exists, (hm).tombstones,\
&(hm).tmpkey, sizeof(*(hm).keys))\
)
#endif
#ifndef lz_hm_hash_get
#define lz_hm_hash_get(hm, k) (\
(hm).tmpkey = k,\
lz_hm_hash_void_get((hm).cap, (hm).exists, &(hm).tmpkey, (hm).keys, sizeof(*(hm).keys))\
lz_hm_hash_void_get((hm).cap, (hm).exists, (hm).tombstones,\
&(hm).tmpkey, (hm).keys, sizeof(*(hm).keys))\
)
#endif
@ -187,16 +203,21 @@ typedef Lz_DA(char) Lz_SB;
void *newkeys = malloc(newcap*sizeof(*(hm).keys));\
void *newvals = malloc(newcap*sizeof(*(hm).vals));\
_Bool *newexists = calloc(newcap, sizeof(_Bool));\
_Bool *newtombstones = calloc(newcap, sizeof(_Bool));\
printf("Grow\n");\
\
for (size_t i = 0; i < (hm).cap; ++i) {\
if ((hm).exists[i]) {\
size_t newhash = lz_hm_hash_void_set(newcap, newexists,\
&(hm).keys[i], sizeof(*(hm).keys));\
newtombstones,\
&(hm).keys[i],\
sizeof(*(hm).keys));\
memcpy(newvals + sizeof(*(hm).vals)*newhash,\
&(hm).vals[i], sizeof(*(hm).vals));\
memcpy(newkeys + sizeof(*(hm).keys)*newhash,\
&(hm).keys[i], sizeof(*(hm).keys));\
newexists[newhash] = 1;\
newtombstones[newhash] = 0;\
}\
}\
free((hm).vals);\
@ -205,6 +226,8 @@ typedef Lz_DA(char) Lz_SB;
(hm).keys = newkeys;\
free((hm).exists);\
(hm).exists = newexists;\
free((hm).tombstones);\
(hm).tombstones = newtombstones;\
(hm).cap = newcap;\
} while(0)
#endif
@ -216,14 +239,23 @@ typedef Lz_DA(char) Lz_SB;
(hm).vals[idx] = v;\
++(hm).cnt;\
(hm).exists[idx] = 1;\
(hm).tombstones[idx] = 0;\
if (4*(hm).cnt > 3*(hm).cap) {\
lz_hm_grow(hm);\
}\
} while(0)
#endif
#ifdef LAZY_IMPL
#ifndef lz_hm_remove
#define lz_hm_remove(hm, k) do {\
size_t idx = lz_hm_hash_get(hm,k);\
(hm).tombstones[idx] = 1;\
(hm).exists[idx] = 0;\
} while(0)
#endif
#ifdef LAZY_IMPL
#undef LAZY_IMPL
size_t lz_hm_hash_raw_bytes(size_t cap, void *key, size_t k_s) {
size_t hash = 0;
for (size_t i = 0; i < k_s; ++i) {
@ -234,32 +266,35 @@ size_t lz_hm_hash_raw_bytes(size_t cap, void *key, size_t k_s) {
return hash % cap;
}
size_t lz_hm_hash_void_get(size_t cap, _Bool *exists, void *key,
void *keys, size_t k_s) {
size_t lz_hm_hash_void_get(size_t cap, _Bool *exists, _Bool *tombstones,
void *key, void *keys, size_t k_s) {
size_t hash = lz_hm_hash_raw_bytes(cap, key, k_s);
for (size_t i = 0; i < cap; ++i) {
size_t localhash = (hash + i) % cap;
int diff = memcmp(keys+k_s*localhash, key, k_s);
if (diff == 0) {
size_t tombstone = tombstones[localhash];
if (diff == 0 && !tombstone) {
return localhash;
}
size_t istaken = exists[localhash];
if (!istaken) {
if (!istaken && !tombstone) {
return (size_t)-1;
}
}
return (size_t)-1;
}
size_t lz_hm_hash_void_set(size_t cap, _Bool *exists, void* key, size_t k_s) {
size_t lz_hm_hash_void_set(size_t cap, _Bool *exists,
_Bool *tombstones, void* key, size_t k_s) {
size_t hash = lz_hm_hash_raw_bytes(cap, key, k_s);
for (size_t i = 0; i < cap; ++i) {
size_t localhash = (hash + i) % cap;
_Bool tombstone = tombstones[localhash];
_Bool istaken = exists[localhash];
if (!istaken) return localhash;
if (!istaken || tombstone) return localhash;
}
return (size_t)-1;
}
@ -274,35 +309,35 @@ char *lz_cstr_dup(const char *s) {
memcpy(p, s, n+1);
return p;
}
void lz_drop_left(Lz_Slc *src, size_t n) {
void lz_slc_drop_left(Lz_Slc *src, size_t n) {
if (src->cnt < n) n = src->cnt;
src->data += n;
src->cnt -= n;
}
void lz_drop_right(Lz_Slc *src, size_t n) {
void lz_slc_drop_right(Lz_Slc *src, size_t n) {
if (src->cnt < n) n = src->cnt;
src->cnt -= n;
}
void lz_trim_left_typ(Lz_Slc *src, int (*classfunc)(int)) {
void lz_slc_trim_left_typ(Lz_Slc *src, int (*classfunc)(int)) {
while (classfunc(src->data[0])) {
lz_drop_left(src, 1);
lz_slc_drop_left(src, 1);
}
}
void lz_trim_right_typ(Lz_Slc *src, int (*classfunc)(int)) {
void lz_slc_trim_right_typ(Lz_Slc *src, int (*classfunc)(int)) {
while (classfunc(src->data[src->cnt-1])) {
lz_drop_right(src, 1);
lz_slc_drop_right(src, 1);
}
}
void lz_trim_typ(Lz_Slc *src, int (*classfunc)(int)) {
lz_trim_left_typ(src, classfunc);
lz_trim_right_typ(src, classfunc);
void lz_slc_trim_typ(Lz_Slc *src, int (*classfunc)(int)) {
lz_slc_trim_left_typ(src, classfunc);
lz_slc_trim_right_typ(src, classfunc);
}
void lz_split_slc(Lz_Slc *src, char delim, Lz_Slc *dst) {
void lz_slc_split(Lz_Slc *src, char delim, Lz_Slc *dst) {
size_t i = 0;
while (i < src->cnt && src->data[i] != delim) {
++i;
@ -317,7 +352,7 @@ 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) {
void lz_slc_split_typ(Lz_Slc *src, int (*classfunc)(int), Lz_Slc *dst) {
size_t i = 0;
while (i < src->cnt && !classfunc(src->data[i])) {
++i;
@ -330,7 +365,7 @@ void lz_split_slc_typ(Lz_Slc *src, int (*classfunc)(int), Lz_Slc *dst) {
} else {
src->cnt = 0;
}
lz_trim_left_typ(src, classfunc);
lz_slc_trim_left_typ(src, classfunc);
}
Lz_SB lz_sb_from_cstr(const char *dat) {
@ -348,4 +383,72 @@ Lz_Slc lz_cstr_to_slc(char *dat) {
out.cnt = strlen(dat);
return out;
}
double lz_slc_atof(Lz_Slc *src) {
char *cstr = malloc(src->cnt+1);
memcpy(cstr, src->data, src->cnt);
cstr[src->cnt] = 0;
double x = atof(cstr);
free(cstr);
return x;
}
int lz_slc_atoi(Lz_Slc *src) {
char *cstr = malloc(src->cnt+1);
memcpy(cstr, src->data, src->cnt);
cstr[src->cnt] = 0;
int x = atoi(cstr);
free(cstr);
return x;
}
long lz_slc_atol(Lz_Slc *src) {
char *cstr = malloc(src->cnt+1);
memcpy(cstr, src->data, src->cnt);
cstr[src->cnt] = 0;
int x = atol(cstr);
free(cstr);
return x;
}
long long lz_slc_atoll(Lz_Slc *src) {
char *cstr = malloc(src->cnt+1);
memcpy(cstr, src->data, src->cnt);
cstr[src->cnt] = 0;
int x = atoll(cstr);
free(cstr);
return x;
}
double lz_sb_atof(Lz_SB *src) {
char *cstr = malloc(src->cnt+1);
memcpy(cstr, src->data, src->cnt);
cstr[src->cnt] = 0;
double x = atof(cstr);
free(cstr);
return x;
}
int lz_sb_atoi(Lz_SB *src) {
char *cstr = malloc(src->cnt+1);
memcpy(cstr, src->data, src->cnt);
cstr[src->cnt] = 0;
int x = atoi(cstr);
free(cstr);
return x;
}
long lz_sb_atol(Lz_SB *src) {
char *cstr = malloc(src->cnt+1);
memcpy(cstr, src->data, src->cnt);
cstr[src->cnt] = 0;
int x = atol(cstr);
free(cstr);
return x;
}
long long lz_sb_atoll(Lz_SB *src) {
char *cstr = malloc(src->cnt+1);
memcpy(cstr, src->data, src->cnt);
cstr[src->cnt] = 0;
int x = atoll(cstr);
free(cstr);
return x;
}
#endif