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(®.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(®.table, hash, size(*Object)); *(entry: **Object) = obj; }; fn objreg_count(reg: *ObjectRegistry) size = htab::count(®.table); fn objreg_clear(reg: *ObjectRegistry) void = htab::clear(®.table, size(*Object)); type ObjectRegistryIterator = struct { inner: htab::iterator, }; fn objreg_iter(reg: *ObjectRegistry) ObjectRegistryIterator = ObjectRegistryIterator { inner = htab::iter(®.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; }; };