authorgravatar for thejoshwolfe@gmail.comJosh Wolfe <thejoshwolfe@gmail.com> 2019-06-12 23:39:53-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-06-13 00:17:12-04:00
log80fa871f4a087478336692406aaa9ec99eb53754
tree9a3bfd8f76a4eb5f747379803278663982433bdc
parentfcc0728a35fe602ff8ad8c28370e901231550dea

Add HashMap apis that assert the common case

* putNoClobber() for put() * removeAssertDiscard() for remove()

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

std/hash_map.zig+18-5
...@@ -183,6 +183,11 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3...@@ -183,6 +183,11 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3
183 return putAssumeCapacity(self, key, value);183 return putAssumeCapacity(self, key, value);
184 }184 }
185185
186 /// Calls put() and asserts that no kv pair is clobbered.
187 pub fn putNoClobber(self: *Self, key: K, value: V) !void {
188 assert((try self.put(key, value)) == null);
189 }
190
186 pub fn putAssumeCapacity(self: *Self, key: K, value: V) ?KV {191 pub fn putAssumeCapacity(self: *Self, key: K, value: V) ?KV {
187 assert(self.count() < self.entries.len);192 assert(self.count() < self.entries.len);
188 self.incrementModificationCount();193 self.incrementModificationCount();
...@@ -203,6 +208,7 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3...@@ -203,6 +208,7 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3
203 return hm.get(key) != null;208 return hm.get(key) != null;
204 }209 }
205210
211 /// Returns any kv pair that was removed.
206 pub fn remove(hm: *Self, key: K) ?KV {212 pub fn remove(hm: *Self, key: K) ?KV {
207 if (hm.entries.len == 0) return null;213 if (hm.entries.len == 0) return null;
208 hm.incrementModificationCount();214 hm.incrementModificationCount();
...@@ -236,6 +242,11 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3...@@ -236,6 +242,11 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3
236 return null;242 return null;
237 }243 }
238244
245 /// Calls remove(), asserts that a kv pair is removed, and discards it.
246 pub fn removeAssertDiscard(hm: *Self, key: K) void {
247 assert(hm.remove(key) != null);
248 }
249
239 pub fn iterator(hm: *const Self) Iterator {250 pub fn iterator(hm: *const Self) Iterator {
240 return Iterator{251 return Iterator{
241 .hm = hm,252 .hm = hm,
...@@ -250,7 +261,7 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3...@@ -250,7 +261,7 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3
250 try other.initCapacity(self.entries.len);261 try other.initCapacity(self.entries.len);
251 var it = self.iterator();262 var it = self.iterator();
252 while (it.next()) |entry| {263 while (it.next()) |entry| {
253 assert((try other.put(entry.key, entry.value)) == null);264 try other.putNoClobber(entry.key, entry.value);
254 }265 }
255 return other;266 return other;
256 }267 }
...@@ -392,8 +403,8 @@ test "basic hash map usage" {...@@ -392,8 +403,8 @@ test "basic hash map usage" {
392 testing.expect((try map.put(2, 22)) == null);403 testing.expect((try map.put(2, 22)) == null);
393 testing.expect((try map.put(3, 33)) == null);404 testing.expect((try map.put(3, 33)) == null);
394 testing.expect((try map.put(4, 44)) == null);405 testing.expect((try map.put(4, 44)) == null);
395 testing.expect((try map.put(5, 55)) == null);
396406
407 map.putNoClobber(5, 55);
397 testing.expect((try map.put(5, 66)).?.value == 55);408 testing.expect((try map.put(5, 66)).?.value == 55);
398 testing.expect((try map.put(5, 55)).?.value == 66);409 testing.expect((try map.put(5, 55)).?.value == 66);
399410
...@@ -422,6 +433,8 @@ test "basic hash map usage" {...@@ -422,6 +433,8 @@ test "basic hash map usage" {
422 testing.expect(rmv1.?.value == 22);433 testing.expect(rmv1.?.value == 22);
423 testing.expect(map.remove(2) == null);434 testing.expect(map.remove(2) == null);
424 testing.expect(map.get(2) == null);435 testing.expect(map.get(2) == null);
436
437 map.removeAssertDiscard(3);
425}438}
426439
427test "iterator hash map" {440test "iterator hash map" {
...@@ -431,9 +444,9 @@ test "iterator hash map" {...@@ -431,9 +444,9 @@ test "iterator hash map" {
431 var reset_map = AutoHashMap(i32, i32).init(&direct_allocator.allocator);444 var reset_map = AutoHashMap(i32, i32).init(&direct_allocator.allocator);
432 defer reset_map.deinit();445 defer reset_map.deinit();
433446
434 testing.expect((try reset_map.put(1, 11)) == null);447 reset_map.putNoClobber(1, 11);
435 testing.expect((try reset_map.put(2, 22)) == null);448 reset_map.putNoClobber(2, 22);
436 testing.expect((try reset_map.put(3, 33)) == null);449 reset_map.putNoClobber(3, 33);
437450
438 var keys = [_]i32{451 var keys = [_]i32{
439 3,452 3,