authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-08-04 00:29:39+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-08-04 09:47:42+02:00
logee6f7fee2900ea18bfd056e57952aba606158d7b
tree5360b0d6127090290171fe8711e675da31d4c99a
parentaad4598367b136a06e3569373be7da8febea7f31

libstd: add ArrayHashMap.popOrNull function

which internally calls `ArrayHashMap.pop`, however, returns `?KV` instead and performs the bounds checking automatically. This function correponds to `ArrayList.popOrNull` and is meant to fill the gap for situations where we want the quick lookup offered by the hash map with elegant ability to iterate and pop of the container with automatic bound checking that plugs in well with a `while`-loop such as ```zig var map = std.ArrayHashMap(K, V).init(allocator); map.deinit(); while (map.popOrNull()) |entry| { // ... do something } assert(map.count() == 0); ```

1 files changed, 37 insertions(+), 0 deletions(-)

lib/std/array_hash_map.zig+37
...@@ -414,6 +414,12 @@ pub fn ArrayHashMap(...@@ -414,6 +414,12 @@ pub fn ArrayHashMap(
414 pub fn pop(self: *Self) KV {414 pub fn pop(self: *Self) KV {
415 return self.unmanaged.popContext(self.ctx);415 return self.unmanaged.popContext(self.ctx);
416 }416 }
417
418 /// Removes the last inserted `Entry` in the hash map and returns it if count is nonzero.
419 /// Otherwise returns null.
420 pub fn popOrNull(self: *Self) ?KV {
421 return self.unmanaged.popOrNullContext(self.ctx);
422 }
417 };423 };
418}424}
419425
...@@ -1181,6 +1187,17 @@ pub fn ArrayHashMapUnmanaged(...@@ -1181,6 +1187,17 @@ pub fn ArrayHashMapUnmanaged(
1181 };1187 };
1182 }1188 }
11831189
1190 /// Removes the last inserted `Entry` in the hash map and returns it if count is nonzero.
1191 /// Otherwise returns null.
1192 pub fn popOrNull(self: *Self) ?KV {
1193 if (@sizeOf(ByIndexContext) != 0)
1194 @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call popContext instead.");
1195 return self.popOrNullContext(undefined);
1196 }
1197 pub fn popOrNullContext(self: *Self, ctx: Context) ?KV {
1198 return if (self.entries.len == 0) null else self.popContext(ctx);
1199 }
1200
1184 // ------------------ No pub fns below this point ------------------1201 // ------------------ No pub fns below this point ------------------
11851202
1186 fn fetchRemoveByKey(self: *Self, key: anytype, key_ctx: anytype, ctx: ByIndexContext, comptime removal_type: RemovalType) ?KV {1203 fn fetchRemoveByKey(self: *Self, key: anytype, key_ctx: anytype, ctx: ByIndexContext, comptime removal_type: RemovalType) ?KV {
...@@ -2094,6 +2111,26 @@ test "pop" {...@@ -2094,6 +2111,26 @@ test "pop" {
2094 }2111 }
2095}2112}
20962113
2114test "popOrNull" {
2115 var map = AutoArrayHashMap(i32, i32).init(std.testing.allocator);
2116 defer map.deinit();
2117
2118 // Insert just enough entries so that the map expands. Afterwards,
2119 // pop all entries out of the map.
2120
2121 var i: i32 = 0;
2122 while (i < 9) : (i += 1) {
2123 try testing.expect((try map.fetchPut(i, i)) == null);
2124 }
2125
2126 while (map.popOrNull()) |pop| {
2127 try testing.expect(pop.key == i - 1 and pop.value == i - 1);
2128 i -= 1;
2129 }
2130
2131 try testing.expect(map.count() == 0);
2132}
2133
2097test "reIndex" {2134test "reIndex" {
2098 var map = ArrayHashMap(i32, i32, AutoContext(i32), true).init(std.testing.allocator);2135 var map = ArrayHashMap(i32, i32, AutoContext(i32), true).init(std.testing.allocator);
2099 defer map.deinit();2136 defer map.deinit();