add keymap
This commit is contained in:
parent
1558467b41
commit
7d5b4ea151
97
collection.c
97
collection.c
@ -232,3 +232,100 @@ char* arena_strdup(Arena* a, const char* str)
|
|||||||
strcpy(p, str);
|
strcpy(p, str);
|
||||||
return p;
|
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);
|
||||||
|
|||||||
15
collection.h
15
collection.h
@ -92,4 +92,19 @@ char* arena_strdup(Arena* a, const char* str);
|
|||||||
(ELEM_PTR), \
|
(ELEM_PTR), \
|
||||||
sizeof(*(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
|
#endif
|
||||||
|
|||||||
11
main.c
11
main.c
@ -100,4 +100,15 @@ int main(int argc, char* argv[])
|
|||||||
arena_deinit(&ast_arena);
|
arena_deinit(&ast_arena);
|
||||||
arena_deinit(&sym_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);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user