aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabrice <fabrice@schaub-dev.xyz>2026-03-22 21:31:59 +0100
committerFabrice <fabrice@schaub-dev.xyz>2026-03-22 21:31:59 +0100
commit403d8dc92750679eb96968f5fc4465e96401ef14 (patch)
treeafae902778194e390e7bb994597f6ccf78199240
parent9b43c34b9b51d953bd4363df576a6f93e9596700 (diff)
adding proper example
-rw-r--r--README92
-rw-r--r--cheesemap.c5
-rw-r--r--cheesemap.h22
-rw-r--r--cm-demo.c114
-rw-r--r--makefile2
5 files changed, 141 insertions, 94 deletions
diff --git a/README b/README
index a00fff5..3d4e465 100644
--- a/README
+++ b/README
@@ -7,36 +7,74 @@ is not yet production tested but fully working.
* Example
```
-#include "cheesemap.h"
-#include <stdint.h>
+#include <stdio.h>
#include <string.h>
-#include <stddef.h>
-
-struct user_info {
- const char* country;
- int age;
- int zip;
-};
-
-uint64_t hash(const uint8_t* key) {
- const char* name = (const char*)key;
- uint64_t count;
- while(*name) {
- count++;
- name++;
- }
-
- return count;
+#include "cheesemap.h"
+
+// Convenience macro for array length
+#define countof(arr) (sizeof(arr) / sizeof(*(arr)))
+
+// Simple hash function for string keys
+uint64_t hash_string(const uint8_t* key, uint8_t* user) {
+ (void)user;
+ const char* str = *(const char**)key;
+ uint64_t hash = 5381;
+ int c;
+ while ((c = *str++))
+ hash = ((hash << 5) + hash) + c; // hash * 33 + c
+ return hash;
}
-bool compare(const uint8_t* key1, const uint8_t* key2) {
- const char* name1 = (const char*)key1;
- const char* name2 = (const char*)key2;
- return strcmp(name1, name2);
+// Compare function for string keys
+bool compare_string(const uint8_t* key1, const uint8_t* key2, uint8_t* user) {
+ (void)user;
+ return strcmp(*(const char**)key1, *(const char**)key2) == 0;
}
-int main() {
- struct cheesemap map;
- cm_new(&map, sizeof(const char*), _Alignof(const char*), sizeof(struct user_info), _Alignof(struct user_info), NULL
-}
+int main(void) {
+ // Create a map: string -> int (word frequency counter)
+ struct cheesemap map;
+ cm_new_(&map, const char*, int, NULL, hash_string, compare_string);
+
+ // Count word frequencies
+ const char* words[] = {"hello", "world", "hello", "cheesemap", "world", "hello"};
+ for (size_t i = 0; i < countof(words); i++) {
+ int* count;
+ if (cm_lookup_(&map, words[i], &count)) {
+ (*count)++; // Word exists, increment
+ } else {
+ int initial = 1;
+ cm_insert_(&map, words[i], initial);
+ }
+ }
+
+ // Iterate and print all word counts
+ printf("Word frequencies:\n");
+ struct cheesemap_iter iter;
+ cm_iter_init(&iter, &map);
+ const char** word;
+ int* count;
+ while (cm_iter_next(&iter, &map, (uint8_t**)&word, (uint8_t**)&count)) {
+ printf(" %s: %d\n", *word, *count);
+ }
+
+ // Lookup a specific word
+ const char* search = "hello";
+ if (cm_lookup_(&map, search, &count)) {
+ printf("\n'%s' appears %d times\n", search, *count);
+ }
+
+ // Remove a word
+ const char* remove = "world";
+ cm_remove_(&map, remove, NULL);
+ printf("Removed '%s'\n", remove);
+
+ // Verify removal
+ if (!cm_lookup_(&map, remove, &count)) {
+ printf("'%s' no longer in map\n", remove);
+ }
+
+ cm_drop(&map);
+ return 0;
+}
```
diff --git a/cheesemap.c b/cheesemap.c
index a65b64e..bf1841f 100644
--- a/cheesemap.c
+++ b/cheesemap.c
@@ -351,7 +351,7 @@ bool cm_raw_reserve(struct cheesemap_raw* map, cm_hash_fn hash, uint8_t* user,
return cm_raw_resize(map, hash, user, entry_size, new_capacity);
}
-bool cm_raw_lookup(struct cheesemap_raw* map, cm_hash_fn hash,
+bool cm_raw_lookup(const struct cheesemap_raw* map, cm_hash_fn hash,
cm_compare_fn compare, uint8_t* user, uintptr_t entry_size,
uintptr_t value_offset, const uint8_t* key,
uint8_t** out_value) {
@@ -471,7 +471,8 @@ bool cm_insert(struct cheesemap* map, const uint8_t* key,
value);
}
-bool cm_lookup(struct cheesemap* map, const uint8_t* key, uint8_t** out_value) {
+bool cm_lookup(const struct cheesemap* map, const uint8_t* key,
+ uint8_t** out_value) {
assert(map != NULL);
assert(key != NULL && out_value != NULL);
diff --git a/cheesemap.h b/cheesemap.h
index 27093db..436bfe1 100644
--- a/cheesemap.h
+++ b/cheesemap.h
@@ -96,7 +96,7 @@ bool cm_raw_new_with(struct cheesemap_raw* map, uintptr_t entry_size,
void cm_raw_drop(struct cheesemap_raw* map, uintptr_t entry_size);
bool cm_raw_reserve(struct cheesemap_raw* map, cm_hash_fn hash, uint8_t* user,
uintptr_t entry_size, uintptr_t additional);
-bool cm_raw_lookup(struct cheesemap_raw* map, cm_hash_fn hash,
+bool cm_raw_lookup(const struct cheesemap_raw* map, cm_hash_fn hash,
cm_compare_fn compare, uint8_t* user, uintptr_t entry_size,
uintptr_t value_offset, const uint8_t* key,
uint8_t** out_value);
@@ -127,11 +127,29 @@ void cm_new(struct cheesemap* map, uintptr_t key_size, uintptr_t key_align,
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_lookup(const 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 convenience macros
+//
+
+#define cm_new_(map, K, V, user, hash_fn, cmp_fn) \
+ cm_new(map, sizeof(K), _Alignof(K), sizeof(V), _Alignof(V), user, hash_fn, \
+ cmp_fn)
+
+#define cm_lookup_(map, key, out_val) \
+ cm_lookup(map, (const uint8_t*)&(key), (uint8_t**)(out_val))
+
+#define cm_insert_(map, key, val) \
+ cm_insert(map, (const uint8_t*)&(key), (const uint8_t*)&(val))
+
+#define cm_remove_(map, key, out_val) \
+ cm_remove(map, (const uint8_t*)&(key), (uint8_t*)(out_val))
+
+////////////////////////////////
// cheesemap iterators
//
diff --git a/cm-demo.c b/cm-demo.c
index 8d79333..3d91843 100644
--- a/cm-demo.c
+++ b/cm-demo.c
@@ -1,83 +1,71 @@
-#include <stddef.h>
-#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "cheesemap.h"
-struct user_info {
- const char* country;
- int age;
- int zip;
-};
+// Convenience macro for array length
+#define countof(arr) (sizeof(arr) / sizeof(*(arr)))
-static const char* NAME = "Max Mustermann";
-static struct user_info INFO = {
- .age = 23,
- .country = "germany",
- .zip = 69420,
-};
-
-static const char* NAME2 = "Peter Urs";
-static struct user_info INFO2 = {
- .age = 64,
- .country = "switzerland",
- .zip = 1201,
-};
-
-uint64_t hash(const uint8_t* key, uint8_t* user) {
+// Simple hash function for string keys
+uint64_t hash_string(const uint8_t* key, uint8_t* user) {
(void)user;
-
- const char* name = (const char*)key;
- uint64_t count;
- while (*name) {
- count++;
- name++;
- }
-
- return count;
+ const char* str = *(const char**)key;
+ uint64_t hash = 5381;
+ int c;
+ while ((c = *str++)) hash = ((hash << 5) + hash) + c; // hash * 33 + c
+ return hash;
}
-bool compare(const uint8_t* key1, const uint8_t* key2, uint8_t* user) {
+// Compare function for string keys
+bool compare_string(const uint8_t* key1, const uint8_t* key2, uint8_t* user) {
(void)user;
-
- const char* name1 = (const char*)key1;
- const char* name2 = (const char*)key2;
- return strcmp(name1, name2) == 0;
+ return strcmp(*(const char**)key1, *(const char**)key2) == 0;
}
-int main() {
+int main(void) {
+ // Create a map: string -> int (word frequency counter)
struct cheesemap map;
- cm_new(&map, sizeof(const char*), _Alignof(const char*),
- sizeof(struct user_info), _Alignof(struct user_info), NULL, hash,
- compare);
-
- bool ok = cm_insert(&map, (const uint8_t*)NAME, (uint8_t*)&INFO);
- if (!ok) return 1;
-
- ok = cm_insert(&map, (const uint8_t*)NAME2, (const uint8_t*)&INFO2);
- if (!ok) return 1;
-
- struct user_info* found_max;
- ok = cm_lookup(&map, (const uint8_t*)NAME, (uint8_t**)&found_max);
- if (!ok) return 1;
+ cm_new_(&map, const char*, int, NULL, hash_string, compare_string);
+
+ // Count word frequencies
+ const char* words[] = {"hello", "world", "hello",
+ "cheesemap", "world", "hello"};
+ for (size_t i = 0; i < countof(words); i++) {
+ int* count;
+ if (cm_lookup_(&map, words[i], &count)) {
+ (*count)++; // Word exists, increment
+ } else {
+ int initial = 1;
+ cm_insert_(&map, words[i], initial);
+ }
+ }
- if (memcmp(&INFO, found_max, sizeof(struct user_info)) != 0) return 1;
- printf("Max Mustermann is of age %d lives in %s at ZIP %d\n", found_max->age,
- found_max->country, found_max->zip);
+ // Iterate and print all word counts
+ printf("Word frequencies:\n");
+ struct cheesemap_iter iter;
+ cm_iter_init(&iter, &map);
+ const char** word;
+ int* count;
+ while (cm_iter_next(&iter, &map, (uint8_t**)&word, (uint8_t**)&count)) {
+ printf(" %s: %d\n", *word, *count);
+ }
- struct user_info* found_peter;
- ok = cm_lookup(&map, (const uint8_t*)NAME2, (uint8_t**)&found_peter);
- if (memcmp(&INFO2, found_peter, sizeof(struct user_info)) != 0) return 1;
- printf("Peter Urs is of age %d lives in %s at ZIP %d\n", found_peter->age,
- found_peter->country, found_peter->zip);
+ // Lookup a specific word
+ const char* search = "hello";
+ if (cm_lookup_(&map, search, &count)) {
+ printf("\n'%s' appears %d times\n", search, *count);
+ }
- ok = cm_remove(&map, (const uint8_t*)NAME, NULL);
- if (!ok) return 1;
+ // Remove a word
+ const char* remove = "world";
+ cm_remove_(&map, remove, NULL);
+ printf("Removed '%s'\n", remove);
- struct user_info* found_max2;
- ok = cm_lookup(&map, (const uint8_t*)NAME, (uint8_t**)&found_max2);
- if (ok) return 1;
+ // Verify removal
+ if (!cm_lookup_(&map, remove, &count)) {
+ printf("'%s' no longer in map\n", remove);
+ }
cm_drop(&map);
+ return 0;
}
diff --git a/makefile b/makefile
index a43759e..83ee20a 100644
--- a/makefile
+++ b/makefile
@@ -1,3 +1,5 @@
+.SUFFIXES:
+
CM_OPT_RELEASE ?= 0
CM_OPT_CC_FLAGS ?=
CM_OPT_ASSERT_PATH ?= <assert.h>