authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-02-11 11:31:51-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-02-11 17:24:59-08:00
logc2a3d8cbb935ae68a5bd95d45c65b0f7f32974b0
treefc2091fd8f9e17213275cd72937fe28f5cbc831b
parentb2b830e0e90fc7c26205acb3624c16bce63caab5

std.ArrayHashMap: introduce setKey

Only available in the "unmanaged" variant since the other one is deprecated.

1 files changed, 43 insertions(+), 10 deletions(-)

lib/std/array_hash_map.zig+43-10
......@@ -1335,16 +1335,33 @@ pub fn ArrayHashMapUnmanaged(
13351335 hash.* = h;
13361336 }
13371337 }
1338 // Rebuild the index.
1339 if (self.entries.capacity > linear_scan_max) {
1340 // We're going to rebuild the index header and replace the existing one (if any). The
1341 // indexes should sized such that they will be at most 60% full.
1342 const bit_index = try IndexHeader.findBitIndex(self.entries.capacity);
1343 const new_header = try IndexHeader.alloc(gpa, bit_index);
1344 if (self.index_header) |header| header.free(gpa);
1345 self.insertAllEntriesIntoNewHeader(if (store_hash) {} else ctx, new_header);
1346 self.index_header = new_header;
1347 }
1338 try rebuildIndex(self, gpa, ctx);
1339 }
1340
1341 /// Modify an entry's key without reordering any entries.
1342 pub fn setKey(self: *Self, gpa: Allocator, index: usize, new_key: K) Oom!void {
1343 if (@sizeOf(ByIndexContext) != 0)
1344 @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call setKeyContext instead.");
1345 return setKeyContext(self, gpa, index, new_key, undefined);
1346 }
1347
1348 pub fn setKeyContext(self: *Self, gpa: Allocator, index: usize, new_key: K, ctx: Context) Oom!void {
1349 const key_ptr = &self.entries.items(.key)[index];
1350 key_ptr.* = new_key;
1351 if (store_hash) self.entries.items(.hash)[index].* = checkedHash(ctx, key_ptr.*);
1352 try rebuildIndex(self, gpa, undefined);
1353 }
1354
1355 fn rebuildIndex(self: *Self, gpa: Allocator, ctx: Context) Oom!void {
1356 if (self.entries.capacity <= linear_scan_max) return;
1357
1358 // We're going to rebuild the index header and replace the existing one (if any). The
1359 // indexes should sized such that they will be at most 60% full.
1360 const bit_index = try IndexHeader.findBitIndex(self.entries.capacity);
1361 const new_header = try IndexHeader.alloc(gpa, bit_index);
1362 if (self.index_header) |header| header.free(gpa);
1363 self.insertAllEntriesIntoNewHeader(if (store_hash) {} else ctx, new_header);
1364 self.index_header = new_header;
13481365 }
13491366
13501367 /// Sorts the entries and then rebuilds the index.
......@@ -2530,6 +2547,22 @@ test "0 sized key and 0 sized value" {
25302547 try testing.expectEqual(map.get(0), null);
25312548}
25322549
2550test "setKey" {
2551 const gpa = std.testing.allocator;
2552
2553 var map: AutoArrayHashMapUnmanaged(i32, i32) = .empty;
2554 defer map.deinit(gpa);
2555
2556 try map.put(gpa, 12, 34);
2557 try map.put(gpa, 56, 78);
2558
2559 try map.setKey(gpa, 0, 42);
2560 try testing.expectEqual(2, map.count());
2561 try testing.expectEqual(false, map.contains(12));
2562 try testing.expectEqual(34, map.get(42));
2563 try testing.expectEqual(78, map.get(56));
2564}
2565
25332566pub fn getHashPtrAddrFn(comptime K: type, comptime Context: type) (fn (Context, K) u32) {
25342567 return struct {
25352568 fn hash(ctx: Context, key: K) u32 {