| ... | ... | @@ -1335,16 +1335,33 @@ pub fn ArrayHashMapUnmanaged( |
| 1335 | 1335 | hash.* = h; |
| 1336 | 1336 | } |
| 1337 | 1337 | } |
| 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; |
| 1348 | 1365 | } |
| 1349 | 1366 | |
| 1350 | 1367 | /// Sorts the entries and then rebuilds the index. |
| ... | ... | @@ -2530,6 +2547,22 @@ test "0 sized key and 0 sized value" { |
| 2530 | 2547 | try testing.expectEqual(map.get(0), null); |
| 2531 | 2548 | } |
| 2532 | 2549 | |
| 2550 | test "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 | |
| 2533 | 2566 | pub fn getHashPtrAddrFn(comptime K: type, comptime Context: type) (fn (Context, K) u32) { |
| 2534 | 2567 | return struct { |
| 2535 | 2568 | fn hash(ctx: Context, key: K) u32 { |