authorgravatar for 94326797+riverbl@users.noreply.github.comriverbl <94326797+riverbl@users.noreply.github.com> 2021-11-15 12:54:14+00:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-01-24 20:29:05+02:00
loga0732117d07f9dc9b8afb457d935ca84411ec233
tree87686b97e90207d48d3485d10bfef813700a5739
parent15ef251a153de7f4985c1a87bf7706dde0e27306

HashMap: add removeByPtr


1 files changed, 76 insertions(+), 5 deletions(-)

lib/std/hash_map.zig+76-5
...@@ -629,6 +629,13 @@ pub fn HashMap(...@@ -629,6 +629,13 @@ pub fn HashMap(
629 return self.unmanaged.removeAdapted(key, ctx);629 return self.unmanaged.removeAdapted(key, ctx);
630 }630 }
631631
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 /// Creates a copy of this map, using the same allocator639 /// Creates a copy of this map, using the same allocator
633 pub fn clone(self: Self) !Self {640 pub fn clone(self: Self) !Self {
634 var other = try self.unmanaged.cloneContext(self.allocator, self.ctx);641 var other = try self.unmanaged.cloneContext(self.allocator, self.ctx);
...@@ -1377,6 +1384,14 @@ pub fn HashMapUnmanaged(...@@ -1377,6 +1384,14 @@ pub fn HashMapUnmanaged(
1377 return self.getIndex(key, ctx) != null;1384 return self.getIndex(key, ctx) != null;
1378 }1385 }
13791386
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 /// If there is an `Entry` with a matching key, it is deleted from1395 /// If there is an `Entry` with a matching key, it is deleted from
1381 /// the hash map, and this function returns true. Otherwise this1396 /// the hash map, and this function returns true. Otherwise this
1382 /// function returns false.1397 /// function returns false.
...@@ -1390,17 +1405,29 @@ pub fn HashMapUnmanaged(...@@ -1390,17 +1405,29 @@ pub fn HashMapUnmanaged(
1390 }1405 }
1391 pub fn removeAdapted(self: *Self, key: anytype, ctx: anytype) bool {1406 pub fn removeAdapted(self: *Self, key: anytype, ctx: anytype) bool {
1392 if (self.getIndex(key, ctx)) |idx| {1407 if (self.getIndex(key, ctx)) |idx| {
1393 self.metadata.?[idx].remove();1408 self.removeByIndex(idx);
1394 self.keys()[idx] = undefined;
1395 self.values()[idx] = undefined;
1396 self.size -= 1;
1397 self.available += 1;
1398 return true;1409 return true;
1399 }1410 }
14001411
1401 return false;1412 return false;
1402 }1413 }
14031414
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 fn initMetadatas(self: *Self) void {1431 fn initMetadatas(self: *Self) void {
1405 @memset(@ptrCast([*]u8, self.metadata.?), 0, @sizeOf(Metadata) * self.capacity());1432 @memset(@ptrCast([*]u8, self.metadata.?), 0, @sizeOf(Metadata) * self.capacity());
1406 }1433 }
...@@ -2082,3 +2109,47 @@ test "std.hash_map ensureUnusedCapacity" {...@@ -2082,3 +2109,47 @@ test "std.hash_map ensureUnusedCapacity" {
2082 // should not change the capacity.2109 // should not change the capacity.
2083 try testing.expectEqual(capacity, map.capacity());2110 try testing.expectEqual(capacity, map.capacity());
2084}2111}
2112
2113test "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
2139test "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}