import "./option.zc" import "./hash.zc" import "./mem.zc" struct Set { data: T*; occupied: bool*; deleted: bool*; len: usize; cap: usize; } impl Set { /// Creates a new, empty Set. fn new() -> Set { return Set { data: 0, occupied: 0, deleted: 0, len: 0, cap: 0 }; } fn _resize(self, new_cap: usize) { let old_data = self.data; let old_occupied = self.occupied; let old_deleted = self.deleted; let old_cap = self.cap; self.cap = new_cap; self.data = alloc_n(new_cap); self.occupied = alloc_n(new_cap); self.deleted = alloc_n(new_cap); memset(self.data, 0, new_cap * sizeof(T)); memset(self.occupied, 0, new_cap * sizeof(bool)); memset(self.deleted, 0, new_cap * sizeof(bool)); self.len = 0; for (let i: usize = 0; i < old_cap; i = i + 1) { if (old_occupied[i] && !old_deleted[i]) { self.add(old_data[i]); } } if (old_data != NULL) { dealloc(old_data); } if (old_occupied != NULL) { dealloc(old_occupied); } if (old_deleted != NULL) { dealloc(old_deleted); } } /// Inserts a value; returns whether it was new. fn add(self, val: T) -> bool { if (self.contains(val)) { return false; } if (self.len >= self.cap * 0.75) { let new_cap = self.cap * 2; if (new_cap < 8) new_cap = 8; self._resize(new_cap); } let hash = hash_compute(&val, sizeof(T)); let idx = hash % self.cap; while (self.occupied[idx] && !self.deleted[idx]) { idx = (idx + 1) % self.cap; } self.data[idx] = val; self.occupied[idx] = true; self.deleted[idx] = false; self.len = self.len + 1; return true; } /// Returns whether the value is present. fn contains(self, val: T) -> bool { if (self.cap == 0) { return false; } let hash = hash_compute(&val, sizeof(T)); let idx = hash % self.cap; let start_idx = idx; while (self.occupied[idx]) { if (!self.deleted[idx] && self.data[idx] == val) { return true; } idx = (idx + 1) % self.cap; if (idx == start_idx) { return false; } } return false; } /// Removes a value; returns whether it was present. fn remove(self, val: T) -> bool { if (self.cap == 0) return false; let hash = hash_compute(&val, sizeof(T)); let idx = hash % self.cap; let start_idx = idx; while (self.occupied[idx]) { if (!self.deleted[idx] && self.data[idx] == val) { self.deleted[idx] = true; self.len = self.len - 1; return true; } idx = (idx + 1) % self.cap; if (idx == start_idx) return false; } return false; } /// Returns the number of items. fn length(self) -> usize { return self.len; } /// Returns whether the set is empty. fn is_empty(self) -> bool { return self.len == 0; } /// Frees the backing storage. fn free(self) { if (self.data) { dealloc(self.data); dealloc(self.occupied); dealloc(self.deleted); } self.data = 0; self.occupied = 0; self.deleted = 0; self.len = 0; self.cap = 0; } fn capacity(self) -> usize { return self.cap; } fn is_slot_occupied(self, idx: usize) -> bool { if (idx >= self.cap) return false; return self.occupied[idx] && !self.deleted[idx]; } fn val_at(self, idx: usize) -> Option { if (idx >= self.cap || !self.occupied[idx] || self.deleted[idx]) { return Option::None(); } return Option::Some(self.data[idx]); } /// Removes all items. fn clear(self) { for (let i: usize = 0; i < self.cap; i = i + 1) { self.occupied[i] = false; self.deleted[i] = false; } self.len = 0; } } impl Drop for Set { fn drop(self) { self.free(); } }