ona/src/table.zig

111 lines
2.7 KiB
Zig
Raw Normal View History

2022-10-14 01:13:26 +01:00
const std = @import("std");
pub fn Dynamic(comptime Key: type, comptime Value: type, comptime key_context: KeyContext(Key)) type {
return struct {
2022-10-14 17:10:27 +01:00
load_maximum: f32,
2022-10-14 01:13:26 +01:00
buckets_used: usize,
2022-10-14 17:10:27 +01:00
buckets: []Bucket,
2022-10-14 01:13:26 +01:00
///
///
///
const Bucket = struct {
2022-10-14 17:10:27 +01:00
maybe_entry: ?struct {
key: Key,
value: Value,
},
2022-10-14 01:13:26 +01:00
2022-10-14 17:10:27 +01:00
maybe_next_index: ?usize,
2022-10-14 01:13:26 +01:00
};
///
///
///
const Self = @This();
///
///
///
2022-10-14 17:10:27 +01:00
pub fn delete(self: Self, key: Key) bool {
2022-10-14 01:13:26 +01:00
_ = key;
_ = self;
}
///
///
///
2022-10-14 17:10:27 +01:00
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.
///
2022-10-14 01:13:26 +01:00
pub fn lookup(self: Self, key: Key) ?*Value {
2022-10-14 17:10:27 +01:00
var bucket = &(self.buckets[@mod(key_context.hash(key), self.buckets.len)]);
if (bucket.maybe_entry) |*entry|
if (key_context.equals(entry.key, key)) return &entry.value;
2022-10-14 01:13:26 +01:00
2022-10-14 17:10:27 +01:00
while (bucket.maybe_next_index) |index| {
bucket = &(self.buckets[index]);
2022-10-14 01:13:26 +01:00
2022-10-14 17:10:27 +01:00
if (bucket.maybe_entry) |*entry|
if (key_context.equals(entry.key, key)) return &entry.value;
2022-10-14 01:13:26 +01:00
}
return null;
}
};
}
2022-10-14 17:10:27 +01:00
///
///
///
pub const InsertError = std.mem.Allocator || error {
KeyExists,
};
2022-10-14 01:13:26 +01:00
pub fn KeyContext(comptime Key: type) type {
return struct {
hash: fn (Key) usize,
equals: fn (Key, Key) bool,
};
}
fn equalsString(this_string: []const u8, that_string: []const u8) bool {
return std.mem.eql(u8, this_string, that_string);
}
fn hashString(string: []const u8) usize {
var hash = @as(usize, 5381);
for (string) |byte| hash = ((hash << 5) + hash) + byte;
return hash;
}
pub const string_context = KeyContext([]const u8){
.hash = hashString,
.equals = equalsString,
};