aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabrice <fabrice@schaub-dev.xyz>2026-03-22 13:49:46 +0100
committerFabrice <fabrice@schaub-dev.xyz>2026-03-22 13:49:46 +0100
commit5f955749eb99e53304338453e351c9f8e5f5a2f7 (patch)
tree88563277f9569ee078974a57f19a02c555b3757c
parente4cd519363547444be338ff087a559bb0490c5f1 (diff)
finishing wrapper
-rw-r--r--cheesemap.c71
-rw-r--r--cheesemap.h13
-rw-r--r--cm-demo.c102
3 files changed, 177 insertions, 9 deletions
diff --git a/cheesemap.c b/cheesemap.c
index bdaee94..f5ea7f4 100644
--- a/cheesemap.c
+++ b/cheesemap.c
@@ -209,7 +209,7 @@ static bool cm_raw_find_in_group(const struct cheesemap_raw* map,
const struct cheesemap_fns* fns, group_t group,
const struct sequence* seq, uint8_t h2,
uintptr_t key_size, const uint8_t* key,
- uintptr_t* out_index) {
+ uintptr_t value_size, uintptr_t* out_index) {
assert(map != NULL && fns != NULL);
assert(seq != NULL);
assert(key != NULL && out_index != NULL);
@@ -219,7 +219,7 @@ static bool cm_raw_find_in_group(const struct cheesemap_raw* map,
uintptr_t bucket_offset = cm_bitmask_lowest_set_bit(mask);
uintptr_t index = (seq->pos + bucket_offset) & map->bucket_mask;
- uint8_t* elem = cm_raw_elem_at(map, index, key_size);
+ uint8_t* elem = cm_raw_elem_at(map, index, key_size + value_size);
if (fns->compare(key, elem, fns->map_usr)) {
*out_index = index;
return true;
@@ -234,7 +234,7 @@ static bool cm_raw_find_in_group(const struct cheesemap_raw* map,
static bool cm_raw_find(const struct cheesemap_raw* map,
const struct cheesemap_fns* fns, cm_hash_t hash,
uintptr_t key_size, const uint8_t* key,
- uintptr_t* out_index) {
+ uintptr_t value_size, uintptr_t* out_index) {
assert(map != NULL && fns != NULL);
assert(key != NULL && out_index != NULL);
@@ -246,7 +246,7 @@ static bool cm_raw_find(const struct cheesemap_raw* map,
group_t group = cm_group_load(ctrl);
if (cm_raw_find_in_group(map, fns, group, &seq, h2, key_size, key,
- out_index))
+ value_size, out_index))
return true;
if (cm_group_match_empty(group) != 0) return false;
@@ -367,7 +367,8 @@ bool cm_raw_lookup(struct cheesemap_raw* map, const struct cheesemap_fns* fns,
cm_hash_t hash = fns->hash(key, fns->map_usr);
uintptr_t index;
- if (!cm_raw_find(map, fns, hash, key_size, key, &index)) return false;
+ if (!cm_raw_find(map, fns, hash, key_size, key, value_size, &index))
+ return false;
uint8_t* elem = cm_raw_elem_at(map, index, key_size + value_size);
*out_value = elem + key_size;
@@ -383,7 +384,8 @@ bool cm_raw_remove(struct cheesemap_raw* map, const struct cheesemap_fns* fns,
cm_hash_t hash = fns->hash(key, fns->map_usr);
uintptr_t index;
- if (!cm_raw_find(map, fns, hash, key_size, key, &index)) return false;
+ if (!cm_raw_find(map, fns, hash, key_size, key, value_size, &index))
+ return false;
if (out_value != NULL) {
uint8_t* elem = cm_raw_elem_at(map, index, key_size + value_size);
@@ -465,6 +467,38 @@ void cm_drop(struct cheesemap* map) {
memset(map, 0, sizeof(*map));
}
+bool cm_insert(struct cheesemap* map, const uint8_t* key,
+ const uint8_t* value) {
+ assert(map != NULL);
+ assert(key != NULL && value != NULL);
+
+ return cm_raw_insert(&map->raw, &map->fns, map->key_size, key,
+ map->value_size, value);
+}
+
+bool cm_lookup(struct cheesemap* map, const uint8_t* key, uint8_t** out_value) {
+ assert(map != NULL);
+ assert(key != NULL && out_value != NULL);
+
+ return cm_raw_lookup(&map->raw, &map->fns, map->key_size, key,
+ map->value_size, out_value);
+}
+
+bool cm_remove(struct cheesemap* map, const uint8_t* key, uint8_t* out_value) {
+ assert(map != NULL);
+ assert(key != NULL);
+
+ return cm_raw_remove(&map->raw, &map->fns, map->key_size, key,
+ map->value_size, out_value);
+}
+
+bool cm_reserve(struct cheesemap* map, uintptr_t additional) {
+ assert(map != NULL);
+
+ return cm_raw_reserve(&map->raw, &map->fns, map->key_size, map->value_size,
+ additional);
+}
+
/* iterator */
static inline uint8_t* cm_raw_iter_next_entry(
const struct cheesemap_raw_iter* iter, uint8_t* old_entry,
@@ -533,3 +567,28 @@ bool cheesemap_raw_iter_next(struct cheesemap_raw_iter* iter,
iter->n_entry = cm_raw_iter_next_entry(iter, iter->n_entry, entry_size);
}
}
+
+void cm_iter_init(struct cheesemap_iter* iter, const struct cheesemap* map) {
+ assert(iter != NULL && map != NULL);
+
+ iter->key_size = map->key_size;
+ iter->value_size = map->value_size;
+ cm_raw_iter_init(&iter->raw, &map->raw, map->key_size + map->value_size, 0);
+}
+
+bool cm_iter_next(struct cheesemap_iter* iter, const struct cheesemap* map,
+ uint8_t** out_key, uint8_t** out_value) {
+ assert(iter != NULL && map != NULL);
+ assert(out_key != NULL && out_value != NULL);
+
+ uintptr_t index;
+ if (!cheesemap_raw_iter_next(&iter->raw, iter->key_size + iter->value_size,
+ &index))
+ return false;
+
+ uint8_t* elem =
+ cm_raw_elem_at(&map->raw, index, iter->key_size + iter->value_size);
+ *out_key = elem;
+ *out_value = elem + iter->key_size;
+ return true;
+}
diff --git a/cheesemap.h b/cheesemap.h
index 423ec17..d1f72ef 100644
--- a/cheesemap.h
+++ b/cheesemap.h
@@ -140,6 +140,11 @@ void cm_new(struct cheesemap* map, uintptr_t key_size, uintptr_t value_size,
uint8_t* mem_usr, cm_malloc_fn malloc, cm_free_fn free,
uint8_t* map_usr, cm_hash_fn hash, cm_compare_fn compare);
void cm_drop(struct cheesemap* map);
+bool cm_insert(struct cheesemap* map, const uint8_t* key,
+ const uint8_t* value);
+bool cm_lookup(struct cheesemap* map, const uint8_t* key, uint8_t** out_value);
+bool cm_remove(struct cheesemap* map, const uint8_t* key, uint8_t* out_value);
+bool cm_reserve(struct cheesemap* map, uintptr_t additional);
////////////////////////////////
// cheesemap iterators
@@ -159,6 +164,14 @@ void cm_raw_iter_init(struct cheesemap_raw_iter* iter,
bool cheesemap_raw_iter_next(struct cheesemap_raw_iter* iter,
uintptr_t entry_size, uintptr_t* out_index);
+struct cheesemap_iter {
+ uintptr_t key_size, value_size;
+ struct cheesemap_raw_iter raw;
+};
+
+void cm_iter_init(struct cheesemap_iter* iter, const struct cheesemap* map);
+bool cm_iter_next(struct cheesemap_iter* iter, const struct cheesemap* map,
+ uint8_t** out_key, uint8_t** out_value);
#ifdef __cplusplus
}
diff --git a/cm-demo.c b/cm-demo.c
index ed90ca1..d872daa 100644
--- a/cm-demo.c
+++ b/cm-demo.c
@@ -41,9 +41,7 @@ int main() {
for (uint64_t i = 0; i < num_entries; i++) {
uint64_t key = i;
uint64_t value = i * 2;
- bool success =
- cm_raw_insert(&map.raw, &map.fns, sizeof(uint64_t), (uint8_t*)&key,
- sizeof(uint64_t), (uint8_t*)&value);
+ bool success = cm_insert(&map, (uint8_t*)&key, (uint8_t*)&value);
if (!success) {
printf("Insert failed at i=%lu\n", i);
cm_drop(&map);
@@ -61,6 +59,104 @@ int main() {
printf("Map buckets: %lu\n", map.raw.bucket_mask + 1);
printf("Growth left: %lu\n", map.raw.growth_left);
+ // Test lookups
+ printf("\nTesting lookups...\n");
+ for (uint64_t i = 0; i < 10; i++) {
+ uint64_t key = i * 100000;
+ uint8_t* value_ptr;
+ if (cm_lookup(&map, (uint8_t*)&key, &value_ptr)) {
+ uint64_t value = *(uint64_t*)value_ptr;
+ printf(" Lookup key=%lu -> value=%lu (expected %lu)\n", key, value,
+ key * 2);
+ } else {
+ printf(" Lookup key=%lu FAILED\n", key);
+ }
+ }
+
+ // Test iteration
+ printf("\nIterating first 10 entries...\n");
+ struct cheesemap_iter iter;
+ cm_iter_init(&iter, &map);
+ uintptr_t count = 0;
+ uint8_t *key_ptr, *value_ptr;
+ while (cm_iter_next(&iter, &map, &key_ptr, &value_ptr)) {
+ uint64_t key = *(uint64_t*)key_ptr;
+ uint64_t value = *(uint64_t*)value_ptr;
+ if (count < 10) {
+ printf(" [%lu] key=%lu, value=%lu\n", count, key, value);
+ }
+ count++;
+ }
+ printf(" Total iterated: %lu entries\n", count);
+
+ // Test removes
+ printf("\nTesting removes...\n");
+ for (uint64_t i = 0; i < 5; i++) {
+ uint64_t key = i * 200000;
+ uint64_t old_value;
+ if (cm_remove(&map, (uint8_t*)&key, (uint8_t*)&old_value)) {
+ printf(" Removed key=%lu, old_value=%lu\n", key, old_value);
+ } else {
+ printf(" Remove key=%lu FAILED\n", key);
+ }
+ }
+ printf("Map count after removes: %lu\n", map.raw.count);
+
+ // Verify removes worked
+ printf("\nVerifying removes...\n");
+ for (uint64_t i = 0; i < 5; i++) {
+ uint64_t key = i * 200000;
+ uint8_t* value_ptr;
+ if (cm_lookup(&map, (uint8_t*)&key, &value_ptr)) {
+ printf(" ERROR: key=%lu still exists!\n", key);
+ } else {
+ printf(" Confirmed key=%lu removed\n", key);
+ }
+ }
+
+ // Deep check: verify ALL remaining entries
+ printf("\nDeep check: verifying all %lu remaining entries...\n",
+ map.raw.count);
+ uint64_t checked = 0, errors = 0;
+ for (uint64_t i = 0; i < num_entries; i++) {
+ uint64_t key = i;
+ uint8_t* value_ptr;
+ bool should_exist = (i % 200000 != 0 || i / 200000 >= 5);
+
+ if (cm_lookup(&map, (uint8_t*)&key, &value_ptr)) {
+ uint64_t value = *(uint64_t*)value_ptr;
+ if (!should_exist) {
+ printf(" ERROR: key=%lu exists but should be removed!\n", key);
+ errors++;
+ } else if (value != key * 2) {
+ printf(" ERROR: key=%lu has wrong value %lu (expected %lu)\n", key,
+ value, key * 2);
+ errors++;
+ }
+ checked++;
+ } else {
+ if (should_exist) {
+ printf(" ERROR: key=%lu missing but should exist!\n", key);
+ errors++;
+ }
+ }
+ }
+ printf(" Checked %lu entries, found %lu errors\n", checked, errors);
+
+ // Verify iteration count matches
+ printf("\nVerifying iteration count...\n");
+ cm_iter_init(&iter, &map);
+ count = 0;
+ while (cm_iter_next(&iter, &map, &key_ptr, &value_ptr)) {
+ count++;
+ }
+ if (count == map.raw.count) {
+ printf(" OK: iteration count %lu matches map count\n", count);
+ } else {
+ printf(" ERROR: iteration count %lu != map count %lu\n", count,
+ map.raw.count);
+ }
+
// Calculate memory usage
uintptr_t entry_size = sizeof(uint64_t) + sizeof(uint64_t);
uintptr_t buckets = map.raw.bucket_mask + 1;