diff options
| author | Ginger Bill <bill@gingerbill.org> | 2016-09-01 20:38:44 +0100 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2016-09-01 20:38:44 +0100 |
| commit | fa09d805e23c59cb881573a7a1aee5fbc5752ea2 (patch) | |
| tree | 5407c69e5f63b0d3dcab9eef6fee323273070445 /src/common.cpp | |
| parent | ff6e21cb879397982cddf3cf5f47bba681271a2c (diff) | |
Match statements; Type System change (Type_Record for all sum and product types)
Diffstat (limited to 'src/common.cpp')
| -rw-r--r-- | src/common.cpp | 145 |
1 files changed, 129 insertions, 16 deletions
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 <typename T> void map_clear (Map<T> *h); template <typename T> void map_grow (Map<T> *h); template <typename T> void map_rehash (Map<T> *h, isize new_count); +template <typename T> typename MapEntry<T> *multi_map_find_first(Map<T> *h, HashKey key); +template <typename T> typename MapEntry<T> *multi_map_find_next (Map<T> *h, typename MapEntry<T> *e); + +template <typename T> isize multi_map_count (Map<T> *h, HashKey key); +template <typename T> void multi_map_get_all (Map<T> *h, HashKey key, T *items); +template <typename T> void multi_map_insert (Map<T> *h, HashKey key, T value); +template <typename T> void multi_map_remove (Map<T> *h, HashKey key, typename MapEntry<T> *e); +template <typename T> void multi_map_remove_all(Map<T> *h, HashKey key); + template <typename T> @@ -151,6 +160,24 @@ gb_internal MapFindResult map__find(Map<T> *h, HashKey key) { } template <typename T> +gb_internal MapFindResult map__find(Map<T> *h, typename MapEntry<T> *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 <typename T> gb_internal b32 map__full(Map<T> *h) { return 0.75f * gb_array_count(h->hashes) <= gb_array_count(h->entries); } @@ -221,26 +248,33 @@ void map_set(Map<T> *h, HashKey key, T value) { map_grow(h); } + + +template <typename T> +void map__erase(Map<T> *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 <typename T> void map_remove(Map<T> *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<T> *h) { gb_array_clear(h->hashes); gb_array_clear(h->entries); } + + + +template <typename T> +typename MapEntry<T> *multi_map_find_first(Map<T> *h, HashKey key) { + isize i = map__find(h, key).entry_index; + if (i < 0) { + return NULL; + } + return &h->entries[i]; +} + +template <typename T> +typename MapEntry<T> *multi_map_find_next(Map<T> *h, typename MapEntry<T> *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 <typename T> +isize multi_map_count(Map<T> *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 <typename T> +void multi_map_get_all(Map<T> *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 <typename T> +void multi_map_insert(Map<T> *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 <typename T> +void multi_map_remove(Map<T> *h, HashKey key, typename MapEntry<T> *e) { + MapFindResult fr = map__find(h, e); + if (fr.entry_index >= 0) { + map__erase(h, fr); + } +} + +template <typename T> +void multi_map_remove_all(Map<T> *h, HashKey key) { + while (map_get(h, key) != NULL) { + map_remove(h, key); + } +} + |