module Std::Set { extern func bux_hash_bytes(ptr: *void, size: uint) -> uint; extern func bux_mem_eq(a: *void, b: *void, size: uint) -> int; extern func bux_alloc(size: uint) -> *void; extern func bux_free(ptr: *void); struct SetEntry { value: T, occupied: bool, } struct Set { entries: *SetEntry, cap: uint, len: uint, } func Set_New(cap: uint) -> Set { let total: uint = cap * sizeof(SetEntry); let data: *SetEntry = bux_alloc(total) as *SetEntry; var i: uint = 0; while i < cap { data[i].occupied = false; i = i + 1; } return Set { entries: data, cap: cap, len: 0 }; } func Set_Add(s: *Set, value: T) { var valuePtr: *T = &value; let hash: uint = bux_hash_bytes(valuePtr as *void, sizeof(T)); var idx: uint = hash % s.cap; while s.entries[idx].occupied { var entryPtr: *T = &s.entries[idx].value; if bux_mem_eq(entryPtr as *void, valuePtr as *void, sizeof(T)) != 0 { return; } idx = (idx + 1) % s.cap; } s.entries[idx].value = value; s.entries[idx].occupied = true; s.len = s.len + 1; } func Set_Has(s: *Set, value: T) -> bool { var valuePtr: *T = &value; let hash: uint = bux_hash_bytes(valuePtr as *void, sizeof(T)); var idx: uint = hash % s.cap; while s.entries[idx].occupied { var entryPtr: *T = &s.entries[idx].value; if bux_mem_eq(entryPtr as *void, valuePtr as *void, sizeof(T)) != 0 { return true; } idx = (idx + 1) % s.cap; } return false; } func Set_Len(s: *Set) -> uint { return s.len; } func Set_Free(s: *Set) { bux_free(s.entries as *void); s.entries = null as *SetEntry; s.cap = 0; s.len = 0; } func Set_Drop(s: *Set) { Set_Free(s); } }