| ... | ... | @@ -53,6 +53,14 @@ pub fn hashString(s: []const u8) u32 { |
| 53 | 53 | return @as(u32, @truncate(std.hash.Wyhash.hash(0, s))); |
| 54 | 54 | } |
| 55 | 55 | |
| 56 | /// Deprecated in favor of `ArrayHashMapWithAllocator` (no code changes needed) |
| 57 | /// or `ArrayHashMapUnmanaged` (will need to update callsites to pass an |
| 58 | /// allocator). After Zig 0.14.0 is released, `ArrayHashMapWithAllocator` will |
| 59 | /// be removed and `ArrayHashMapUnmanaged` will be a deprecated alias. After |
| 60 | /// Zig 0.15.0 is released, the deprecated alias `ArrayHashMapUnmanaged` will |
| 61 | /// be removed. |
| 62 | pub const ArrayHashMap = ArrayHashMapWithAllocator; |
| 63 | |
| 56 | 64 | /// A hash table of keys and values, each stored sequentially. |
| 57 | 65 | /// |
| 58 | 66 | /// Insertion order is preserved. In general, this data structure supports the same |
| ... | ... | @@ -67,7 +75,7 @@ pub fn hashString(s: []const u8) u32 { |
| 67 | 75 | /// |
| 68 | 76 | /// See `ArrayHashMapUnmanaged` for a variant of this data structure that accepts an |
| 69 | 77 | /// `Allocator` as a parameter when needed rather than storing it. |
| 70 | | pub fn ArrayHashMap( |
| 78 | pub fn ArrayHashMapWithAllocator( |
| 71 | 79 | comptime K: type, |
| 72 | 80 | comptime V: type, |
| 73 | 81 | /// A namespace that provides these two functions: |
| ... | ... | @@ -604,42 +612,48 @@ pub fn ArrayHashMapUnmanaged( |
| 604 | 612 | ordered, |
| 605 | 613 | }; |
| 606 | 614 | |
| 615 | const Oom = Allocator.Error; |
| 616 | |
| 607 | 617 | /// Convert from an unmanaged map to a managed map. After calling this, |
| 608 | 618 | /// the promoted map should no longer be used. |
| 609 | | pub fn promote(self: Self, allocator: Allocator) Managed { |
| 619 | pub fn promote(self: Self, gpa: Allocator) Managed { |
| 610 | 620 | if (@sizeOf(Context) != 0) |
| 611 | 621 | @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call promoteContext instead."); |
| 612 | | return self.promoteContext(allocator, undefined); |
| 622 | return self.promoteContext(gpa, undefined); |
| 613 | 623 | } |
| 614 | | pub fn promoteContext(self: Self, allocator: Allocator, ctx: Context) Managed { |
| 624 | pub fn promoteContext(self: Self, gpa: Allocator, ctx: Context) Managed { |
| 615 | 625 | return .{ |
| 616 | 626 | .unmanaged = self, |
| 617 | | .allocator = allocator, |
| 627 | .allocator = gpa, |
| 618 | 628 | .ctx = ctx, |
| 619 | 629 | }; |
| 620 | 630 | } |
| 621 | 631 | |
| 622 | | pub fn init(allocator: Allocator, key_list: []const K, value_list: []const V) !Self { |
| 632 | pub fn init(gpa: Allocator, key_list: []const K, value_list: []const V) Oom!Self { |
| 623 | 633 | var self: Self = .{}; |
| 624 | | try self.entries.resize(allocator, key_list.len); |
| 625 | | errdefer self.entries.deinit(allocator); |
| 634 | errdefer self.deinit(gpa); |
| 635 | try self.reinit(gpa, key_list, value_list); |
| 636 | return self; |
| 637 | } |
| 638 | |
| 639 | pub fn reinit(self: *Self, gpa: Allocator, key_list: []const K, value_list: []const V) Oom!void { |
| 640 | try self.entries.resize(gpa, key_list.len); |
| 626 | 641 | @memcpy(self.keys(), key_list); |
| 627 | 642 | if (@sizeOf(V) != 0) { |
| 628 | 643 | assert(key_list.len == value_list.len); |
| 629 | 644 | @memcpy(self.values(), value_list); |
| 630 | 645 | } |
| 631 | | try self.reIndex(allocator); |
| 632 | | return self; |
| 646 | try self.reIndex(gpa); |
| 633 | 647 | } |
| 634 | 648 | |
| 635 | 649 | /// Frees the backing allocation and leaves the map in an undefined state. |
| 636 | 650 | /// Note that this does not free keys or values. You must take care of that |
| 637 | 651 | /// before calling this function, if it is needed. |
| 638 | | pub fn deinit(self: *Self, allocator: Allocator) void { |
| 652 | pub fn deinit(self: *Self, gpa: Allocator) void { |
| 639 | 653 | self.pointer_stability.assertUnlocked(); |
| 640 | | self.entries.deinit(allocator); |
| 654 | self.entries.deinit(gpa); |
| 641 | 655 | if (self.index_header) |header| { |
| 642 | | header.free(allocator); |
| 656 | header.free(gpa); |
| 643 | 657 | } |
| 644 | 658 | self.* = undefined; |
| 645 | 659 | } |
| ... | ... | @@ -677,13 +691,13 @@ pub fn ArrayHashMapUnmanaged( |
| 677 | 691 | } |
| 678 | 692 | |
| 679 | 693 | /// Clears the map and releases the backing allocation |
| 680 | | pub fn clearAndFree(self: *Self, allocator: Allocator) void { |
| 694 | pub fn clearAndFree(self: *Self, gpa: Allocator) void { |
| 681 | 695 | self.pointer_stability.lock(); |
| 682 | 696 | defer self.pointer_stability.unlock(); |
| 683 | 697 | |
| 684 | | self.entries.shrinkAndFree(allocator, 0); |
| 698 | self.entries.shrinkAndFree(gpa, 0); |
| 685 | 699 | if (self.index_header) |header| { |
| 686 | | header.free(allocator); |
| 700 | header.free(gpa); |
| 687 | 701 | self.index_header = null; |
| 688 | 702 | } |
| 689 | 703 | } |
| ... | ... | @@ -746,25 +760,25 @@ pub fn ArrayHashMapUnmanaged( |
| 746 | 760 | /// Otherwise, puts a new item with undefined value, and |
| 747 | 761 | /// the `Entry` pointer points to it. Caller should then initialize |
| 748 | 762 | /// the value (but not the key). |
| 749 | | pub fn getOrPut(self: *Self, allocator: Allocator, key: K) !GetOrPutResult { |
| 763 | pub fn getOrPut(self: *Self, gpa: Allocator, key: K) Oom!GetOrPutResult { |
| 750 | 764 | if (@sizeOf(Context) != 0) |
| 751 | 765 | @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call getOrPutContext instead."); |
| 752 | | return self.getOrPutContext(allocator, key, undefined); |
| 766 | return self.getOrPutContext(gpa, key, undefined); |
| 753 | 767 | } |
| 754 | | pub fn getOrPutContext(self: *Self, allocator: Allocator, key: K, ctx: Context) !GetOrPutResult { |
| 755 | | const gop = try self.getOrPutContextAdapted(allocator, key, ctx, ctx); |
| 768 | pub fn getOrPutContext(self: *Self, gpa: Allocator, key: K, ctx: Context) Oom!GetOrPutResult { |
| 769 | const gop = try self.getOrPutContextAdapted(gpa, key, ctx, ctx); |
| 756 | 770 | if (!gop.found_existing) { |
| 757 | 771 | gop.key_ptr.* = key; |
| 758 | 772 | } |
| 759 | 773 | return gop; |
| 760 | 774 | } |
| 761 | | pub fn getOrPutAdapted(self: *Self, allocator: Allocator, key: anytype, key_ctx: anytype) !GetOrPutResult { |
| 775 | pub fn getOrPutAdapted(self: *Self, gpa: Allocator, key: anytype, key_ctx: anytype) Oom!GetOrPutResult { |
| 762 | 776 | if (@sizeOf(Context) != 0) |
| 763 | 777 | @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call getOrPutContextAdapted instead."); |
| 764 | | return self.getOrPutContextAdapted(allocator, key, key_ctx, undefined); |
| 778 | return self.getOrPutContextAdapted(gpa, key, key_ctx, undefined); |
| 765 | 779 | } |
| 766 | | pub fn getOrPutContextAdapted(self: *Self, allocator: Allocator, key: anytype, key_ctx: anytype, ctx: Context) !GetOrPutResult { |
| 767 | | self.ensureTotalCapacityContext(allocator, self.entries.len + 1, ctx) catch |err| { |
| 780 | pub fn getOrPutContextAdapted(self: *Self, gpa: Allocator, key: anytype, key_ctx: anytype, ctx: Context) Oom!GetOrPutResult { |
| 781 | self.ensureTotalCapacityContext(gpa, self.entries.len + 1, ctx) catch |err| { |
| 768 | 782 | // "If key exists this function cannot fail." |
| 769 | 783 | const index = self.getIndexAdapted(key, key_ctx) orelse return err; |
| 770 | 784 | const slice = self.entries.slice(); |
| ... | ... | @@ -844,13 +858,13 @@ pub fn ArrayHashMapUnmanaged( |
| 844 | 858 | } |
| 845 | 859 | } |
| 846 | 860 | |
| 847 | | pub fn getOrPutValue(self: *Self, allocator: Allocator, key: K, value: V) !GetOrPutResult { |
| 861 | pub fn getOrPutValue(self: *Self, gpa: Allocator, key: K, value: V) Oom!GetOrPutResult { |
| 848 | 862 | if (@sizeOf(Context) != 0) |
| 849 | 863 | @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call getOrPutValueContext instead."); |
| 850 | | return self.getOrPutValueContext(allocator, key, value, undefined); |
| 864 | return self.getOrPutValueContext(gpa, key, value, undefined); |
| 851 | 865 | } |
| 852 | | pub fn getOrPutValueContext(self: *Self, allocator: Allocator, key: K, value: V, ctx: Context) !GetOrPutResult { |
| 853 | | const res = try self.getOrPutContextAdapted(allocator, key, ctx, ctx); |
| 866 | pub fn getOrPutValueContext(self: *Self, gpa: Allocator, key: K, value: V, ctx: Context) Oom!GetOrPutResult { |
| 867 | const res = try self.getOrPutContextAdapted(gpa, key, ctx, ctx); |
| 854 | 868 | if (!res.found_existing) { |
| 855 | 869 | res.key_ptr.* = key; |
| 856 | 870 | res.value_ptr.* = value; |
| ... | ... | @@ -860,32 +874,32 @@ pub fn ArrayHashMapUnmanaged( |
| 860 | 874 | |
| 861 | 875 | /// Increases capacity, guaranteeing that insertions up until the |
| 862 | 876 | /// `expected_count` will not cause an allocation, and therefore cannot fail. |
| 863 | | pub fn ensureTotalCapacity(self: *Self, allocator: Allocator, new_capacity: usize) !void { |
| 877 | pub fn ensureTotalCapacity(self: *Self, gpa: Allocator, new_capacity: usize) Oom!void { |
| 864 | 878 | if (@sizeOf(ByIndexContext) != 0) |
| 865 | 879 | @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call ensureTotalCapacityContext instead."); |
| 866 | | return self.ensureTotalCapacityContext(allocator, new_capacity, undefined); |
| 880 | return self.ensureTotalCapacityContext(gpa, new_capacity, undefined); |
| 867 | 881 | } |
| 868 | | pub fn ensureTotalCapacityContext(self: *Self, allocator: Allocator, new_capacity: usize, ctx: Context) !void { |
| 882 | pub fn ensureTotalCapacityContext(self: *Self, gpa: Allocator, new_capacity: usize, ctx: Context) Oom!void { |
| 869 | 883 | self.pointer_stability.lock(); |
| 870 | 884 | defer self.pointer_stability.unlock(); |
| 871 | 885 | |
| 872 | 886 | if (new_capacity <= linear_scan_max) { |
| 873 | | try self.entries.ensureTotalCapacity(allocator, new_capacity); |
| 887 | try self.entries.ensureTotalCapacity(gpa, new_capacity); |
| 874 | 888 | return; |
| 875 | 889 | } |
| 876 | 890 | |
| 877 | 891 | if (self.index_header) |header| { |
| 878 | 892 | if (new_capacity <= header.capacity()) { |
| 879 | | try self.entries.ensureTotalCapacity(allocator, new_capacity); |
| 893 | try self.entries.ensureTotalCapacity(gpa, new_capacity); |
| 880 | 894 | return; |
| 881 | 895 | } |
| 882 | 896 | } |
| 883 | 897 | |
| 884 | | try self.entries.ensureTotalCapacity(allocator, new_capacity); |
| 898 | try self.entries.ensureTotalCapacity(gpa, new_capacity); |
| 885 | 899 | const new_bit_index = try IndexHeader.findBitIndex(new_capacity); |
| 886 | | const new_header = try IndexHeader.alloc(allocator, new_bit_index); |
| 900 | const new_header = try IndexHeader.alloc(gpa, new_bit_index); |
| 887 | 901 | |
| 888 | | if (self.index_header) |old_header| old_header.free(allocator); |
| 902 | if (self.index_header) |old_header| old_header.free(gpa); |
| 889 | 903 | self.insertAllEntriesIntoNewHeader(if (store_hash) {} else ctx, new_header); |
| 890 | 904 | self.index_header = new_header; |
| 891 | 905 | } |
| ... | ... | @@ -895,20 +909,20 @@ pub fn ArrayHashMapUnmanaged( |
| 895 | 909 | /// therefore cannot fail. |
| 896 | 910 | pub fn ensureUnusedCapacity( |
| 897 | 911 | self: *Self, |
| 898 | | allocator: Allocator, |
| 912 | gpa: Allocator, |
| 899 | 913 | additional_capacity: usize, |
| 900 | | ) !void { |
| 914 | ) Oom!void { |
| 901 | 915 | if (@sizeOf(Context) != 0) |
| 902 | 916 | @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call ensureTotalCapacityContext instead."); |
| 903 | | return self.ensureUnusedCapacityContext(allocator, additional_capacity, undefined); |
| 917 | return self.ensureUnusedCapacityContext(gpa, additional_capacity, undefined); |
| 904 | 918 | } |
| 905 | 919 | pub fn ensureUnusedCapacityContext( |
| 906 | 920 | self: *Self, |
| 907 | | allocator: Allocator, |
| 921 | gpa: Allocator, |
| 908 | 922 | additional_capacity: usize, |
| 909 | 923 | ctx: Context, |
| 910 | | ) !void { |
| 911 | | return self.ensureTotalCapacityContext(allocator, self.count() + additional_capacity, ctx); |
| 924 | ) Oom!void { |
| 925 | return self.ensureTotalCapacityContext(gpa, self.count() + additional_capacity, ctx); |
| 912 | 926 | } |
| 913 | 927 | |
| 914 | 928 | /// Returns the number of total elements which may be present before it is |
| ... | ... | @@ -922,25 +936,25 @@ pub fn ArrayHashMapUnmanaged( |
| 922 | 936 | |
| 923 | 937 | /// Clobbers any existing data. To detect if a put would clobber |
| 924 | 938 | /// existing data, see `getOrPut`. |
| 925 | | pub fn put(self: *Self, allocator: Allocator, key: K, value: V) !void { |
| 939 | pub fn put(self: *Self, gpa: Allocator, key: K, value: V) Oom!void { |
| 926 | 940 | if (@sizeOf(Context) != 0) |
| 927 | 941 | @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call putContext instead."); |
| 928 | | return self.putContext(allocator, key, value, undefined); |
| 942 | return self.putContext(gpa, key, value, undefined); |
| 929 | 943 | } |
| 930 | | pub fn putContext(self: *Self, allocator: Allocator, key: K, value: V, ctx: Context) !void { |
| 931 | | const result = try self.getOrPutContext(allocator, key, ctx); |
| 944 | pub fn putContext(self: *Self, gpa: Allocator, key: K, value: V, ctx: Context) Oom!void { |
| 945 | const result = try self.getOrPutContext(gpa, key, ctx); |
| 932 | 946 | result.value_ptr.* = value; |
| 933 | 947 | } |
| 934 | 948 | |
| 935 | 949 | /// Inserts a key-value pair into the hash map, asserting that no previous |
| 936 | 950 | /// entry with the same key is already present |
| 937 | | pub fn putNoClobber(self: *Self, allocator: Allocator, key: K, value: V) !void { |
| 951 | pub fn putNoClobber(self: *Self, gpa: Allocator, key: K, value: V) Oom!void { |
| 938 | 952 | if (@sizeOf(Context) != 0) |
| 939 | 953 | @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call putNoClobberContext instead."); |
| 940 | | return self.putNoClobberContext(allocator, key, value, undefined); |
| 954 | return self.putNoClobberContext(gpa, key, value, undefined); |
| 941 | 955 | } |
| 942 | | pub fn putNoClobberContext(self: *Self, allocator: Allocator, key: K, value: V, ctx: Context) !void { |
| 943 | | const result = try self.getOrPutContext(allocator, key, ctx); |
| 956 | pub fn putNoClobberContext(self: *Self, gpa: Allocator, key: K, value: V, ctx: Context) Oom!void { |
| 957 | const result = try self.getOrPutContext(gpa, key, ctx); |
| 944 | 958 | assert(!result.found_existing); |
| 945 | 959 | result.value_ptr.* = value; |
| 946 | 960 | } |
| ... | ... | @@ -973,13 +987,13 @@ pub fn ArrayHashMapUnmanaged( |
| 973 | 987 | } |
| 974 | 988 | |
| 975 | 989 | /// Inserts a new `Entry` into the hash map, returning the previous one, if any. |
| 976 | | pub fn fetchPut(self: *Self, allocator: Allocator, key: K, value: V) !?KV { |
| 990 | pub fn fetchPut(self: *Self, gpa: Allocator, key: K, value: V) Oom!?KV { |
| 977 | 991 | if (@sizeOf(Context) != 0) |
| 978 | 992 | @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call fetchPutContext instead."); |
| 979 | | return self.fetchPutContext(allocator, key, value, undefined); |
| 993 | return self.fetchPutContext(gpa, key, value, undefined); |
| 980 | 994 | } |
| 981 | | pub fn fetchPutContext(self: *Self, allocator: Allocator, key: K, value: V, ctx: Context) !?KV { |
| 982 | | const gop = try self.getOrPutContext(allocator, key, ctx); |
| 995 | pub fn fetchPutContext(self: *Self, gpa: Allocator, key: K, value: V, ctx: Context) Oom!?KV { |
| 996 | const gop = try self.getOrPutContext(gpa, key, ctx); |
| 983 | 997 | var result: ?KV = null; |
| 984 | 998 | if (gop.found_existing) { |
| 985 | 999 | result = KV{ |
| ... | ... | @@ -1265,20 +1279,20 @@ pub fn ArrayHashMapUnmanaged( |
| 1265 | 1279 | /// Create a copy of the hash map which can be modified separately. |
| 1266 | 1280 | /// The copy uses the same context as this instance, but is allocated |
| 1267 | 1281 | /// with the provided allocator. |
| 1268 | | pub fn clone(self: Self, allocator: Allocator) !Self { |
| 1282 | pub fn clone(self: Self, gpa: Allocator) Oom!Self { |
| 1269 | 1283 | if (@sizeOf(ByIndexContext) != 0) |
| 1270 | 1284 | @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call cloneContext instead."); |
| 1271 | | return self.cloneContext(allocator, undefined); |
| 1285 | return self.cloneContext(gpa, undefined); |
| 1272 | 1286 | } |
| 1273 | | pub fn cloneContext(self: Self, allocator: Allocator, ctx: Context) !Self { |
| 1287 | pub fn cloneContext(self: Self, gpa: Allocator, ctx: Context) Oom!Self { |
| 1274 | 1288 | var other: Self = .{}; |
| 1275 | | other.entries = try self.entries.clone(allocator); |
| 1276 | | errdefer other.entries.deinit(allocator); |
| 1289 | other.entries = try self.entries.clone(gpa); |
| 1290 | errdefer other.entries.deinit(gpa); |
| 1277 | 1291 | |
| 1278 | 1292 | if (self.index_header) |header| { |
| 1279 | 1293 | // TODO: I'm pretty sure this could be memcpy'd instead of |
| 1280 | 1294 | // doing all this work. |
| 1281 | | const new_header = try IndexHeader.alloc(allocator, header.bit_index); |
| 1295 | const new_header = try IndexHeader.alloc(gpa, header.bit_index); |
| 1282 | 1296 | other.insertAllEntriesIntoNewHeader(if (store_hash) {} else ctx, new_header); |
| 1283 | 1297 | other.index_header = new_header; |
| 1284 | 1298 | } |
| ... | ... | @@ -1304,13 +1318,13 @@ pub fn ArrayHashMapUnmanaged( |
| 1304 | 1318 | /// directly without going through the methods of this map. |
| 1305 | 1319 | /// |
| 1306 | 1320 | /// The time complexity of this operation is O(n). |
| 1307 | | pub fn reIndex(self: *Self, allocator: Allocator) !void { |
| 1321 | pub fn reIndex(self: *Self, gpa: Allocator) Oom!void { |
| 1308 | 1322 | if (@sizeOf(ByIndexContext) != 0) |
| 1309 | 1323 | @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call reIndexContext instead."); |
| 1310 | | return self.reIndexContext(allocator, undefined); |
| 1324 | return self.reIndexContext(gpa, undefined); |
| 1311 | 1325 | } |
| 1312 | 1326 | |
| 1313 | | pub fn reIndexContext(self: *Self, allocator: Allocator, ctx: Context) !void { |
| 1327 | pub fn reIndexContext(self: *Self, gpa: Allocator, ctx: Context) Oom!void { |
| 1314 | 1328 | // Recompute all hashes. |
| 1315 | 1329 | if (store_hash) { |
| 1316 | 1330 | for (self.keys(), self.entries.items(.hash)) |key, *hash| { |
| ... | ... | @@ -1323,8 +1337,8 @@ pub fn ArrayHashMapUnmanaged( |
| 1323 | 1337 | // We're going to rebuild the index header and replace the existing one (if any). The |
| 1324 | 1338 | // indexes should sized such that they will be at most 60% full. |
| 1325 | 1339 | const bit_index = try IndexHeader.findBitIndex(self.entries.capacity); |
| 1326 | | const new_header = try IndexHeader.alloc(allocator, bit_index); |
| 1327 | | if (self.index_header) |header| header.free(allocator); |
| 1340 | const new_header = try IndexHeader.alloc(gpa, bit_index); |
| 1341 | if (self.index_header) |header| header.free(gpa); |
| 1328 | 1342 | self.insertAllEntriesIntoNewHeader(if (store_hash) {} else ctx, new_header); |
| 1329 | 1343 | self.index_header = new_header; |
| 1330 | 1344 | } |
| ... | ... | @@ -1416,10 +1430,10 @@ pub fn ArrayHashMapUnmanaged( |
| 1416 | 1430 | /// performing hash and equality checks. It is a bug to call this |
| 1417 | 1431 | /// function if the discarded entries require deinitialization. For |
| 1418 | 1432 | /// that use case, `shrinkRetainingCapacity` can be used instead. |
| 1419 | | pub fn shrinkAndFree(self: *Self, allocator: Allocator, new_len: usize) void { |
| 1433 | pub fn shrinkAndFree(self: *Self, gpa: Allocator, new_len: usize) void { |
| 1420 | 1434 | if (@sizeOf(ByIndexContext) != 0) |
| 1421 | 1435 | @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call shrinkAndFreeContext instead."); |
| 1422 | | return self.shrinkAndFreeContext(allocator, new_len, undefined); |
| 1436 | return self.shrinkAndFreeContext(gpa, new_len, undefined); |
| 1423 | 1437 | } |
| 1424 | 1438 | |
| 1425 | 1439 | /// Shrinks the underlying `Entry` array to `new_len` elements and |
| ... | ... | @@ -1430,7 +1444,7 @@ pub fn ArrayHashMapUnmanaged( |
| 1430 | 1444 | /// function if the discarded entries require deinitialization. For |
| 1431 | 1445 | /// that use case, `shrinkRetainingCapacityContext` can be used |
| 1432 | 1446 | /// instead. |
| 1433 | | pub fn shrinkAndFreeContext(self: *Self, allocator: Allocator, new_len: usize, ctx: Context) void { |
| 1447 | pub fn shrinkAndFreeContext(self: *Self, gpa: Allocator, new_len: usize, ctx: Context) void { |
| 1434 | 1448 | self.pointer_stability.lock(); |
| 1435 | 1449 | defer self.pointer_stability.unlock(); |
| 1436 | 1450 | |
| ... | ... | @@ -1442,7 +1456,7 @@ pub fn ArrayHashMapUnmanaged( |
| 1442 | 1456 | while (i < self.entries.len) : (i += 1) |
| 1443 | 1457 | self.removeFromIndexByIndex(i, if (store_hash) {} else ctx, header); |
| 1444 | 1458 | } |
| 1445 | | self.entries.shrinkAndFree(allocator, new_len); |
| 1459 | self.entries.shrinkAndFree(gpa, new_len); |
| 1446 | 1460 | } |
| 1447 | 1461 | |
| 1448 | 1462 | /// Removes the last inserted `Entry` in the hash map and returns it. |
| ... | ... | @@ -2086,7 +2100,7 @@ const IndexHeader = struct { |
| 2086 | 2100 | return @as(u32, @intCast(self.length() - 1)); |
| 2087 | 2101 | } |
| 2088 | 2102 | |
| 2089 | | fn findBitIndex(desired_capacity: usize) !u8 { |
| 2103 | fn findBitIndex(desired_capacity: usize) Allocator.Error!u8 { |
| 2090 | 2104 | if (desired_capacity > max_capacity) return error.OutOfMemory; |
| 2091 | 2105 | var new_bit_index = @as(u8, @intCast(std.math.log2_int_ceil(usize, desired_capacity))); |
| 2092 | 2106 | if (desired_capacity > index_capacities[new_bit_index]) new_bit_index += 1; |
| ... | ... | @@ -2097,11 +2111,11 @@ const IndexHeader = struct { |
| 2097 | 2111 | |
| 2098 | 2112 | /// Allocates an index header, and fills the entryIndexes array with empty. |
| 2099 | 2113 | /// The distance array contents are undefined. |
| 2100 | | fn alloc(allocator: Allocator, new_bit_index: u8) !*IndexHeader { |
| 2114 | fn alloc(gpa: Allocator, new_bit_index: u8) Allocator.Error!*IndexHeader { |
| 2101 | 2115 | const len = @as(usize, 1) << @as(math.Log2Int(usize), @intCast(new_bit_index)); |
| 2102 | 2116 | const index_size = hash_map.capacityIndexSize(new_bit_index); |
| 2103 | 2117 | const nbytes = @sizeOf(IndexHeader) + index_size * len; |
| 2104 | | const bytes = try allocator.alignedAlloc(u8, @alignOf(IndexHeader), nbytes); |
| 2118 | const bytes = try gpa.alignedAlloc(u8, @alignOf(IndexHeader), nbytes); |
| 2105 | 2119 | @memset(bytes[@sizeOf(IndexHeader)..], 0xff); |
| 2106 | 2120 | const result: *IndexHeader = @alignCast(@ptrCast(bytes.ptr)); |
| 2107 | 2121 | result.* = .{ |
| ... | ... | @@ -2111,11 +2125,11 @@ const IndexHeader = struct { |
| 2111 | 2125 | } |
| 2112 | 2126 | |
| 2113 | 2127 | /// Releases the memory for a header and its associated arrays. |
| 2114 | | fn free(header: *IndexHeader, allocator: Allocator) void { |
| 2128 | fn free(header: *IndexHeader, gpa: Allocator) void { |
| 2115 | 2129 | const index_size = hash_map.capacityIndexSize(header.bit_index); |
| 2116 | 2130 | const ptr: [*]align(@alignOf(IndexHeader)) u8 = @ptrCast(header); |
| 2117 | 2131 | const slice = ptr[0 .. @sizeOf(IndexHeader) + header.length() * index_size]; |
| 2118 | | allocator.free(slice); |
| 2132 | gpa.free(slice); |
| 2119 | 2133 | } |
| 2120 | 2134 | |
| 2121 | 2135 | /// Puts an IndexHeader into the state that it would be in after being freshly allocated. |