From 7d5b4ea151e8df1861f5948f0d45830fee7ca1b4 Mon Sep 17 00:00:00 2001 From: sfja Date: Fri, 2 Oct 2026 04:37:30 +0200 Subject: [PATCH] add keymap --- collection.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++ collection.h | 15 ++++++++ main.c | 11 ++++++ 3 files changed, 123 insertions(+) diff --git a/collection.c b/collection.c index 94edff4..022091c 100644 --- a/collection.c +++ b/collection.c @@ -232,3 +232,100 @@ char* arena_strdup(Arena* a, const char* str) strcpy(p, str); return p; } + +struct KeymapEntry { + KeymapKey key; + unsigned char value[]; +}; + +void keymap_init(Keymap* m, size_t elem_size) +{ + size_t entry_size = sizeof(KeymapEntry) + (elem_size + 7ul & ~7ul); + + *m = (Keymap) { + ARRAY_FIELD_INIT(entries), + .elem_size = elem_size, + .entry_size = entry_size, + .temp_entry = malloc(entry_size), + }; +} + +void keymap_deinit(Keymap* m) +{ + if (m->entries) + free(m->entries); + free(m->temp_entry); +} + +static KeymapEntry* keymap_idx(Keymap* m, size_t idx) +{ + return (KeymapEntry*)((unsigned char*)m->entries + m->entry_size * idx); +} + +struct SearchResult { + KeymapEntry* entry; + size_t idx; +}; + +static struct SearchResult keymap_search( + Keymap* m, size_t begin, size_t end, KeymapKey key) +{ + if (begin == end) + return (struct SearchResult) { nullptr, begin }; + + size_t middle = (end - begin) / 2 + begin; + KeymapEntry* entry = keymap_idx(m, middle); + + if (entry->key == key) + return (struct SearchResult) { entry, middle }; + + return key < entry->key ? keymap_search(m, begin, middle, key) + : keymap_search(m, middle + 1, end, key); +} + +void keymap_set(Keymap* m, KeymapKey key, void* value) +{ + struct SearchResult result = keymap_search(m, 0, m->entries_size, key); + + if (result.entry) { + memcpy(result.entry->value, value, m->elem_size); + return; + } + + printf("index = %ld\n", result.idx); + + if (m->entries_size) { + if (keymap_idx(m, result.idx)->key < key) { + printf("key is bigger\n"); + } else { + printf("key is smaller\n"); + } + } + + KeymapEntry* entry = m->temp_entry; + memset(entry, 0, m->entry_size); + + array_push((void**)&m->entries, + &m->entries_cap, + &m->entries_size, + entry, + m->entry_size); + + entry->key = key; + memcpy(&entry->value, value, m->elem_size); + + if (result.idx < m->entries_size - 1) { + memmove(keymap_idx(m, result.idx + 1), + keymap_idx(m, result.idx), + (m->entries_size - result.idx - 1) * m->entry_size); + } + + memcpy(keymap_idx(m, result.idx), entry, m->entry_size); + + for (size_t i = 0; i < m->entries_size; ++i) { + KeymapEntry* entry = keymap_idx(m, i); + printf(" %ld -> %d\n", entry->key, *(int*)entry->value); + } +} + +void* keymap_get(Keymap* m, KeymapKey key); diff --git a/collection.h b/collection.h index c49f389..408952d 100644 --- a/collection.h +++ b/collection.h @@ -92,4 +92,19 @@ char* arena_strdup(Arena* a, const char* str); (ELEM_PTR), \ sizeof(*(ELEM_PTR))) +typedef size_t KeymapKey; +typedef struct KeymapEntry KeymapEntry; + +typedef struct { + ARRAY_FIELD(KeymapEntry, entries); + size_t elem_size; + size_t entry_size; + KeymapEntry* temp_entry; +} Keymap; + +void keymap_init(Keymap* m, size_t elem_size); +void keymap_deinit(Keymap* m); +void keymap_set(Keymap* m, KeymapKey key, void* value); +void* keymap_get(Keymap* m, KeymapKey key); + #endif diff --git a/main.c b/main.c index 7065576..cea8a8e 100644 --- a/main.c +++ b/main.c @@ -100,4 +100,15 @@ int main(int argc, char* argv[]) arena_deinit(&ast_arena); arena_deinit(&sym_arena); } + + Keymap map; + keymap_init(&map, sizeof(int)); + + int a[] = { 3, 1, 4, 1 }; + keymap_set(&map, 4, &a[3]); + keymap_set(&map, 3, &a[2]); + keymap_set(&map, 2, &a[1]); + keymap_set(&map, 1, &a[0]); + + keymap_deinit(&map); }