diff --git a/src/table.zig b/src/table.zig index cec8dba..81d7f03 100644 --- a/src/table.zig +++ b/src/table.zig @@ -2,23 +2,20 @@ const std = @import("std"); pub fn Dynamic(comptime Key: type, comptime Value: type, comptime key_context: KeyContext(Key)) type { return struct { + load_maximum: f32, buckets_used: usize, - bucket_map: []?Bucket, + buckets: []Bucket, /// /// /// const Bucket = struct { - key: Key, - value: Value, - next: ?usize, - }; - - /// - /// - /// - pub const InsertError = error { + maybe_entry: ?struct { + key: Key, + value: Value, + }, + maybe_next_index: ?usize, }; /// @@ -29,8 +26,7 @@ pub fn Dynamic(comptime Key: type, comptime Value: type, comptime key_context: K /// /// /// - pub fn insert(self: Self, key: Key, value: Value) InsertError!void { - _ = value; + pub fn delete(self: Self, key: Key) bool { _ = key; _ = self; } @@ -38,14 +34,43 @@ pub fn Dynamic(comptime Key: type, comptime Value: type, comptime key_context: K /// /// /// + pub fn insert(self: Self, key: Key, value: Value) InsertError!void { + if ((@intToFloat(f32, self.buckets_used) / @intToFloat( + f32, self.buckets.len)) >= self.load_maximum) try self.rehash(); + + var hash = @mod(key_context.hash(key), self.buckets.len); + + while (true) { + const bucket = &(self.buckets[hash]); + + const entry = &(bucket.maybe_entry orelse { + bucket.maybe_entry = .{ + .key = key, + .value = value + }; + }); + + if (key_context.equals(entry.key, key)) return error.KeyExists; + + hash = @mod(hashHash(hash), self.buckets.len); + } + } + + /// + /// Searches for a value indexed with `key` in `self`, returning it or `null` if no matching + /// entry was found. + /// pub fn lookup(self: Self, key: Key) ?*Value { - var bucket = &(self.bucket_map[@mod(key_context.hash( - key), self.bucket_map.len)] orelse return null); + var bucket = &(self.buckets[@mod(key_context.hash(key), self.buckets.len)]); - while (bucket) { - if (key_context.equals(bucket.key, key)) return &bucket.value; + if (bucket.maybe_entry) |*entry| + if (key_context.equals(entry.key, key)) return &entry.value; - bucket = bucket.next; + while (bucket.maybe_next_index) |index| { + bucket = &(self.buckets[index]); + + if (bucket.maybe_entry) |*entry| + if (key_context.equals(entry.key, key)) return &entry.value; } return null; @@ -53,6 +78,13 @@ pub fn Dynamic(comptime Key: type, comptime Value: type, comptime key_context: K }; } +/// +/// +/// +pub const InsertError = std.mem.Allocator || error { + KeyExists, +}; + pub fn KeyContext(comptime Key: type) type { return struct { hash: fn (Key) usize,