Improve memory safety of hash table

This commit is contained in:
kayomn 2022-10-15 21:08:52 +01:00
parent 2792f27473
commit 98372cc85f
1 changed files with 20 additions and 16 deletions

View File

@ -56,16 +56,18 @@ pub fn Hashed(comptime Key: type, comptime Value: type,
} }
/// ///
/// Searches for `key` to delete it, returning the deleted value or `null` if no matching /// Searches for `key` and deletes it from `self.
/// key was found.
/// ///
pub fn remove(self: Self, key: Key) ?Value { /// The removed value is returned or `null` if no key matching `key` was found.
///
pub fn remove(self: *Self, key: Key) ?Value {
var bucket = &(self.buckets[@mod(key_context.hash(key), self.buckets.len)]); var bucket = &(self.buckets[@mod(key_context.hash(key), self.buckets.len)]);
if (bucket.maybe_entry) |*entry| if (key_context.equals(entry.key, key)) { if (bucket.maybe_entry) |*entry| if (key_context.equals(entry.key, key)) {
defer entry.value = null; defer {
bucket.maybe_entry = null;
self.filled -= 1; self.filled -= 1;
}
return entry.value; return entry.value;
}; };
@ -74,9 +76,10 @@ pub fn Hashed(comptime Key: type, comptime Value: type,
bucket = &(self.buckets[index]); bucket = &(self.buckets[index]);
if (bucket.maybe_entry) |*entry| if (key_context.equals(entry.key, key)) { if (bucket.maybe_entry) |*entry| if (key_context.equals(entry.key, key)) {
defer entry.value = null; defer {
bucket.maybe_entry = null;
self.filled -= 1; self.filled -= 1;
}
return entry.value; return entry.value;
}; };
@ -129,20 +132,21 @@ pub fn Hashed(comptime Key: type, comptime Value: type,
} }
/// ///
/// Searches for a value indexed with `key` in `self`, returning it or `null` if no matching /// Searches for a value indexed with `key` in `self`.
/// entry was found.
/// ///
pub fn lookup(self: Self, key: Key) ?*Value { /// The found value is returned or `null` if an key matching `key` failed to be found.
///
pub fn lookup(self: Self, key: Key) ?Value {
var bucket = &(self.buckets[@mod(key_context.hash(key), self.buckets.len)]); var bucket = &(self.buckets[@mod(key_context.hash(key), self.buckets.len)]);
if (bucket.maybe_entry) |*entry| if (bucket.maybe_entry) |entry|
if (key_context.equals(entry.key, key)) return &entry.value; if (key_context.equals(entry.key, key)) return entry.value;
while (bucket.maybe_next_index) |index| { while (bucket.maybe_next_index) |index| {
bucket = &(self.buckets[index]); bucket = &(self.buckets[index]);
if (bucket.maybe_entry) |*entry| if (bucket.maybe_entry) |entry|
if (key_context.equals(entry.key, key)) return &entry.value; if (key_context.equals(entry.key, key)) return entry.value;
} }
return null; return null;