diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2021-08-04 00:29:39 +0200 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2021-08-04 09:47:42 +0200 |
| commit | ee6f7fee2900ea18bfd056e57952aba606158d7b (patch) | |
| tree | 5360b0d6127090290171fe8711e675da31d4c99a /lib/std/array_hash_map.zig | |
| parent | aad4598367b136a06e3569373be7da8febea7f31 (diff) | |
| download | zig-ee6f7fee2900ea18bfd056e57952aba606158d7b.tar.gz zig-ee6f7fee2900ea18bfd056e57952aba606158d7b.zip | |
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);
```
Diffstat (limited to 'lib/std/array_hash_map.zig')
| -rw-r--r-- | lib/std/array_hash_map.zig | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/lib/std/array_hash_map.zig b/lib/std/array_hash_map.zig index 9bcecab47e..4ca603d2e8 100644 --- a/lib/std/array_hash_map.zig +++ b/lib/std/array_hash_map.zig @@ -414,6 +414,12 @@ pub fn ArrayHashMap( pub fn pop(self: *Self) KV { return self.unmanaged.popContext(self.ctx); } + + /// Removes the last inserted `Entry` in the hash map and returns it if count is nonzero. + /// Otherwise returns null. + pub fn popOrNull(self: *Self) ?KV { + return self.unmanaged.popOrNullContext(self.ctx); + } }; } @@ -1181,6 +1187,17 @@ pub fn ArrayHashMapUnmanaged( }; } + /// Removes the last inserted `Entry` in the hash map and returns it if count is nonzero. + /// Otherwise returns null. + pub fn popOrNull(self: *Self) ?KV { + if (@sizeOf(ByIndexContext) != 0) + @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call popContext instead."); + return self.popOrNullContext(undefined); + } + pub fn popOrNullContext(self: *Self, ctx: Context) ?KV { + return if (self.entries.len == 0) null else self.popContext(ctx); + } + // ------------------ No pub fns below this point ------------------ fn fetchRemoveByKey(self: *Self, key: anytype, key_ctx: anytype, ctx: ByIndexContext, comptime removal_type: RemovalType) ?KV { @@ -2094,6 +2111,26 @@ test "pop" { } } +test "popOrNull" { + var map = AutoArrayHashMap(i32, i32).init(std.testing.allocator); + defer map.deinit(); + + // Insert just enough entries so that the map expands. Afterwards, + // pop all entries out of the map. + + var i: i32 = 0; + while (i < 9) : (i += 1) { + try testing.expect((try map.fetchPut(i, i)) == null); + } + + while (map.popOrNull()) |pop| { + try testing.expect(pop.key == i - 1 and pop.value == i - 1); + i -= 1; + } + + try testing.expect(map.count() == 0); +} + test "reIndex" { var map = ArrayHashMap(i32, i32, AutoContext(i32), true).init(std.testing.allocator); defer map.deinit(); |
