diff options
| -rw-r--r-- | examples/25.pry | 54 | ||||
| -rw-r--r-- | std/hashmap.pry | 81 |
2 files changed, 135 insertions, 0 deletions
diff --git a/examples/25.pry b/examples/25.pry new file mode 100644 index 0000000..6c497aa --- /dev/null +++ b/examples/25.pry @@ -0,0 +1,54 @@ +import "!stdlib.pry"; +import "!mem.pry"; +import "!hashmap.pry"; + +let main = () => i64 { + let alloc = arena_init(1024); + + let map = hashmap_init(8, alloc); + + hashmap_put(map, "name", cast(*void, "Alice")); + hashmap_put(map, "city", cast(*void, "Boston")); + hashmap_put(map, "job", cast(*void, "Engineer")); + + let name = cast(*i8, hashmap_get(map, "name")); + let city = cast(*i8, hashmap_get(map, "city")); + let job = cast(*i8, hashmap_get(map, "job")); + + printf("Name: %s\n", name); + printf("City: %s\n", city); + printf("Job: %s\n", job); + + hashmap_put(map, "name", cast(*void, "Bob")); + hashmap_put(map, "city", cast(*void, "Seattle")); + + let new_name = cast(*i8, hashmap_get(map, "name")); + let new_city = cast(*i8, hashmap_get(map, "city")); + + printf("Updated Name: %s\n", new_name); + printf("Updated City: %s\n", new_city); + + let missing = hashmap_get(map, "missing"); + if missing == cast(*void, null) { + printf("Missing key not found\n"); + }; + + arena_free(alloc); + + return 0; +}; + +/* + +Expected stdout: + +Name: Alice +City: Boston +Job: Engineer +Updated Name: Bob +Updated City: Seattle +Missing key not found + +Expected return: 0 + +*/ diff --git a/std/hashmap.pry b/std/hashmap.pry new file mode 100644 index 0000000..5022596 --- /dev/null +++ b/std/hashmap.pry @@ -0,0 +1,81 @@ +import "!mem.pry"; +import "!stdlib.pry"; + +let HashMapEntry = struct { + key: *i8, + value: *void, + next: *HashMapEntry, +}; + +let HashMap = struct { + buckets: **HashMapEntry, + bucket_count: i64, + arena: *arena, +}; + +let simple_hash = (key: *i8, bucket_count: i64) => i64 { + let hash = 0; + let i = 0; + while true { + let c = *(key + cast(*i8, i)); + if c == '\0' { + return hash % bucket_count; + }; + let x = cast(i64, c); + hash = hash + x; + i = i + 1; + }; + return hash % bucket_count; +}; + +let hashmap_init = (bucket_count: i64, alloc: *arena) => *HashMap { + let map = cast(*HashMap, arena_alloc(alloc, sizeof(HashMap))); + (*map).buckets = cast(**HashMapEntry, arena_alloc(alloc, sizeof(*HashMapEntry) * bucket_count)); + (*map).bucket_count = bucket_count; + (*map).arena = alloc; + + let i = 0; + while i < bucket_count { + (*((*map).buckets + cast(**HashMapEntry, i))) = cast(*HashMapEntry, null); + i = i + 1; + }; + + return map; +}; + +let hashmap_put = (map: *HashMap, key: *i8, value: *void) => void { + let bucket_index = simple_hash(key, (*map).bucket_count); + let bucket = *((*map).buckets + cast(**HashMapEntry, bucket_index)); + + let current = bucket; + while current != cast(*HashMapEntry, null) { + if strcmp((*current).key, key) { + (*current).value = value; + return; + }; + current = (*current).next; + }; + + let new_entry = cast(*HashMapEntry, arena_alloc((*map).arena, sizeof(HashMapEntry))); + (*new_entry).key = key; + (*new_entry).value = value; + (*new_entry).next = bucket; + + (*((*map).buckets + cast(**HashMapEntry, bucket_index))) = new_entry; + + return; +}; + +let hashmap_get = (map: *HashMap, key: *i8) => *void { + let bucket_index = simple_hash(key, (*map).bucket_count); + let current = *((*map).buckets + cast(**HashMapEntry, bucket_index)); + + while current != cast(*HashMapEntry, null) { + if strcmp((*current).key, key) { + return (*current).value; + }; + current = (*current).next; + }; + + return cast(*void, null); +}; |