aboutsummaryrefslogtreecommitdiff
path: root/src/set.hff
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-13 10:38:27 +0200
committerlemon <lsof@mailbox.org>2022-08-13 10:38:27 +0200
commit7d4cb5bb96b061ed8708889b75e4d50757d9b3f2 (patch)
treeb57fdfa2dd7d61b888930d45c5f8f6f873db39ff /src/set.hff
parent62132ecc8d032ef251d6b54177414a9ba29e8610 (diff)
set template
Diffstat (limited to 'src/set.hff')
-rw-r--r--src/set.hff46
1 files changed, 46 insertions, 0 deletions
diff --git a/src/set.hff b/src/set.hff
new file mode 100644
index 0000000..acff95b
--- /dev/null
+++ b/src/set.hff
@@ -0,0 +1,46 @@
+import "vec.hff";
+import "all.hff";
+
+struct Set<T, Traits> {
+ buf Vec<T>,
+ set **const T,
+ N int,
+ count int,
+
+ fn intern(self *Set, x T) *const T {
+ if self.set == #null {
+ self.set = xcalloc(self.N = 16, sizeof *T);
+ }
+
+ if self.count == self.N / 2 {
+ free(self.set);
+ self.set = xcalloc(self.N *= 2, sizeof *T);
+ vec_each(p, i, self.buf,
+ let i = Traits:hash(p) & (self.N - 1);
+ for ;; {
+ if self.set[i] == #null {
+ self.set[i] = &self.buf.dat[i];
+ break;
+ }
+ i = (i + 1) & (self.N - 1);
+ }
+ )
+ }
+
+ let i0 = Traits:hash(x) & (self.N - 1);
+ let i int = i0;
+ do {
+ if self.set[i] == #null {
+ ++self.count;
+ self.buf->push(Traits:dup(x));
+ return self.set[i] = &self.buf.dat[self.buf.len - 1];
+ } else if Traits:eq(*self.set[i], x) {
+ fprintf(stderr, "found %s\n", x);
+ return self.set[i];
+ }
+ i = (i + 1) & (self.N - 1);
+ } while i != i0;
+ assert(#f, "unreachable");
+ }
+
+}