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(
414414 pub fn pop(self: *Self) KV {
415415 return self.unmanaged.popContext(self.ctx);
416416 }
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 }
417423 };
418424}
419425
......@@ -1181,6 +1187,17 @@ pub fn ArrayHashMapUnmanaged(
11811187 };
11821188 }
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
11841201 // ------------------ No pub fns below this point ------------------
11851202
11861203 fn fetchRemoveByKey(self: *Self, key: anytype, key_ctx: anytype, ctx: ByIndexContext, comptime removal_type: RemovalType) ?KV {
......@@ -2094,6 +2111,26 @@ test "pop" {
20942111 }
20952112}
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
20972134test "reIndex" {
20982135 var map = ArrayHashMap(i32, i32, AutoContext(i32), true).init(std.testing.allocator);
20992136 defer map.deinit();