| ... | @@ -118,7 +118,7 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3 | ... | @@ -118,7 +118,7 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3 |
| 118 | }; | 118 | }; |
| 119 | } | 119 | } |
| 120 | self.incrementModificationCount(); | 120 | self.incrementModificationCount(); |
| 121 | try self.ensureCapacity(); | 121 | try self.autoCapacity(); |
| 122 | const put_result = self.internalPut(key); | 122 | const put_result = self.internalPut(key); |
| 123 | assert(put_result.old_kv == null); | 123 | assert(put_result.old_kv == null); |
| 124 | return GetOrPutResult{ | 124 | return GetOrPutResult{ |
| ... | @@ -135,15 +135,15 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3 | ... | @@ -135,15 +135,15 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3 |
| 135 | return res.kv; | 135 | return res.kv; |
| 136 | } | 136 | } |
| 137 | | 137 | |
| 138 | fn ensureCapacity(self: *Self) !void { | 138 | /// Sets the capacity to the new capacity if the new |
| 139 | if (self.entries.len == 0) { | 139 | /// capacity is greater than the current capacity. |
| 140 | return self.initCapacity(16); | 140 | pub fn ensureCapacity(self: *Self, new_capacity: usize) !void { |
| | 141 | if (new_capacity <= self.entries.len) { |
| | 142 | return; |
| 141 | } | 143 | } |
| 142 | | 144 | const old_entries = self.entries; |
| 143 | // if we get too full (60%), double the capacity | 145 | try self.initCapacity(new_capacity); |
| 144 | if (self.size * 5 >= self.entries.len * 3) { | 146 | if (old_entries.len > 0) { |
| 145 | const old_entries = self.entries; | | |
| 146 | try self.initCapacity(self.entries.len * 2); | | |
| 147 | // dump all of the old elements into the new table | 147 | // dump all of the old elements into the new table |
| 148 | for (old_entries) |*old_entry| { | 148 | for (old_entries) |*old_entry| { |
| 149 | if (old_entry.used) { | 149 | if (old_entry.used) { |
| ... | @@ -157,7 +157,7 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3 | ... | @@ -157,7 +157,7 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3 |
| 157 | /// Returns the kv pair that was already there. | 157 | /// Returns the kv pair that was already there. |
| 158 | pub fn put(self: *Self, key: K, value: V) !?KV { | 158 | pub fn put(self: *Self, key: K, value: V) !?KV { |
| 159 | self.incrementModificationCount(); | 159 | self.incrementModificationCount(); |
| 160 | try self.ensureCapacity(); | 160 | try self.autoCapacity(); |
| 161 | | 161 | |
| 162 | const put_result = self.internalPut(key); | 162 | const put_result = self.internalPut(key); |
| 163 | put_result.new_entry.kv.value = value; | 163 | put_result.new_entry.kv.value = value; |
| ... | @@ -227,6 +227,16 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3 | ... | @@ -227,6 +227,16 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3 |
| 227 | return other; | 227 | return other; |
| 228 | } | 228 | } |
| 229 | | 229 | |
| | 230 | fn autoCapacity(self: *Self) !void { |
| | 231 | if (self.entries.len == 0) { |
| | 232 | return self.ensureCapacity(16); |
| | 233 | } |
| | 234 | // if we get too full (60%), double the capacity |
| | 235 | if (self.size * 5 >= self.entries.len * 3) { |
| | 236 | return self.ensureCapacity(self.entries.len * 2); |
| | 237 | } |
| | 238 | } |
| | 239 | |
| 230 | fn initCapacity(hm: *Self, capacity: usize) !void { | 240 | fn initCapacity(hm: *Self, capacity: usize) !void { |
| 231 | hm.entries = try hm.allocator.alloc(Entry, capacity); | 241 | hm.entries = try hm.allocator.alloc(Entry, capacity); |
| 232 | hm.size = 0; | 242 | hm.size = 0; |