summaryrefslogtreecommitdiff
path: root/objreg.ha
blob: 2630328c2f2d6a6e3d8733777a1a43215c5d5bca (plain)
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
use hash::fnv;
use htab;

type ObjectRegistry = struct {
	table: htab::table, // *Object
};

type Object = struct {
	name: str,
};

def OBJREG_EMPTY = ObjectRegistry {
	table = HTAB_EMPTY,
};

fn newobjreg() ObjectRegistry =
	ObjectRegistry {
		table = htab::new(0, size(*Object)),
	};

fn objreg_eqfunc(ctx: *opaque, entry: *opaque) bool =
	return *(ctx: *str) == (entry: **Object).name;

fn objreg_find(reg: *ObjectRegistry, name: str) nullable *opaque = {
	const hash = fnv::string64(name);
	match (htab::get(&reg.table, hash,
		&objreg_eqfunc, &name, size(*Object))) {
	case let entry: *opaque =>
		return *(entry: **Object);
	case null =>
		return null;
	};
};

fn objreg_register(reg: *ObjectRegistry, obj: *Object) void = {
	assert(objreg_find(reg, obj.name) == null, "already registered");
	const hash = fnv::string64(obj.name);
	const entry = htab::add(&reg.table, hash, size(*Object));
	*(entry: **Object) = obj;
};

fn objreg_count(reg: *ObjectRegistry) size =
	htab::count(&reg.table);

fn objreg_clear(reg: *ObjectRegistry) void =
	htab::clear(&reg.table, size(*Object));

type ObjectRegistryIterator = struct {
	inner: htab::iterator,
};

fn objreg_iter(reg: *ObjectRegistry) ObjectRegistryIterator =
	ObjectRegistryIterator {
		inner = htab::iter(&reg.table),
	};

fn objreg_next(it: *ObjectRegistryIterator) nullable *Object = {
	match (htab::next(&it.inner, size(*Object))) {
	case let entry: *opaque =>
		return *(entry: **Object);
	case null =>
		return null;
	};
};