| ... | ... | @@ -629,6 +629,13 @@ pub fn HashMap( |
| 629 | 629 | return self.unmanaged.removeAdapted(key, ctx); |
| 630 | 630 | } |
| 631 | 631 | |
| 632 | /// Delete the entry with key pointed to by keyPtr from the hash map. |
| 633 | /// keyPtr is assumed to be a valid pointer to a key that is present |
| 634 | /// in the hash map. |
| 635 | pub fn removeByPtr(self: *Self, keyPtr: *K) void { |
| 636 | self.unmanaged.removeByPtr(keyPtr); |
| 637 | } |
| 638 | |
| 632 | 639 | /// Creates a copy of this map, using the same allocator |
| 633 | 640 | pub fn clone(self: Self) !Self { |
| 634 | 641 | var other = try self.unmanaged.cloneContext(self.allocator, self.ctx); |
| ... | ... | @@ -1377,6 +1384,14 @@ pub fn HashMapUnmanaged( |
| 1377 | 1384 | return self.getIndex(key, ctx) != null; |
| 1378 | 1385 | } |
| 1379 | 1386 | |
| 1387 | fn removeByIndex(self: *Self, idx: usize) void { |
| 1388 | self.metadata.?[idx].remove(); |
| 1389 | self.keys()[idx] = undefined; |
| 1390 | self.values()[idx] = undefined; |
| 1391 | self.size -= 1; |
| 1392 | self.available += 1; |
| 1393 | } |
| 1394 | |
| 1380 | 1395 | /// If there is an `Entry` with a matching key, it is deleted from |
| 1381 | 1396 | /// the hash map, and this function returns true. Otherwise this |
| 1382 | 1397 | /// function returns false. |
| ... | ... | @@ -1390,17 +1405,29 @@ pub fn HashMapUnmanaged( |
| 1390 | 1405 | } |
| 1391 | 1406 | pub fn removeAdapted(self: *Self, key: anytype, ctx: anytype) bool { |
| 1392 | 1407 | if (self.getIndex(key, ctx)) |idx| { |
| 1393 | | self.metadata.?[idx].remove(); |
| 1394 | | self.keys()[idx] = undefined; |
| 1395 | | self.values()[idx] = undefined; |
| 1396 | | self.size -= 1; |
| 1397 | | self.available += 1; |
| 1408 | self.removeByIndex(idx); |
| 1398 | 1409 | return true; |
| 1399 | 1410 | } |
| 1400 | 1411 | |
| 1401 | 1412 | return false; |
| 1402 | 1413 | } |
| 1403 | 1414 | |
| 1415 | /// Delete the entry with key pointed to by keyPtr from the hash map. |
| 1416 | /// keyPtr is assumed to be a valid pointer to a key that is present |
| 1417 | /// in the hash map. |
| 1418 | pub fn removeByPtr(self: *Self, keyPtr: *K) void { |
| 1419 | // TODO: replace with pointer subtraction once supported by zig |
| 1420 | // if @sizeOf(K) == 0 then there is at most one item in the hash |
| 1421 | // map, which is assumed to exist as keyPtr must be valid. This |
| 1422 | // item must be at index 0. |
| 1423 | const idx = if (@sizeOf(K) > 0) |
| 1424 | (@ptrToInt(keyPtr) - @ptrToInt(self.keys())) / @sizeOf(K) |
| 1425 | else |
| 1426 | 0; |
| 1427 | |
| 1428 | self.removeByIndex(idx); |
| 1429 | } |
| 1430 | |
| 1404 | 1431 | fn initMetadatas(self: *Self) void { |
| 1405 | 1432 | @memset(@ptrCast([*]u8, self.metadata.?), 0, @sizeOf(Metadata) * self.capacity()); |
| 1406 | 1433 | } |
| ... | ... | @@ -2082,3 +2109,47 @@ test "std.hash_map ensureUnusedCapacity" { |
| 2082 | 2109 | // should not change the capacity. |
| 2083 | 2110 | try testing.expectEqual(capacity, map.capacity()); |
| 2084 | 2111 | } |
| 2112 | |
| 2113 | test "std.hash_map removeByPtr" { |
| 2114 | var map = AutoHashMap(i32, u64).init(testing.allocator); |
| 2115 | defer map.deinit(); |
| 2116 | |
| 2117 | var i: i32 = undefined; |
| 2118 | |
| 2119 | i = 0; |
| 2120 | while (i < 10) : (i += 1) { |
| 2121 | try map.put(i, 0); |
| 2122 | } |
| 2123 | |
| 2124 | try testing.expect(map.count() == 10); |
| 2125 | |
| 2126 | i = 0; |
| 2127 | while (i < 10) : (i += 1) { |
| 2128 | const keyPtr = map.getKeyPtr(i); |
| 2129 | try testing.expect(keyPtr != null); |
| 2130 | |
| 2131 | if (keyPtr) |ptr| { |
| 2132 | map.removeByPtr(ptr); |
| 2133 | } |
| 2134 | } |
| 2135 | |
| 2136 | try testing.expect(map.count() == 0); |
| 2137 | } |
| 2138 | |
| 2139 | test "std.hash_map removeByPtr 0 sized key" { |
| 2140 | var map = AutoHashMap(u0, u64).init(testing.allocator); |
| 2141 | defer map.deinit(); |
| 2142 | |
| 2143 | try map.put(0, 0); |
| 2144 | |
| 2145 | try testing.expect(map.count() == 1); |
| 2146 | |
| 2147 | const keyPtr = map.getKeyPtr(0); |
| 2148 | try testing.expect(keyPtr != null); |
| 2149 | |
| 2150 | if (keyPtr) |ptr| { |
| 2151 | map.removeByPtr(ptr); |
| 2152 | } |
| 2153 | |
| 2154 | try testing.expect(map.count() == 0); |
| 2155 | } |