From fa09d805e23c59cb881573a7a1aee5fbc5752ea2 Mon Sep 17 00:00:00 2001 From: Ginger Bill Date: Thu, 1 Sep 2016 20:38:44 +0100 Subject: Match statements; Type System change (Type_Record for all sum and product types) --- src/common.cpp | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 129 insertions(+), 16 deletions(-) (limited to 'src/common.cpp') diff --git a/src/common.cpp b/src/common.cpp index ccf165d35..890c82373 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -110,6 +110,15 @@ template void map_clear (Map *h); template void map_grow (Map *h); template void map_rehash (Map *h, isize new_count); +template typename MapEntry *multi_map_find_first(Map *h, HashKey key); +template typename MapEntry *multi_map_find_next (Map *h, typename MapEntry *e); + +template isize multi_map_count (Map *h, HashKey key); +template void multi_map_get_all (Map *h, HashKey key, T *items); +template void multi_map_insert (Map *h, HashKey key, T value); +template void multi_map_remove (Map *h, HashKey key, typename MapEntry *e); +template void multi_map_remove_all(Map *h, HashKey key); + template @@ -150,6 +159,24 @@ gb_internal MapFindResult map__find(Map *h, HashKey key) { return fr; } +template +gb_internal MapFindResult map__find(Map *h, typename MapEntry *e) { + MapFindResult fr = {-1, -1, -1}; + if (gb_array_count(h->hashes) > 0) { + fr.hash_index = e->key.key % gb_array_count(h->hashes); + fr.entry_index = h->hashes[fr.hash_index]; + while (fr.entry_index >= 0) { + if (&h->entries[fr.entry_index] == e) { + return fr; + } + fr.entry_prev = fr.entry_index; + fr.entry_index = h->entries[fr.entry_index].next; + } + } + return fr; +} + + template gb_internal b32 map__full(Map *h) { return 0.75f * gb_array_count(h->hashes) <= gb_array_count(h->entries); @@ -221,26 +248,33 @@ void map_set(Map *h, HashKey key, T value) { map_grow(h); } + + +template +void map__erase(Map *h, MapFindResult fr) { + if (fr.entry_prev < 0) { + h->hashes[fr.hash_index] = h->entries[fr.entry_index].next; + } else { + h->entries[fr.entry_prev].next = h->entries[fr.entry_index].next; + } + if (fr.entry_index == gb_array_count(h->entries)-1) { + gb_array_pop(h->entries); + return; + } + h->entries[fr.entry_index] = h->entries[gb_array_count(h->entries)-1]; + MapFindResult last = map__find(h, h->entries[fr.entry_index].key); + if (last.entry_prev >= 0) { + h->entries[last.entry_prev].next = fr.entry_index; + } else { + h->hashes[last.hash_index] = fr.entry_index; + } +} + template void map_remove(Map *h, HashKey key) { MapFindResult fr = map__find(h, key); if (fr.entry_index >= 0) { - if (fr.entry_prev < 0) { - h->hashes[fr.hash_index] = h->entries[fr.entry_index].next; - } else { - h->entries[fr.entry_prev].next = h->entries[fr.entry_index].next; - } - if (fr.entry_index == gb_array_count(h->entries)-1) { - gb_array_pop(h->entries); - return; - } - h->entries[fr.entry_index] = h->entries[gb_array_count(h->entries)-1]; - MapFindResult last = map__find(h, h->entries[fr.entry_index].key); - if (last.entry_prev >= 0) { - h->entries[last.entry_prev].next = fr.entry_index; - } else { - h->hashes[last.hash_index] = fr.entry_index; - } + map__erase(h, fr); } } @@ -249,3 +283,82 @@ gb_inline void map_clear(Map *h) { gb_array_clear(h->hashes); gb_array_clear(h->entries); } + + + +template +typename MapEntry *multi_map_find_first(Map *h, HashKey key) { + isize i = map__find(h, key).entry_index; + if (i < 0) { + return NULL; + } + return &h->entries[i]; +} + +template +typename MapEntry *multi_map_find_next(Map *h, typename MapEntry *e) { + isize i = e->next; + while (i >= 0) { + if (hash_key_equal(h->entries[i].key, e->key)) { + return &h->entries[i]; + } + i = h->entries[i].next; + } + return NULL; +} + +template +isize multi_map_count(Map *h, HashKey key) { + isize count = 0; + auto *e = multi_map_find_first(h, key); + while (e != NULL) { + count++; + e = multi_map_find_next(h, e); + } + return count; +} + +template +void multi_map_get_all(Map *h, HashKey key, T *items) { + isize i = 0; + auto *e = multi_map_find_first(h, key); + while (e != NULL) { + items[i++] = e->value; + e = multi_map_find_next(h, e); + } +} + +template +void multi_map_insert(Map *h, HashKey key, T value) { + if (gb_array_count(h->hashes) == 0) { + map_grow(h); + } + MapFindResult fr = map__find(h, key); + isize i = map__add_entry(h, key); + if (fr.entry_prev < 0) { + h->hashes[fr.hash_index] = i; + } else { + h->entries[fr.entry_prev].next = i; + } + h->entries[i].next = fr.entry_index; + h->entries[i].value = value; + if (map__full(h)) { + map_grow(h); + } +} + +template +void multi_map_remove(Map *h, HashKey key, typename MapEntry *e) { + MapFindResult fr = map__find(h, e); + if (fr.entry_index >= 0) { + map__erase(h, fr); + } +} + +template +void multi_map_remove_all(Map *h, HashKey key) { + while (map_get(h, key) != NULL) { + map_remove(h, key); + } +} + -- cgit v1.2.3