diff options
| author | Fabrice <fabrice@schaub-dev.xyz> | 2026-03-22 21:31:59 +0100 |
|---|---|---|
| committer | Fabrice <fabrice@schaub-dev.xyz> | 2026-03-22 21:31:59 +0100 |
| commit | 403d8dc92750679eb96968f5fc4465e96401ef14 (patch) | |
| tree | afae902778194e390e7bb994597f6ccf78199240 | |
| parent | 9b43c34b9b51d953bd4363df576a6f93e9596700 (diff) | |
adding proper example
| -rw-r--r-- | README | 92 | ||||
| -rw-r--r-- | cheesemap.c | 5 | ||||
| -rw-r--r-- | cheesemap.h | 22 | ||||
| -rw-r--r-- | cm-demo.c | 114 | ||||
| -rw-r--r-- | makefile | 2 |
5 files changed, 141 insertions, 94 deletions
@@ -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 // @@ -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; } @@ -1,3 +1,5 @@ +.SUFFIXES: + CM_OPT_RELEASE ?= 0 CM_OPT_CC_FLAGS ?= CM_OPT_ASSERT_PATH ?= <assert.h> |
