# hashmap.ha -rw-r--r-- 1.4 KiB View raw
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
// Hash map which maps string -> int
use fmt;
use hash::fnv;

def BUCKETS: size = 64;

type hashmap = [BUCKETS][](str, int);

fn getitem(map: *hashmap, key: str) (int | void) = {
	let bucket = &map[fnv::string(key) % len(map)];
	for (let i = 0z; i < len(bucket); i += 1) {
		if (bucket[i].0 == key) {
			return bucket[i].1;
		};
	};
};

fn setitem(map: *hashmap, key: str, value: int) void = {
	let bucket = &map[fnv::string(key) % len(map)];
	for (let i = 0z; i < len(bucket); i += 1) {
		if (bucket[i].0 == key) {
			bucket[i].1 = value;
			return;
		};
	};
	append(bucket, (key, value));
};

fn delitem(map: *hashmap, key: str) (int | void) = {
	let bucket = &map[fnv::string(key) % len(map)];
	for (let i = 0z; i < len(bucket); i += 1) {
		if (bucket[i].0 == key) {
			let item = bucket[i];
			delete(bucket[i]);
			return item.1;
		};
	};
};

fn finish(map: *hashmap) void = {
	for (let i = 0z; i < len(map); i += 1) {
		free(map[i]);
	};
};

export fn main() void = {
	let map: hashmap = [[]...];
	defer finish(&map);

	setitem(&map, "hello", 1234);
	setitem(&map, "world!", 4321);

	assert(getitem(&map, "hello") as int == 1234);
	assert(getitem(&map, "world!") as int == 4321);
	assert(getitem(&map, "hi there") is void);

	assert(delitem(&map, "hello") as int == 1234);

	// Enumerate keys/values
	for (let i = 0z; i < len(map); i += 1) {
		for (let j = 0z; j < len(map[i]); j += 1) {
			let item = &map[i][j];
			fmt::printfln("{}: {}", item.0, item.1)!;
		};
	};
};