mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-09 15:19:07 +00:00
std: fix HashMap.putAssumeCapacity
This commit is contained in:
parent
06a3a69e6f
commit
f70160f89c
1 changed files with 35 additions and 34 deletions
|
|
@ -468,41 +468,12 @@ pub fn HashMapUnmanaged(
|
||||||
self.putAssumeCapacityNoClobber(key, value);
|
self.putAssumeCapacityNoClobber(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Asserts there is enough capacity to store the new key-value pair.
|
||||||
|
/// Clobbers any existing data. To detect if a put would clobber
|
||||||
|
/// existing data, see `getOrPutAssumeCapacity`.
|
||||||
pub fn putAssumeCapacity(self: *Self, key: K, value: V) void {
|
pub fn putAssumeCapacity(self: *Self, key: K, value: V) void {
|
||||||
const hash = hashFn(key);
|
const gop = self.getOrPutAssumeCapacity(key);
|
||||||
const mask = self.capacity() - 1;
|
gop.entry.value = value;
|
||||||
const fingerprint = Metadata.takeFingerprint(hash);
|
|
||||||
var idx = @truncate(usize, hash & mask);
|
|
||||||
|
|
||||||
var first_tombstone_idx: usize = self.capacity(); // invalid index
|
|
||||||
var metadata = self.metadata.? + idx;
|
|
||||||
while (metadata[0].isUsed() or metadata[0].isTombstone()) {
|
|
||||||
if (metadata[0].isUsed() and metadata[0].fingerprint == fingerprint) {
|
|
||||||
const entry = &self.entries()[idx];
|
|
||||||
if (eqlFn(entry.key, key)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (first_tombstone_idx == self.capacity() and metadata[0].isTombstone()) {
|
|
||||||
first_tombstone_idx = idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
idx = (idx + 1) & mask;
|
|
||||||
metadata = self.metadata.? + idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (first_tombstone_idx < self.capacity()) {
|
|
||||||
// Cheap try to lower probing lengths after deletions. Recycle a tombstone.
|
|
||||||
idx = first_tombstone_idx;
|
|
||||||
metadata = self.metadata.? + idx;
|
|
||||||
} else {
|
|
||||||
// We're using a slot previously free.
|
|
||||||
self.available -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
metadata[0].fill(fingerprint);
|
|
||||||
const entry = &self.entries()[idx];
|
|
||||||
entry.* = .{ .key = key, .value = undefined };
|
|
||||||
self.size += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Insert an entry in the map. Assumes it is not already present,
|
/// Insert an entry in the map. Assumes it is not already present,
|
||||||
|
|
@ -1148,6 +1119,36 @@ test "std.hash_map put" {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "std.hash_map putAssumeCapacity" {
|
||||||
|
var map = AutoHashMap(u32, u32).init(std.testing.allocator);
|
||||||
|
defer map.deinit();
|
||||||
|
|
||||||
|
try map.ensureCapacity(20);
|
||||||
|
var i: u32 = 0;
|
||||||
|
while (i < 20) : (i += 1) {
|
||||||
|
map.putAssumeCapacityNoClobber(i, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
var sum = i;
|
||||||
|
while (i < 20) : (i += 1) {
|
||||||
|
sum += map.get(i).?;
|
||||||
|
}
|
||||||
|
expectEqual(sum, 190);
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while (i < 20) : (i += 1) {
|
||||||
|
map.putAssumeCapacity(i, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
sum = i;
|
||||||
|
while (i < 20) : (i += 1) {
|
||||||
|
sum += map.get(i).?;
|
||||||
|
}
|
||||||
|
expectEqual(sum, 20);
|
||||||
|
}
|
||||||
|
|
||||||
test "std.hash_map getOrPut" {
|
test "std.hash_map getOrPut" {
|
||||||
var map = AutoHashMap(u32, u32).init(std.testing.allocator);
|
var map = AutoHashMap(u32, u32).init(std.testing.allocator);
|
||||||
defer map.deinit();
|
defer map.deinit();
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue