| author | |
| committer | |
| log | c3a862522bbb59ee23a53e0562c402283db59b9c |
| tree | b14399fc672d911c11f6e9f14fb911f818b67d67 |
| parent | 0606af509f9a7f5e6bc458940aa9529d73232fc4 |
And deprecate all the API names except for:
* `std.array_hash_map.Auto`
* `std.array_hash_map.String`
* `std.array_hash_map.Custom`26 files changed, 271 insertions(+), 725 deletions(-)
lib/std/Build.zig+12-12| ... | ... | @@ -86,10 +86,10 @@ libc_runtimes_dir: ?[]const u8 = null, |
| 86 | 86 | |
| 87 | 87 | dep_prefix: []const u8 = "", |
| 88 | 88 | |
| 89 | modules: std.StringArrayHashMap(*Module), | |
| 89 | modules: std.array_hash_map.String(*Module), | |
| 90 | 90 | |
| 91 | named_writefiles: std.StringArrayHashMap(*Step.WriteFile), | |
| 92 | named_lazy_paths: std.StringArrayHashMap(LazyPath), | |
| 91 | named_writefiles: std.array_hash_map.String(*Step.WriteFile), | |
| 92 | named_lazy_paths: std.array_hash_map.String(LazyPath), | |
| 93 | 93 | /// The hash of this instance's package. `""` means that this is the root package. |
| 94 | 94 | pkg_hash: []const u8, |
| 95 | 95 | /// A mapping from dependency names to package hashes. |
| ... | ... | @@ -312,9 +312,9 @@ pub fn create( |
| 312 | 312 | }, |
| 313 | 313 | .install_path = undefined, |
| 314 | 314 | .args = null, |
| 315 | .modules = .init(arena), | |
| 316 | .named_writefiles = .init(arena), | |
| 317 | .named_lazy_paths = .init(arena), | |
| 315 | .modules = .empty, | |
| 316 | .named_writefiles = .empty, | |
| 317 | .named_lazy_paths = .empty, | |
| 318 | 318 | .pkg_hash = "", |
| 319 | 319 | .available_deps = available_deps, |
| 320 | 320 | .release_mode = .off, |
| ... | ... | @@ -405,9 +405,9 @@ fn createChildOnly( |
| 405 | 405 | .enable_wine = parent.enable_wine, |
| 406 | 406 | .libc_runtimes_dir = parent.libc_runtimes_dir, |
| 407 | 407 | .dep_prefix = parent.fmt("{s}{s}.", .{ parent.dep_prefix, dep_name }), |
| 408 | .modules = .init(allocator), | |
| 409 | .named_writefiles = .init(allocator), | |
| 410 | .named_lazy_paths = .init(allocator), | |
| 408 | .modules = .empty, | |
| 409 | .named_writefiles = .empty, | |
| 410 | .named_lazy_paths = .empty, | |
| 411 | 411 | .pkg_hash = pkg_hash, |
| 412 | 412 | .available_deps = pkg_deps, |
| 413 | 413 | .release_mode = parent.release_mode, |
| ... | ... | @@ -908,7 +908,7 @@ pub const AssemblyOptions = struct { |
| 908 | 908 | /// `createModule` can be used instead to create a private module. |
| 909 | 909 | pub fn addModule(b: *Build, name: []const u8, options: Module.CreateOptions) *Module { |
| 910 | 910 | const module = Module.create(b, options); |
| 911 | b.modules.put(b.dupe(name), module) catch @panic("OOM"); | |
| 911 | b.modules.put(b.graph.arena, b.dupe(name), module) catch @panic("OOM"); | |
| 912 | 912 | return module; |
| 913 | 913 | } |
| 914 | 914 | |
| ... | ... | @@ -1056,12 +1056,12 @@ pub fn addWriteFile(b: *Build, file_path: []const u8, data: []const u8) *Step.Wr |
| 1056 | 1056 | |
| 1057 | 1057 | pub fn addNamedWriteFiles(b: *Build, name: []const u8) *Step.WriteFile { |
| 1058 | 1058 | const wf = Step.WriteFile.create(b); |
| 1059 | b.named_writefiles.put(b.dupe(name), wf) catch @panic("OOM"); | |
| 1059 | b.named_writefiles.put(b.graph.arena, b.dupe(name), wf) catch @panic("OOM"); | |
| 1060 | 1060 | return wf; |
| 1061 | 1061 | } |
| 1062 | 1062 | |
| 1063 | 1063 | pub fn addNamedLazyPath(b: *Build, name: []const u8, lp: LazyPath) void { |
| 1064 | b.named_lazy_paths.put(b.dupe(name), lp.dupe(b)) catch @panic("OOM"); | |
| 1064 | b.named_lazy_paths.put(b.graph.arena, b.dupe(name), lp.dupe(b)) catch @panic("OOM"); | |
| 1065 | 1065 | } |
| 1066 | 1066 | |
| 1067 | 1067 | /// Creates a step for mutating files inside a temporary directory created lazily |
lib/std/Build/Step/CheckObject.zig+3-3| ... | ... | @@ -1814,16 +1814,16 @@ const ElfDumper = struct { |
| 1814 | 1814 | files.putAssumeCapacityNoClobber(object.off - @sizeOf(elf.ar_hdr), object.name); |
| 1815 | 1815 | } |
| 1816 | 1816 | |
| 1817 | var symbols = std.AutoArrayHashMap(usize, std.array_list.Managed([]const u8)).init(ctx.gpa); | |
| 1817 | var symbols: std.array_hash_map.Auto(usize, std.array_list.Managed([]const u8)) = .empty; | |
| 1818 | 1818 | defer { |
| 1819 | 1819 | for (symbols.values()) |*value| { |
| 1820 | 1820 | value.deinit(); |
| 1821 | 1821 | } |
| 1822 | symbols.deinit(); | |
| 1822 | symbols.deinit(ctx.gpa); | |
| 1823 | 1823 | } |
| 1824 | 1824 | |
| 1825 | 1825 | for (ctx.symtab.items) |entry| { |
| 1826 | const gop = try symbols.getOrPut(@intCast(entry.off)); | |
| 1826 | const gop = try symbols.getOrPut(ctx.gpa, @intCast(entry.off)); | |
| 1827 | 1827 | if (!gop.found_existing) { |
| 1828 | 1828 | gop.value_ptr.* = std.array_list.Managed([]const u8).init(ctx.gpa); |
| 1829 | 1829 | } |
lib/std/Build/Step/ConfigHeader.zig+34-32| ... | ... | @@ -38,7 +38,7 @@ pub const Value = union(enum) { |
| 38 | 38 | }; |
| 39 | 39 | |
| 40 | 40 | step: Step, |
| 41 | values: std.StringArrayHashMap(Value), | |
| 41 | values: std.array_hash_map.String(Value), | |
| 42 | 42 | /// This directory contains the generated file under the name `include_path`. |
| 43 | 43 | generated_dir: std.Build.GeneratedFile, |
| 44 | 44 | |
| ... | ... | @@ -95,7 +95,7 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader { |
| 95 | 95 | .first_ret_addr = options.first_ret_addr orelse @returnAddress(), |
| 96 | 96 | }), |
| 97 | 97 | .style = options.style, |
| 98 | .values = .init(owner.allocator), | |
| 98 | .values = .empty, | |
| 99 | 99 | |
| 100 | 100 | .max_bytes = options.max_bytes, |
| 101 | 101 | .include_path = include_path, |
| ... | ... | @@ -110,7 +110,8 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader { |
| 110 | 110 | } |
| 111 | 111 | |
| 112 | 112 | pub fn addIdent(config_header: *ConfigHeader, name: []const u8, value: []const u8) void { |
| 113 | config_header.values.put(name, .{ .ident = value }) catch @panic("OOM"); | |
| 113 | const arena = config_header.step.owner.allocator; | |
| 114 | config_header.values.put(arena, name, .{ .ident = value }) catch @panic("OOM"); | |
| 114 | 115 | } |
| 115 | 116 | |
| 116 | 117 | pub fn addValue(config_header: *ConfigHeader, name: []const u8, comptime T: type, value: T) void { |
| ... | ... | @@ -131,43 +132,44 @@ pub fn getOutputFile(ch: *ConfigHeader) std.Build.LazyPath { |
| 131 | 132 | } |
| 132 | 133 | |
| 133 | 134 | fn addValueInner(config_header: *ConfigHeader, name: []const u8, comptime T: type, value: T) !void { |
| 135 | const arena = config_header.step.owner.allocator; | |
| 134 | 136 | switch (@typeInfo(T)) { |
| 135 | 137 | .null => { |
| 136 | try config_header.values.put(name, .undef); | |
| 138 | try config_header.values.put(arena, name, .undef); | |
| 137 | 139 | }, |
| 138 | 140 | .void => { |
| 139 | try config_header.values.put(name, .defined); | |
| 141 | try config_header.values.put(arena, name, .defined); | |
| 140 | 142 | }, |
| 141 | 143 | .bool => { |
| 142 | try config_header.values.put(name, .{ .boolean = value }); | |
| 144 | try config_header.values.put(arena, name, .{ .boolean = value }); | |
| 143 | 145 | }, |
| 144 | 146 | .int => { |
| 145 | try config_header.values.put(name, .{ .int = value }); | |
| 147 | try config_header.values.put(arena, name, .{ .int = value }); | |
| 146 | 148 | }, |
| 147 | 149 | .comptime_int => { |
| 148 | try config_header.values.put(name, .{ .int = value }); | |
| 150 | try config_header.values.put(arena, name, .{ .int = value }); | |
| 149 | 151 | }, |
| 150 | 152 | .@"enum", .enum_literal => { |
| 151 | try config_header.values.put(name, .{ .ident = @tagName(value) }); | |
| 153 | try config_header.values.put(arena, name, .{ .ident = @tagName(value) }); | |
| 152 | 154 | }, |
| 153 | 155 | .optional => { |
| 154 | 156 | if (value) |x| { |
| 155 | 157 | return addValueInner(config_header, name, @TypeOf(x), x); |
| 156 | 158 | } else { |
| 157 | try config_header.values.put(name, .undef); | |
| 159 | try config_header.values.put(arena, name, .undef); | |
| 158 | 160 | } |
| 159 | 161 | }, |
| 160 | 162 | .pointer => |ptr| { |
| 161 | 163 | switch (@typeInfo(ptr.child)) { |
| 162 | 164 | .array => |array| { |
| 163 | 165 | if (ptr.size == .one and array.child == u8) { |
| 164 | try config_header.values.put(name, .{ .string = value }); | |
| 166 | try config_header.values.put(arena, name, .{ .string = value }); | |
| 165 | 167 | return; |
| 166 | 168 | } |
| 167 | 169 | }, |
| 168 | 170 | .int => { |
| 169 | 171 | if (ptr.size == .slice and ptr.child == u8) { |
| 170 | try config_header.values.put(name, .{ .string = value }); | |
| 172 | try config_header.values.put(arena, name, .{ .string = value }); | |
| 171 | 173 | return; |
| 172 | 174 | } |
| 173 | 175 | }, |
| ... | ... | @@ -218,8 +220,8 @@ fn make(step: *Step, options: Step.MakeOptions) !void { |
| 218 | 220 | }); |
| 219 | 221 | }; |
| 220 | 222 | switch (config_header.style) { |
| 221 | .autoconf_undef => try render_autoconf_undef(step, contents, bw, config_header.values, src_path), | |
| 222 | .autoconf_at => try render_autoconf_at(step, contents, &aw, config_header.values, src_path), | |
| 223 | .autoconf_undef => try render_autoconf_undef(step, contents, bw, &config_header.values, src_path), | |
| 224 | .autoconf_at => try render_autoconf_at(step, contents, &aw, &config_header.values, src_path), | |
| 223 | 225 | else => unreachable, |
| 224 | 226 | } |
| 225 | 227 | }, |
| ... | ... | @@ -282,7 +284,7 @@ fn render_autoconf_undef( |
| 282 | 284 | step: *Step, |
| 283 | 285 | contents: []const u8, |
| 284 | 286 | bw: *Writer, |
| 285 | values: std.StringArrayHashMap(Value), | |
| 287 | values: *const std.array_hash_map.String(Value), | |
| 286 | 288 | src_path: []const u8, |
| 287 | 289 | ) !void { |
| 288 | 290 | const build = step.owner; |
| ... | ... | @@ -334,7 +336,7 @@ fn render_autoconf_at( |
| 334 | 336 | step: *Step, |
| 335 | 337 | contents: []const u8, |
| 336 | 338 | aw: *Writer.Allocating, |
| 337 | values: std.StringArrayHashMap(Value), | |
| 339 | values: *const std.array_hash_map.String(Value), | |
| 338 | 340 | src_path: []const u8, |
| 339 | 341 | ) !void { |
| 340 | 342 | const build = step.owner; |
| ... | ... | @@ -373,7 +375,7 @@ fn render_autoconf_at( |
| 373 | 375 | if (!last_line) try bw.writeByte('\n'); |
| 374 | 376 | } |
| 375 | 377 | |
| 376 | for (values.unmanaged.entries.slice().items(.key), used) |name, u| { | |
| 378 | for (values.entries.slice().items(.key), used) |name, u| { | |
| 377 | 379 | if (!u) { |
| 378 | 380 | try step.addError("{s}: error: config header value unused: '{s}'", .{ src_path, name }); |
| 379 | 381 | any_errors = true; |
| ... | ... | @@ -387,14 +389,14 @@ fn render_cmake( |
| 387 | 389 | step: *Step, |
| 388 | 390 | contents: []const u8, |
| 389 | 391 | bw: *Writer, |
| 390 | values: std.StringArrayHashMap(Value), | |
| 392 | values: std.array_hash_map.String(Value), | |
| 391 | 393 | src_path: []const u8, |
| 392 | 394 | ) !void { |
| 393 | 395 | const build = step.owner; |
| 394 | 396 | const allocator = build.allocator; |
| 395 | 397 | |
| 396 | var values_copy = try values.clone(); | |
| 397 | defer values_copy.deinit(); | |
| 398 | var values_copy = try values.clone(allocator); | |
| 399 | defer values_copy.deinit(allocator); | |
| 398 | 400 | |
| 399 | 401 | var any_errors = false; |
| 400 | 402 | var line_index: u32 = 0; |
| ... | ... | @@ -523,7 +525,7 @@ fn render_cmake( |
| 523 | 525 | fn render_blank( |
| 524 | 526 | gpa: std.mem.Allocator, |
| 525 | 527 | bw: *Writer, |
| 526 | defines: std.StringArrayHashMap(Value), | |
| 528 | defines: std.array_hash_map.String(Value), | |
| 527 | 529 | include_path: []const u8, |
| 528 | 530 | include_guard_override: ?[]const u8, |
| 529 | 531 | ) !void { |
| ... | ... | @@ -555,7 +557,7 @@ fn render_blank( |
| 555 | 557 | , .{include_guard_name}); |
| 556 | 558 | } |
| 557 | 559 | |
| 558 | fn render_nasm(bw: *Writer, defines: std.StringArrayHashMap(Value)) !void { | |
| 560 | fn render_nasm(bw: *Writer, defines: std.array_hash_map.String(Value)) !void { | |
| 559 | 561 | for (defines.keys(), defines.values()) |name, value| try renderValueNasm(bw, name, value); |
| 560 | 562 | } |
| 561 | 563 | |
| ... | ... | @@ -586,7 +588,7 @@ fn renderValueNasm(bw: *Writer, name: []const u8, value: Value) !void { |
| 586 | 588 | fn expand_variables_autoconf_at( |
| 587 | 589 | bw: *Writer, |
| 588 | 590 | contents: []const u8, |
| 589 | values: std.StringArrayHashMap(Value), | |
| 591 | values: *const std.array_hash_map.String(Value), | |
| 590 | 592 | used: []bool, |
| 591 | 593 | ) !void { |
| 592 | 594 | const valid_varname_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_"; |
| ... | ... | @@ -612,7 +614,7 @@ fn expand_variables_autoconf_at( |
| 612 | 614 | try bw.writeAll(key); |
| 613 | 615 | return error.MissingValue; |
| 614 | 616 | }; |
| 615 | const value = values.unmanaged.entries.slice().items(.value)[index]; | |
| 617 | const value = values.entries.slice().items(.value)[index]; | |
| 616 | 618 | used[index] = true; |
| 617 | 619 | try bw.writeAll(contents[source_offset..curr]); |
| 618 | 620 | switch (value) { |
| ... | ... | @@ -633,7 +635,7 @@ fn expand_variables_autoconf_at( |
| 633 | 635 | fn expand_variables_cmake( |
| 634 | 636 | allocator: Allocator, |
| 635 | 637 | contents: []const u8, |
| 636 | values: std.StringArrayHashMap(Value), | |
| 638 | values: std.array_hash_map.String(Value), | |
| 637 | 639 | ) ![]const u8 { |
| 638 | 640 | var result: std.array_list.Managed(u8) = .init(allocator); |
| 639 | 641 | errdefer result.deinit(); |
| ... | ... | @@ -765,7 +767,7 @@ fn testReplaceVariablesAutoconfAt( |
| 765 | 767 | allocator: Allocator, |
| 766 | 768 | contents: []const u8, |
| 767 | 769 | expected: []const u8, |
| 768 | values: std.StringArrayHashMap(Value), | |
| 770 | values: std.array_hash_map.String(Value), | |
| 769 | 771 | ) !void { |
| 770 | 772 | var aw: Writer.Allocating = .init(allocator); |
| 771 | 773 | defer aw.deinit(); |
| ... | ... | @@ -784,7 +786,7 @@ fn testReplaceVariablesCMake( |
| 784 | 786 | allocator: Allocator, |
| 785 | 787 | contents: []const u8, |
| 786 | 788 | expected: []const u8, |
| 787 | values: std.StringArrayHashMap(Value), | |
| 789 | values: std.array_hash_map.String(Value), | |
| 788 | 790 | ) !void { |
| 789 | 791 | const actual = try expand_variables_cmake(allocator, contents, values); |
| 790 | 792 | defer allocator.free(actual); |
| ... | ... | @@ -794,7 +796,7 @@ fn testReplaceVariablesCMake( |
| 794 | 796 | |
| 795 | 797 | test "expand_variables_autoconf_at simple cases" { |
| 796 | 798 | const allocator = std.testing.allocator; |
| 797 | var values: std.StringArrayHashMap(Value) = .init(allocator); | |
| 799 | var values: std.array_hash_map.String(Value) = .init(allocator); | |
| 798 | 800 | defer values.deinit(); |
| 799 | 801 | |
| 800 | 802 | // empty strings are preserved |
| ... | ... | @@ -890,7 +892,7 @@ test "expand_variables_autoconf_at simple cases" { |
| 890 | 892 | |
| 891 | 893 | test "expand_variables_autoconf_at edge cases" { |
| 892 | 894 | const allocator = std.testing.allocator; |
| 893 | var values: std.StringArrayHashMap(Value) = .init(allocator); | |
| 895 | var values: std.array_hash_map.String(Value) = .init(allocator); | |
| 894 | 896 | defer values.deinit(); |
| 895 | 897 | |
| 896 | 898 | // @-vars resolved only when they wrap valid characters, otherwise considered literals |
| ... | ... | @@ -906,7 +908,7 @@ test "expand_variables_autoconf_at edge cases" { |
| 906 | 908 | |
| 907 | 909 | test "expand_variables_cmake simple cases" { |
| 908 | 910 | const allocator = std.testing.allocator; |
| 909 | var values: std.StringArrayHashMap(Value) = .init(allocator); | |
| 911 | var values: std.array_hash_map.String(Value) = .init(allocator); | |
| 910 | 912 | defer values.deinit(); |
| 911 | 913 | |
| 912 | 914 | try values.putNoClobber("undef", .undef); |
| ... | ... | @@ -994,7 +996,7 @@ test "expand_variables_cmake simple cases" { |
| 994 | 996 | |
| 995 | 997 | test "expand_variables_cmake edge cases" { |
| 996 | 998 | const allocator = std.testing.allocator; |
| 997 | var values: std.StringArrayHashMap(Value) = .init(allocator); | |
| 999 | var values: std.array_hash_map.String(Value) = .init(allocator); | |
| 998 | 1000 | defer values.deinit(); |
| 999 | 1001 | |
| 1000 | 1002 | // special symbols |
| ... | ... | @@ -1055,7 +1057,7 @@ test "expand_variables_cmake edge cases" { |
| 1055 | 1057 | |
| 1056 | 1058 | test "expand_variables_cmake escaped characters" { |
| 1057 | 1059 | const allocator = std.testing.allocator; |
| 1058 | var values: std.StringArrayHashMap(Value) = .init(allocator); | |
| 1060 | var values: std.array_hash_map.String(Value) = .init(allocator); | |
| 1059 | 1061 | defer values.deinit(); |
| 1060 | 1062 | |
| 1061 | 1063 | try values.putNoClobber("string", Value{ .string = "text" }); |
lib/std/array_hash_map.zig+96-555| ... | ... | @@ -12,27 +12,15 @@ const hash_map = @This(); |
| 12 | 12 | /// An `ArrayHashMap` with default hash and equal functions. |
| 13 | 13 | /// |
| 14 | 14 | /// See `AutoContext` for a description of the hash and equal implementations. |
| 15 | pub fn AutoArrayHashMap(comptime K: type, comptime V: type) type { | |
| 15 | pub fn Auto(comptime K: type, comptime V: type) type { | |
| 16 | 16 | return ArrayHashMap(K, V, AutoContext(K), !autoEqlIsCheap(K)); |
| 17 | 17 | } |
| 18 | 18 | |
| 19 | /// An `ArrayHashMapUnmanaged` with default hash and equal functions. | |
| 20 | /// | |
| 21 | /// See `AutoContext` for a description of the hash and equal implementations. | |
| 22 | pub fn AutoArrayHashMapUnmanaged(comptime K: type, comptime V: type) type { | |
| 23 | return ArrayHashMapUnmanaged(K, V, AutoContext(K), !autoEqlIsCheap(K)); | |
| 24 | } | |
| 25 | ||
| 26 | 19 | /// An `ArrayHashMap` with strings as keys. |
| 27 | pub fn StringArrayHashMap(comptime V: type) type { | |
| 20 | pub fn String(comptime V: type) type { | |
| 28 | 21 | return ArrayHashMap([]const u8, V, StringContext, true); |
| 29 | 22 | } |
| 30 | 23 | |
| 31 | /// An `ArrayHashMapUnmanaged` with strings as keys. | |
| 32 | pub fn StringArrayHashMapUnmanaged(comptime V: type) type { | |
| 33 | return ArrayHashMapUnmanaged([]const u8, V, StringContext, true); | |
| 34 | } | |
| 35 | ||
| 36 | 24 | pub const StringContext = struct { |
| 37 | 25 | pub fn hash(self: @This(), s: []const u8) u32 { |
| 38 | 26 | _ = self; |
| ... | ... | @@ -53,454 +41,8 @@ pub fn hashString(s: []const u8) u32 { |
| 53 | 41 | return @truncate(std.hash.Wyhash.hash(0, s)); |
| 54 | 42 | } |
| 55 | 43 | |
| 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 | ||
| 64 | /// A hash table of keys and values, each stored sequentially. | |
| 65 | /// | |
| 66 | /// Insertion order is preserved. In general, this data structure supports the same | |
| 67 | /// operations as `std.ArrayList`. | |
| 68 | /// | |
| 69 | /// Deletion operations: | |
| 70 | /// * `swapRemove` - O(1) | |
| 71 | /// * `orderedRemove` - O(N) | |
| 72 | /// | |
| 73 | /// Modifying the hash map while iterating is allowed, however, one must understand | |
| 74 | /// the (well defined) behavior when mixing insertions and deletions with iteration. | |
| 75 | /// | |
| 76 | /// See `ArrayHashMapUnmanaged` for a variant of this data structure that accepts an | |
| 77 | /// `Allocator` as a parameter when needed rather than storing it. | |
| 78 | pub fn ArrayHashMapWithAllocator( | |
| 79 | comptime K: type, | |
| 80 | comptime V: type, | |
| 81 | /// A namespace that provides these two functions: | |
| 82 | /// * `pub fn hash(self, K) u32` | |
| 83 | /// * `pub fn eql(self, K, K, usize) bool` | |
| 84 | /// | |
| 85 | /// The final `usize` in the `eql` function represents the index of the key | |
| 86 | /// that's already inside the map. | |
| 87 | comptime Context: type, | |
| 88 | /// When `false`, this data structure is biased towards cheap `eql` | |
| 89 | /// functions and avoids storing each key's hash in the table. Setting | |
| 90 | /// `store_hash` to `true` incurs more memory cost but limits `eql` to | |
| 91 | /// being called only once per insertion/deletion (provided there are no | |
| 92 | /// hash collisions). | |
| 93 | comptime store_hash: bool, | |
| 94 | ) type { | |
| 95 | return struct { | |
| 96 | unmanaged: Unmanaged, | |
| 97 | allocator: Allocator, | |
| 98 | ctx: Context, | |
| 99 | ||
| 100 | /// The ArrayHashMapUnmanaged type using the same settings as this managed map. | |
| 101 | pub const Unmanaged = ArrayHashMapUnmanaged(K, V, Context, store_hash); | |
| 102 | ||
| 103 | /// Pointers to a key and value in the backing store of this map. | |
| 104 | /// Modifying the key is allowed only if it does not change the hash. | |
| 105 | /// Modifying the value is allowed. | |
| 106 | /// Entry pointers become invalid whenever this ArrayHashMap is modified, | |
| 107 | /// unless `ensureTotalCapacity`/`ensureUnusedCapacity` was previously used. | |
| 108 | pub const Entry = Unmanaged.Entry; | |
| 109 | ||
| 110 | /// A KV pair which has been copied out of the backing store | |
| 111 | pub const KV = Unmanaged.KV; | |
| 112 | ||
| 113 | /// The Data type used for the MultiArrayList backing this map | |
| 114 | pub const Data = Unmanaged.Data; | |
| 115 | /// The MultiArrayList type backing this map | |
| 116 | pub const DataList = Unmanaged.DataList; | |
| 117 | ||
| 118 | /// The stored hash type, either u32 or void. | |
| 119 | pub const Hash = Unmanaged.Hash; | |
| 120 | ||
| 121 | /// getOrPut variants return this structure, with pointers | |
| 122 | /// to the backing store and a flag to indicate whether an | |
| 123 | /// existing entry was found. | |
| 124 | /// Modifying the key is allowed only if it does not change the hash. | |
| 125 | /// Modifying the value is allowed. | |
| 126 | /// Entry pointers become invalid whenever this ArrayHashMap is modified, | |
| 127 | /// unless `ensureTotalCapacity`/`ensureUnusedCapacity` was previously used. | |
| 128 | pub const GetOrPutResult = Unmanaged.GetOrPutResult; | |
| 129 | ||
| 130 | /// An Iterator over Entry pointers. | |
| 131 | pub const Iterator = Unmanaged.Iterator; | |
| 132 | ||
| 133 | const Self = @This(); | |
| 134 | ||
| 135 | /// Create an ArrayHashMap instance which will use a specified allocator. | |
| 136 | pub fn init(allocator: Allocator) Self { | |
| 137 | if (@sizeOf(Context) != 0) | |
| 138 | @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call initContext instead."); | |
| 139 | return initContext(allocator, undefined); | |
| 140 | } | |
| 141 | pub fn initContext(allocator: Allocator, ctx: Context) Self { | |
| 142 | return .{ | |
| 143 | .unmanaged = .empty, | |
| 144 | .allocator = allocator, | |
| 145 | .ctx = ctx, | |
| 146 | }; | |
| 147 | } | |
| 148 | ||
| 149 | /// Frees the backing allocation and leaves the map in an undefined state. | |
| 150 | /// Note that this does not free keys or values. You must take care of that | |
| 151 | /// before calling this function, if it is needed. | |
| 152 | pub fn deinit(self: *Self) void { | |
| 153 | self.unmanaged.deinit(self.allocator); | |
| 154 | self.* = undefined; | |
| 155 | } | |
| 156 | ||
| 157 | /// Puts the hash map into a state where any method call that would | |
| 158 | /// cause an existing key or value pointer to become invalidated will | |
| 159 | /// instead trigger an assertion. | |
| 160 | /// | |
| 161 | /// An additional call to `lockPointers` in such state also triggers an | |
| 162 | /// assertion. | |
| 163 | /// | |
| 164 | /// `unlockPointers` returns the hash map to the previous state. | |
| 165 | pub fn lockPointers(self: *Self) void { | |
| 166 | self.unmanaged.lockPointers(); | |
| 167 | } | |
| 168 | ||
| 169 | /// Undoes a call to `lockPointers`. | |
| 170 | pub fn unlockPointers(self: *Self) void { | |
| 171 | self.unmanaged.unlockPointers(); | |
| 172 | } | |
| 173 | ||
| 174 | /// Clears the map but retains the backing allocation for future use. | |
| 175 | pub fn clearRetainingCapacity(self: *Self) void { | |
| 176 | return self.unmanaged.clearRetainingCapacity(); | |
| 177 | } | |
| 178 | ||
| 179 | /// Clears the map and releases the backing allocation | |
| 180 | pub fn clearAndFree(self: *Self) void { | |
| 181 | return self.unmanaged.clearAndFree(self.allocator); | |
| 182 | } | |
| 183 | ||
| 184 | /// Returns the number of KV pairs stored in this map. | |
| 185 | pub fn count(self: Self) usize { | |
| 186 | return self.unmanaged.count(); | |
| 187 | } | |
| 188 | ||
| 189 | /// Returns the backing array of keys in this map. Modifying the map may | |
| 190 | /// invalidate this array. Modifying this array in a way that changes | |
| 191 | /// key hashes or key equality puts the map into an unusable state until | |
| 192 | /// `reIndex` is called. | |
| 193 | pub fn keys(self: Self) []K { | |
| 194 | return self.unmanaged.keys(); | |
| 195 | } | |
| 196 | /// Returns the backing array of values in this map. Modifying the map | |
| 197 | /// may invalidate this array. It is permitted to modify the values in | |
| 198 | /// this array. | |
| 199 | pub fn values(self: Self) []V { | |
| 200 | return self.unmanaged.values(); | |
| 201 | } | |
| 202 | ||
| 203 | /// Returns an iterator over the pairs in this map. | |
| 204 | /// Modifying the map may invalidate this iterator. | |
| 205 | pub fn iterator(self: *const Self) Iterator { | |
| 206 | return self.unmanaged.iterator(); | |
| 207 | } | |
| 208 | ||
| 209 | /// If key exists this function cannot fail. | |
| 210 | /// If there is an existing item with `key`, then the result | |
| 211 | /// `Entry` pointer points to it, and found_existing is true. | |
| 212 | /// Otherwise, puts a new item with undefined value, and | |
| 213 | /// the `Entry` pointer points to it. Caller should then initialize | |
| 214 | /// the value (but not the key). | |
| 215 | pub fn getOrPut(self: *Self, key: K) !GetOrPutResult { | |
| 216 | return self.unmanaged.getOrPutContext(self.allocator, key, self.ctx); | |
| 217 | } | |
| 218 | pub fn getOrPutAdapted(self: *Self, key: anytype, ctx: anytype) !GetOrPutResult { | |
| 219 | return self.unmanaged.getOrPutContextAdapted(self.allocator, key, ctx, self.ctx); | |
| 220 | } | |
| 221 | ||
| 222 | /// If there is an existing item with `key`, then the result | |
| 223 | /// `Entry` pointer points to it, and found_existing is true. | |
| 224 | /// Otherwise, puts a new item with undefined value, and | |
| 225 | /// the `Entry` pointer points to it. Caller should then initialize | |
| 226 | /// the value (but not the key). | |
| 227 | /// If a new entry needs to be stored, this function asserts there | |
| 228 | /// is enough capacity to store it. | |
| 229 | pub fn getOrPutAssumeCapacity(self: *Self, key: K) GetOrPutResult { | |
| 230 | return self.unmanaged.getOrPutAssumeCapacityContext(key, self.ctx); | |
| 231 | } | |
| 232 | pub fn getOrPutAssumeCapacityAdapted(self: *Self, key: anytype, ctx: anytype) GetOrPutResult { | |
| 233 | return self.unmanaged.getOrPutAssumeCapacityAdapted(key, ctx); | |
| 234 | } | |
| 235 | pub fn getOrPutValue(self: *Self, key: K, value: V) !GetOrPutResult { | |
| 236 | return self.unmanaged.getOrPutValueContext(self.allocator, key, value, self.ctx); | |
| 237 | } | |
| 238 | ||
| 239 | /// Increases capacity, guaranteeing that insertions up until the | |
| 240 | /// `expected_count` will not cause an allocation, and therefore cannot fail. | |
| 241 | pub fn ensureTotalCapacity(self: *Self, new_capacity: usize) !void { | |
| 242 | return self.unmanaged.ensureTotalCapacityContext(self.allocator, new_capacity, self.ctx); | |
| 243 | } | |
| 244 | ||
| 245 | /// Increases capacity, guaranteeing that insertions up until | |
| 246 | /// `additional_count` **more** items will not cause an allocation, and | |
| 247 | /// therefore cannot fail. | |
| 248 | pub fn ensureUnusedCapacity(self: *Self, additional_count: usize) !void { | |
| 249 | return self.unmanaged.ensureUnusedCapacityContext(self.allocator, additional_count, self.ctx); | |
| 250 | } | |
| 251 | ||
| 252 | /// Returns the number of total elements which may be present before it is | |
| 253 | /// no longer guaranteed that no allocations will be performed. | |
| 254 | pub fn capacity(self: Self) usize { | |
| 255 | return self.unmanaged.capacity(); | |
| 256 | } | |
| 257 | ||
| 258 | /// Clobbers any existing data. To detect if a put would clobber | |
| 259 | /// existing data, see `getOrPut`. | |
| 260 | pub fn put(self: *Self, key: K, value: V) !void { | |
| 261 | return self.unmanaged.putContext(self.allocator, key, value, self.ctx); | |
| 262 | } | |
| 263 | ||
| 264 | /// Inserts a key-value pair into the hash map, asserting that no previous | |
| 265 | /// entry with the same key is already present | |
| 266 | pub fn putNoClobber(self: *Self, key: K, value: V) !void { | |
| 267 | return self.unmanaged.putNoClobberContext(self.allocator, key, value, self.ctx); | |
| 268 | } | |
| 269 | ||
| 270 | /// Asserts there is enough capacity to store the new key-value pair. | |
| 271 | /// Clobbers any existing data. To detect if a put would clobber | |
| 272 | /// existing data, see `getOrPutAssumeCapacity`. | |
| 273 | pub fn putAssumeCapacity(self: *Self, key: K, value: V) void { | |
| 274 | return self.unmanaged.putAssumeCapacityContext(key, value, self.ctx); | |
| 275 | } | |
| 276 | ||
| 277 | /// Asserts there is enough capacity to store the new key-value pair. | |
| 278 | /// Asserts that it does not clobber any existing data. | |
| 279 | /// To detect if a put would clobber existing data, see `getOrPutAssumeCapacity`. | |
| 280 | pub fn putAssumeCapacityNoClobber(self: *Self, key: K, value: V) void { | |
| 281 | return self.unmanaged.putAssumeCapacityNoClobberContext(key, value, self.ctx); | |
| 282 | } | |
| 283 | ||
| 284 | /// Inserts a new `Entry` into the hash map, returning the previous one, if any. | |
| 285 | pub fn fetchPut(self: *Self, key: K, value: V) !?KV { | |
| 286 | return self.unmanaged.fetchPutContext(self.allocator, key, value, self.ctx); | |
| 287 | } | |
| 288 | ||
| 289 | /// Inserts a new `Entry` into the hash map, returning the previous one, if any. | |
| 290 | /// If insertion happuns, asserts there is enough capacity without allocating. | |
| 291 | pub fn fetchPutAssumeCapacity(self: *Self, key: K, value: V) ?KV { | |
| 292 | return self.unmanaged.fetchPutAssumeCapacityContext(key, value, self.ctx); | |
| 293 | } | |
| 294 | ||
| 295 | /// Finds pointers to the key and value storage associated with a key. | |
| 296 | pub fn getEntry(self: Self, key: K) ?Entry { | |
| 297 | return self.unmanaged.getEntryContext(key, self.ctx); | |
| 298 | } | |
| 299 | pub fn getEntryAdapted(self: Self, key: anytype, ctx: anytype) ?Entry { | |
| 300 | return self.unmanaged.getEntryAdapted(key, ctx); | |
| 301 | } | |
| 302 | ||
| 303 | /// Finds the index in the `entries` array where a key is stored | |
| 304 | pub fn getIndex(self: Self, key: K) ?usize { | |
| 305 | return self.unmanaged.getIndexContext(key, self.ctx); | |
| 306 | } | |
| 307 | pub fn getIndexAdapted(self: Self, key: anytype, ctx: anytype) ?usize { | |
| 308 | return self.unmanaged.getIndexAdapted(key, ctx); | |
| 309 | } | |
| 310 | ||
| 311 | /// Find the value associated with a key | |
| 312 | pub fn get(self: Self, key: K) ?V { | |
| 313 | return self.unmanaged.getContext(key, self.ctx); | |
| 314 | } | |
| 315 | pub fn getAdapted(self: Self, key: anytype, ctx: anytype) ?V { | |
| 316 | return self.unmanaged.getAdapted(key, ctx); | |
| 317 | } | |
| 318 | ||
| 319 | /// Find a pointer to the value associated with a key | |
| 320 | pub fn getPtr(self: Self, key: K) ?*V { | |
| 321 | return self.unmanaged.getPtrContext(key, self.ctx); | |
| 322 | } | |
| 323 | pub fn getPtrAdapted(self: Self, key: anytype, ctx: anytype) ?*V { | |
| 324 | return self.unmanaged.getPtrAdapted(key, ctx); | |
| 325 | } | |
| 326 | ||
| 327 | /// Find the actual key associated with an adapted key | |
| 328 | pub fn getKey(self: Self, key: K) ?K { | |
| 329 | return self.unmanaged.getKeyContext(key, self.ctx); | |
| 330 | } | |
| 331 | pub fn getKeyAdapted(self: Self, key: anytype, ctx: anytype) ?K { | |
| 332 | return self.unmanaged.getKeyAdapted(key, ctx); | |
| 333 | } | |
| 334 | ||
| 335 | /// Find a pointer to the actual key associated with an adapted key | |
| 336 | pub fn getKeyPtr(self: Self, key: K) ?*K { | |
| 337 | return self.unmanaged.getKeyPtrContext(key, self.ctx); | |
| 338 | } | |
| 339 | pub fn getKeyPtrAdapted(self: Self, key: anytype, ctx: anytype) ?*K { | |
| 340 | return self.unmanaged.getKeyPtrAdapted(key, ctx); | |
| 341 | } | |
| 342 | ||
| 343 | /// Check whether a key is stored in the map | |
| 344 | pub fn contains(self: Self, key: K) bool { | |
| 345 | return self.unmanaged.containsContext(key, self.ctx); | |
| 346 | } | |
| 347 | pub fn containsAdapted(self: Self, key: anytype, ctx: anytype) bool { | |
| 348 | return self.unmanaged.containsAdapted(key, ctx); | |
| 349 | } | |
| 350 | ||
| 351 | /// If there is an `Entry` with a matching key, it is deleted from | |
| 352 | /// the hash map, and then returned from this function. The entry is | |
| 353 | /// removed from the underlying array by swapping it with the last | |
| 354 | /// element. | |
| 355 | pub fn fetchSwapRemove(self: *Self, key: K) ?KV { | |
| 356 | return self.unmanaged.fetchSwapRemoveContext(key, self.ctx); | |
| 357 | } | |
| 358 | pub fn fetchSwapRemoveAdapted(self: *Self, key: anytype, ctx: anytype) ?KV { | |
| 359 | return self.unmanaged.fetchSwapRemoveContextAdapted(key, ctx, self.ctx); | |
| 360 | } | |
| 361 | ||
| 362 | /// If there is an `Entry` with a matching key, it is deleted from | |
| 363 | /// the hash map, and then returned from this function. The entry is | |
| 364 | /// removed from the underlying array by shifting all elements forward | |
| 365 | /// thereby maintaining the current ordering. | |
| 366 | pub fn fetchOrderedRemove(self: *Self, key: K) ?KV { | |
| 367 | return self.unmanaged.fetchOrderedRemoveContext(key, self.ctx); | |
| 368 | } | |
| 369 | pub fn fetchOrderedRemoveAdapted(self: *Self, key: anytype, ctx: anytype) ?KV { | |
| 370 | return self.unmanaged.fetchOrderedRemoveContextAdapted(key, ctx, self.ctx); | |
| 371 | } | |
| 372 | ||
| 373 | /// If there is an `Entry` with a matching key, it is deleted from | |
| 374 | /// the hash map. The entry is removed from the underlying array | |
| 375 | /// by swapping it with the last element. Returns true if an entry | |
| 376 | /// was removed, false otherwise. | |
| 377 | pub fn swapRemove(self: *Self, key: K) bool { | |
| 378 | return self.unmanaged.swapRemoveContext(key, self.ctx); | |
| 379 | } | |
| 380 | pub fn swapRemoveAdapted(self: *Self, key: anytype, ctx: anytype) bool { | |
| 381 | return self.unmanaged.swapRemoveContextAdapted(key, ctx, self.ctx); | |
| 382 | } | |
| 383 | ||
| 384 | /// If there is an `Entry` with a matching key, it is deleted from | |
| 385 | /// the hash map. The entry is removed from the underlying array | |
| 386 | /// by shifting all elements forward, thereby maintaining the | |
| 387 | /// current ordering. Returns true if an entry was removed, false otherwise. | |
| 388 | pub fn orderedRemove(self: *Self, key: K) bool { | |
| 389 | return self.unmanaged.orderedRemoveContext(key, self.ctx); | |
| 390 | } | |
| 391 | pub fn orderedRemoveAdapted(self: *Self, key: anytype, ctx: anytype) bool { | |
| 392 | return self.unmanaged.orderedRemoveContextAdapted(key, ctx, self.ctx); | |
| 393 | } | |
| 394 | ||
| 395 | /// Deletes the item at the specified index in `entries` from | |
| 396 | /// the hash map. The entry is removed from the underlying array | |
| 397 | /// by swapping it with the last element. | |
| 398 | pub fn swapRemoveAt(self: *Self, index: usize) void { | |
| 399 | self.unmanaged.swapRemoveAtContext(index, self.ctx); | |
| 400 | } | |
| 401 | ||
| 402 | /// Deletes the item at the specified index in `entries` from | |
| 403 | /// the hash map. The entry is removed from the underlying array | |
| 404 | /// by shifting all elements forward, thereby maintaining the | |
| 405 | /// current ordering. | |
| 406 | pub fn orderedRemoveAt(self: *Self, index: usize) void { | |
| 407 | self.unmanaged.orderedRemoveAtContext(index, self.ctx); | |
| 408 | } | |
| 409 | ||
| 410 | /// Create a copy of the hash map which can be modified separately. | |
| 411 | /// The copy uses the same context and allocator as this instance. | |
| 412 | pub fn clone(self: Self) !Self { | |
| 413 | var other = try self.unmanaged.cloneContext(self.allocator, self.ctx); | |
| 414 | return other.promoteContext(self.allocator, self.ctx); | |
| 415 | } | |
| 416 | /// Create a copy of the hash map which can be modified separately. | |
| 417 | /// The copy uses the same context as this instance, but the specified | |
| 418 | /// allocator. | |
| 419 | pub fn cloneWithAllocator(self: Self, allocator: Allocator) !Self { | |
| 420 | var other = try self.unmanaged.cloneContext(allocator, self.ctx); | |
| 421 | return other.promoteContext(allocator, self.ctx); | |
| 422 | } | |
| 423 | /// Create a copy of the hash map which can be modified separately. | |
| 424 | /// The copy uses the same allocator as this instance, but the | |
| 425 | /// specified context. | |
| 426 | pub fn cloneWithContext(self: Self, ctx: anytype) !ArrayHashMap(K, V, @TypeOf(ctx), store_hash) { | |
| 427 | var other = try self.unmanaged.cloneContext(self.allocator, ctx); | |
| 428 | return other.promoteContext(self.allocator, ctx); | |
| 429 | } | |
| 430 | /// Create a copy of the hash map which can be modified separately. | |
| 431 | /// The copy uses the specified allocator and context. | |
| 432 | pub fn cloneWithAllocatorAndContext(self: Self, allocator: Allocator, ctx: anytype) !ArrayHashMap(K, V, @TypeOf(ctx), store_hash) { | |
| 433 | var other = try self.unmanaged.cloneContext(allocator, ctx); | |
| 434 | return other.promoteContext(allocator, ctx); | |
| 435 | } | |
| 436 | ||
| 437 | /// Set the map to an empty state, making deinitialization a no-op, and | |
| 438 | /// returning a copy of the original. | |
| 439 | pub fn move(self: *Self) Self { | |
| 440 | self.unmanaged.pointer_stability.assertUnlocked(); | |
| 441 | const result = self.*; | |
| 442 | self.unmanaged = .empty; | |
| 443 | return result; | |
| 444 | } | |
| 445 | ||
| 446 | /// Recomputes stored hashes and rebuilds the key indexes. If the | |
| 447 | /// underlying keys have been modified directly, call this method to | |
| 448 | /// recompute the denormalized metadata necessary for the operation of | |
| 449 | /// the methods of this map that lookup entries by key. | |
| 450 | /// | |
| 451 | /// One use case for this is directly calling `entries.resize()` to grow | |
| 452 | /// the underlying storage, and then setting the `keys` and `values` | |
| 453 | /// directly without going through the methods of this map. | |
| 454 | /// | |
| 455 | /// The time complexity of this operation is O(n). | |
| 456 | pub fn reIndex(self: *Self) !void { | |
| 457 | return self.unmanaged.reIndexContext(self.allocator, self.ctx); | |
| 458 | } | |
| 459 | ||
| 460 | /// Sorts the entries and then rebuilds the index. | |
| 461 | /// `sort_ctx` must have this method: | |
| 462 | /// `fn lessThan(ctx: @TypeOf(ctx), a_index: usize, b_index: usize) bool` | |
| 463 | /// Uses a stable sorting algorithm. | |
| 464 | pub fn sort(self: *Self, sort_ctx: anytype) void { | |
| 465 | return self.unmanaged.sortContext(sort_ctx, self.ctx); | |
| 466 | } | |
| 467 | ||
| 468 | /// Sorts the entries and then rebuilds the index. | |
| 469 | /// `sort_ctx` must have this method: | |
| 470 | /// `fn lessThan(ctx: @TypeOf(ctx), a_index: usize, b_index: usize) bool` | |
| 471 | /// Uses an unstable sorting algorithm. | |
| 472 | pub fn sortUnstable(self: *Self, sort_ctx: anytype) void { | |
| 473 | return self.unmanaged.sortUnstableContext(sort_ctx, self.ctx); | |
| 474 | } | |
| 475 | ||
| 476 | /// Shrinks the underlying `Entry` array to `new_len` elements and | |
| 477 | /// discards any associated index entries. Keeps capacity the same. | |
| 478 | /// | |
| 479 | /// Asserts the discarded entries remain initialized and capable of | |
| 480 | /// performing hash and equality checks. Any deinitialization of | |
| 481 | /// discarded entries must take place *after* calling this function. | |
| 482 | pub fn shrinkRetainingCapacity(self: *Self, new_len: usize) void { | |
| 483 | return self.unmanaged.shrinkRetainingCapacityContext(new_len, self.ctx); | |
| 484 | } | |
| 485 | ||
| 486 | /// Shrinks the underlying `Entry` array to `new_len` elements and | |
| 487 | /// discards any associated index entries. Reduces allocated capacity. | |
| 488 | /// | |
| 489 | /// Asserts the discarded entries remain initialized and capable of | |
| 490 | /// performing hash and equality checks. It is a bug to call this | |
| 491 | /// function if the discarded entries require deinitialization. For | |
| 492 | /// that use case, `shrinkRetainingCapacity` can be used instead. | |
| 493 | pub fn shrinkAndFree(self: *Self, new_len: usize) void { | |
| 494 | return self.unmanaged.shrinkAndFreeContext(self.allocator, new_len, self.ctx); | |
| 495 | } | |
| 496 | ||
| 497 | /// Removes the last inserted `Entry` in the hash map and returns it if count is nonzero. | |
| 498 | /// Otherwise returns null. | |
| 499 | pub fn pop(self: *Self) ?KV { | |
| 500 | return self.unmanaged.popContext(self.ctx); | |
| 501 | } | |
| 502 | }; | |
| 503 | } | |
| 44 | /// Deprecated; use `Custom`. | |
| 45 | pub const ArrayHashMap = Custom; | |
| 504 | 46 | |
| 505 | 47 | /// A hash table of keys and values, each stored sequentially. |
| 506 | 48 | /// |
| ... | ... | @@ -522,11 +64,11 @@ pub fn ArrayHashMapWithAllocator( |
| 522 | 64 | /// |
| 523 | 65 | /// This type is designed to have low overhead for small numbers of entries. When |
| 524 | 66 | /// `store_hash` is `false` and the number of entries in the map is less than 9, |
| 525 | /// the overhead cost of using `ArrayHashMapUnmanaged` rather than `std.ArrayList` is | |
| 67 | /// the overhead cost of using `ArrayHashMap` rather than `std.ArrayList` is | |
| 526 | 68 | /// only a single pointer-sized integer. |
| 527 | 69 | /// |
| 528 | 70 | /// Default initialization of this struct is deprecated; use `.empty` instead. |
| 529 | pub fn ArrayHashMapUnmanaged( | |
| 71 | pub fn Custom( | |
| 530 | 72 | comptime K: type, |
| 531 | 73 | comptime V: type, |
| 532 | 74 | /// A namespace that provides these two functions: |
| ... | ... | @@ -605,9 +147,6 @@ pub fn ArrayHashMapUnmanaged( |
| 605 | 147 | index: usize, |
| 606 | 148 | }; |
| 607 | 149 | |
| 608 | /// The ArrayHashMap type using the same settings as this managed map. | |
| 609 | pub const Managed = ArrayHashMap(K, V, Context, store_hash); | |
| 610 | ||
| 611 | 150 | /// Some functions require a context only if hashes are not stored. |
| 612 | 151 | /// To keep the api simple, this type is only used internally. |
| 613 | 152 | const ByIndexContext = if (store_hash) void else Context; |
| ... | ... | @@ -626,21 +165,6 @@ pub fn ArrayHashMapUnmanaged( |
| 626 | 165 | |
| 627 | 166 | const Oom = Allocator.Error; |
| 628 | 167 | |
| 629 | /// Convert from an unmanaged map to a managed map. After calling this, | |
| 630 | /// the promoted map should no longer be used. | |
| 631 | pub fn promote(self: Self, gpa: Allocator) Managed { | |
| 632 | if (@sizeOf(Context) != 0) | |
| 633 | @compileError("Cannot infer context " ++ @typeName(Context) ++ ", call promoteContext instead."); | |
| 634 | return self.promoteContext(gpa, undefined); | |
| 635 | } | |
| 636 | pub fn promoteContext(self: Self, gpa: Allocator, ctx: Context) Managed { | |
| 637 | return .{ | |
| 638 | .unmanaged = self, | |
| 639 | .allocator = gpa, | |
| 640 | .ctx = ctx, | |
| 641 | }; | |
| 642 | } | |
| 643 | ||
| 644 | 168 | pub fn init(gpa: Allocator, key_list: []const K, value_list: []const V) Oom!Self { |
| 645 | 169 | var self: Self = .{}; |
| 646 | 170 | errdefer self.deinit(gpa); |
| ... | ... | @@ -2189,35 +1713,37 @@ const IndexHeader = struct { |
| 2189 | 1713 | }; |
| 2190 | 1714 | |
| 2191 | 1715 | test "basic hash map usage" { |
| 2192 | var map = AutoArrayHashMap(i32, i32).init(std.testing.allocator); | |
| 2193 | defer map.deinit(); | |
| 1716 | const gpa = testing.allocator; | |
| 2194 | 1717 | |
| 2195 | try testing.expect((try map.fetchPut(1, 11)) == null); | |
| 2196 | try testing.expect((try map.fetchPut(2, 22)) == null); | |
| 2197 | try testing.expect((try map.fetchPut(3, 33)) == null); | |
| 2198 | try testing.expect((try map.fetchPut(4, 44)) == null); | |
| 1718 | var map: Auto(i32, i32) = .empty; | |
| 1719 | defer map.deinit(gpa); | |
| 1720 | ||
| 1721 | try testing.expect((try map.fetchPut(gpa, 1, 11)) == null); | |
| 1722 | try testing.expect((try map.fetchPut(gpa, 2, 22)) == null); | |
| 1723 | try testing.expect((try map.fetchPut(gpa, 3, 33)) == null); | |
| 1724 | try testing.expect((try map.fetchPut(gpa, 4, 44)) == null); | |
| 2199 | 1725 | |
| 2200 | try map.putNoClobber(5, 55); | |
| 2201 | try testing.expect((try map.fetchPut(5, 66)).?.value == 55); | |
| 2202 | try testing.expect((try map.fetchPut(5, 55)).?.value == 66); | |
| 1726 | try map.putNoClobber(gpa, 5, 55); | |
| 1727 | try testing.expect((try map.fetchPut(gpa, 5, 66)).?.value == 55); | |
| 1728 | try testing.expect((try map.fetchPut(gpa, 5, 55)).?.value == 66); | |
| 2203 | 1729 | |
| 2204 | const gop1 = try map.getOrPut(5); | |
| 1730 | const gop1 = try map.getOrPut(gpa, 5); | |
| 2205 | 1731 | try testing.expect(gop1.found_existing == true); |
| 2206 | 1732 | try testing.expect(gop1.value_ptr.* == 55); |
| 2207 | 1733 | try testing.expect(gop1.index == 4); |
| 2208 | 1734 | gop1.value_ptr.* = 77; |
| 2209 | 1735 | try testing.expect(map.getEntry(5).?.value_ptr.* == 77); |
| 2210 | 1736 | |
| 2211 | const gop2 = try map.getOrPut(99); | |
| 1737 | const gop2 = try map.getOrPut(gpa, 99); | |
| 2212 | 1738 | try testing.expect(gop2.found_existing == false); |
| 2213 | 1739 | try testing.expect(gop2.index == 5); |
| 2214 | 1740 | gop2.value_ptr.* = 42; |
| 2215 | 1741 | try testing.expect(map.getEntry(99).?.value_ptr.* == 42); |
| 2216 | 1742 | |
| 2217 | const gop3 = try map.getOrPutValue(5, 5); | |
| 1743 | const gop3 = try map.getOrPutValue(gpa, 5, 5); | |
| 2218 | 1744 | try testing.expect(gop3.value_ptr.* == 77); |
| 2219 | 1745 | |
| 2220 | const gop4 = try map.getOrPutValue(100, 41); | |
| 1746 | const gop4 = try map.getOrPutValue(gpa, 100, 41); | |
| 2221 | 1747 | try testing.expect(gop4.value_ptr.* == 41); |
| 2222 | 1748 | |
| 2223 | 1749 | try testing.expect(map.contains(2)); |
| ... | ... | @@ -2234,7 +1760,7 @@ test "basic hash map usage" { |
| 2234 | 1760 | |
| 2235 | 1761 | // Since we've used `swapRemove` above, the index of this entry should remain unchanged. |
| 2236 | 1762 | try testing.expect(map.getIndex(100).? == 1); |
| 2237 | const gop5 = try map.getOrPut(5); | |
| 1763 | const gop5 = try map.getOrPut(gpa, 5); | |
| 2238 | 1764 | try testing.expect(gop5.found_existing == true); |
| 2239 | 1765 | try testing.expect(gop5.value_ptr.* == 77); |
| 2240 | 1766 | try testing.expect(gop5.index == 4); |
| ... | ... | @@ -2247,7 +1773,7 @@ test "basic hash map usage" { |
| 2247 | 1773 | try testing.expect(map.orderedRemove(100) == false); |
| 2248 | 1774 | try testing.expect(map.getEntry(100) == null); |
| 2249 | 1775 | try testing.expect(map.get(100) == null); |
| 2250 | const gop6 = try map.getOrPut(5); | |
| 1776 | const gop6 = try map.getOrPut(gpa, 5); | |
| 2251 | 1777 | try testing.expect(gop6.found_existing == true); |
| 2252 | 1778 | try testing.expect(gop6.value_ptr.* == 77); |
| 2253 | 1779 | try testing.expect(gop6.index == 3); |
| ... | ... | @@ -2256,15 +1782,17 @@ test "basic hash map usage" { |
| 2256 | 1782 | } |
| 2257 | 1783 | |
| 2258 | 1784 | test "iterator hash map" { |
| 2259 | var reset_map = AutoArrayHashMap(i32, i32).init(std.testing.allocator); | |
| 2260 | defer reset_map.deinit(); | |
| 1785 | const gpa = testing.allocator; | |
| 1786 | ||
| 1787 | var reset_map: Auto(i32, i32) = .empty; | |
| 1788 | defer reset_map.deinit(gpa); | |
| 2261 | 1789 | |
| 2262 | 1790 | // test ensureTotalCapacity with a 0 parameter |
| 2263 | try reset_map.ensureTotalCapacity(0); | |
| 1791 | try reset_map.ensureTotalCapacity(gpa, 0); | |
| 2264 | 1792 | |
| 2265 | try reset_map.putNoClobber(0, 11); | |
| 2266 | try reset_map.putNoClobber(1, 22); | |
| 2267 | try reset_map.putNoClobber(2, 33); | |
| 1793 | try reset_map.putNoClobber(gpa, 0, 11); | |
| 1794 | try reset_map.putNoClobber(gpa, 1, 22); | |
| 1795 | try reset_map.putNoClobber(gpa, 2, 33); | |
| 2268 | 1796 | |
| 2269 | 1797 | const keys = [_]i32{ |
| 2270 | 1798 | 0, 2, 1, |
| ... | ... | @@ -2312,10 +1840,12 @@ test "iterator hash map" { |
| 2312 | 1840 | } |
| 2313 | 1841 | |
| 2314 | 1842 | test "ensure capacity" { |
| 2315 | var map = AutoArrayHashMap(i32, i32).init(std.testing.allocator); | |
| 2316 | defer map.deinit(); | |
| 1843 | const gpa = testing.allocator; | |
| 2317 | 1844 | |
| 2318 | try map.ensureTotalCapacity(20); | |
| 1845 | var map: Auto(i32, i32) = .empty; | |
| 1846 | defer map.deinit(gpa); | |
| 1847 | ||
| 1848 | try map.ensureTotalCapacity(gpa, 20); | |
| 2319 | 1849 | const initial_capacity = map.capacity(); |
| 2320 | 1850 | try testing.expect(initial_capacity >= 20); |
| 2321 | 1851 | var i: i32 = 0; |
| ... | ... | @@ -2329,23 +1859,25 @@ test "ensure capacity" { |
| 2329 | 1859 | test "ensure capacity leak" { |
| 2330 | 1860 | try testing.checkAllAllocationFailures(std.testing.allocator, struct { |
| 2331 | 1861 | pub fn f(allocator: Allocator) !void { |
| 2332 | var map = AutoArrayHashMap(i32, i32).init(allocator); | |
| 2333 | defer map.deinit(); | |
| 1862 | var map: Auto(i32, i32) = .empty; | |
| 1863 | defer map.deinit(allocator); | |
| 2334 | 1864 | |
| 2335 | 1865 | var i: i32 = 0; |
| 2336 | 1866 | // put more than `linear_scan_max` in so index_header gets allocated. |
| 2337 | while (i <= 20) : (i += 1) try map.put(i, i); | |
| 1867 | while (i <= 20) : (i += 1) try map.put(allocator, i, i); | |
| 2338 | 1868 | } |
| 2339 | 1869 | }.f, .{}); |
| 2340 | 1870 | } |
| 2341 | 1871 | |
| 2342 | 1872 | test "big map" { |
| 2343 | var map = AutoArrayHashMap(i32, i32).init(std.testing.allocator); | |
| 2344 | defer map.deinit(); | |
| 1873 | const gpa = testing.allocator; | |
| 1874 | ||
| 1875 | var map: Auto(i32, i32) = .empty; | |
| 1876 | defer map.deinit(gpa); | |
| 2345 | 1877 | |
| 2346 | 1878 | var i: i32 = 0; |
| 2347 | 1879 | while (i < 8) : (i += 1) { |
| 2348 | try map.put(i, i + 10); | |
| 1880 | try map.put(gpa, i, i + 10); | |
| 2349 | 1881 | } |
| 2350 | 1882 | |
| 2351 | 1883 | i = 0; |
| ... | ... | @@ -2358,7 +1890,7 @@ test "big map" { |
| 2358 | 1890 | |
| 2359 | 1891 | i = 4; |
| 2360 | 1892 | while (i < 12) : (i += 1) { |
| 2361 | try map.put(i, i + 12); | |
| 1893 | try map.put(gpa, i, i + 12); | |
| 2362 | 1894 | } |
| 2363 | 1895 | |
| 2364 | 1896 | i = 0; |
| ... | ... | @@ -2393,17 +1925,19 @@ test "big map" { |
| 2393 | 1925 | } |
| 2394 | 1926 | |
| 2395 | 1927 | test "clone" { |
| 2396 | var original = AutoArrayHashMap(i32, i32).init(std.testing.allocator); | |
| 2397 | defer original.deinit(); | |
| 1928 | const gpa = testing.allocator; | |
| 1929 | ||
| 1930 | var original: Auto(i32, i32) = .empty; | |
| 1931 | defer original.deinit(gpa); | |
| 2398 | 1932 | |
| 2399 | 1933 | // put more than `linear_scan_max` so we can test that the index header is properly cloned |
| 2400 | 1934 | var i: u8 = 0; |
| 2401 | 1935 | while (i < 10) : (i += 1) { |
| 2402 | try original.putNoClobber(i, i * 10); | |
| 1936 | try original.putNoClobber(gpa, i, i * 10); | |
| 2403 | 1937 | } |
| 2404 | 1938 | |
| 2405 | var copy = try original.clone(); | |
| 2406 | defer copy.deinit(); | |
| 1939 | var copy = try original.clone(gpa); | |
| 1940 | defer copy.deinit(gpa); | |
| 2407 | 1941 | |
| 2408 | 1942 | i = 0; |
| 2409 | 1943 | while (i < 10) : (i += 1) { |
| ... | ... | @@ -2419,16 +1953,18 @@ test "clone" { |
| 2419 | 1953 | } |
| 2420 | 1954 | |
| 2421 | 1955 | test "shrink" { |
| 2422 | var map = AutoArrayHashMap(i32, i32).init(std.testing.allocator); | |
| 2423 | defer map.deinit(); | |
| 1956 | const gpa = testing.allocator; | |
| 1957 | ||
| 1958 | var map: Auto(i32, i32) = .empty; | |
| 1959 | defer map.deinit(gpa); | |
| 2424 | 1960 | |
| 2425 | 1961 | // This test is more interesting if we insert enough entries to allocate the index header. |
| 2426 | 1962 | const num_entries = 200; |
| 2427 | 1963 | var i: i32 = 0; |
| 2428 | 1964 | while (i < num_entries) : (i += 1) |
| 2429 | try testing.expect((try map.fetchPut(i, i * 10)) == null); | |
| 1965 | try testing.expect((try map.fetchPut(gpa, i, i * 10)) == null); | |
| 2430 | 1966 | |
| 2431 | try testing.expect(map.unmanaged.index_header != null); | |
| 1967 | try testing.expect(map.index_header != null); | |
| 2432 | 1968 | try testing.expect(map.count() == num_entries); |
| 2433 | 1969 | |
| 2434 | 1970 | // Test `shrinkRetainingCapacity`. |
| ... | ... | @@ -2437,7 +1973,7 @@ test "shrink" { |
| 2437 | 1973 | try testing.expect(map.capacity() >= num_entries); |
| 2438 | 1974 | i = 0; |
| 2439 | 1975 | while (i < num_entries) : (i += 1) { |
| 2440 | const gop = try map.getOrPut(i); | |
| 1976 | const gop = try map.getOrPut(gpa, i); | |
| 2441 | 1977 | if (i < 17) { |
| 2442 | 1978 | try testing.expect(gop.found_existing == true); |
| 2443 | 1979 | try testing.expect(gop.value_ptr.* == i * 10); |
| ... | ... | @@ -2445,12 +1981,12 @@ test "shrink" { |
| 2445 | 1981 | } |
| 2446 | 1982 | |
| 2447 | 1983 | // Test `shrinkAndFree`. |
| 2448 | map.shrinkAndFree(15); | |
| 1984 | map.shrinkAndFree(gpa, 15); | |
| 2449 | 1985 | try testing.expect(map.count() == 15); |
| 2450 | 1986 | try testing.expect(map.capacity() == 15); |
| 2451 | 1987 | i = 0; |
| 2452 | 1988 | while (i < num_entries) : (i += 1) { |
| 2453 | const gop = try map.getOrPut(i); | |
| 1989 | const gop = try map.getOrPut(gpa, i); | |
| 2454 | 1990 | if (i < 15) { |
| 2455 | 1991 | try testing.expect(gop.found_existing == true); |
| 2456 | 1992 | try testing.expect(gop.value_ptr.* == i * 10); |
| ... | ... | @@ -2459,15 +1995,17 @@ test "shrink" { |
| 2459 | 1995 | } |
| 2460 | 1996 | |
| 2461 | 1997 | test "pop()" { |
| 2462 | var map = AutoArrayHashMap(i32, i32).init(std.testing.allocator); | |
| 2463 | defer map.deinit(); | |
| 1998 | const gpa = testing.allocator; | |
| 1999 | ||
| 2000 | var map: Auto(i32, i32) = .empty; | |
| 2001 | defer map.deinit(gpa); | |
| 2464 | 2002 | |
| 2465 | 2003 | // Insert just enough entries so that the map expands. Afterwards, |
| 2466 | 2004 | // pop all entries out of the map. |
| 2467 | 2005 | |
| 2468 | 2006 | var i: i32 = 0; |
| 2469 | 2007 | while (i < 9) : (i += 1) { |
| 2470 | try testing.expect((try map.fetchPut(i, i)) == null); | |
| 2008 | try testing.expect((try map.fetchPut(gpa, i, i)) == null); | |
| 2471 | 2009 | } |
| 2472 | 2010 | |
| 2473 | 2011 | while (map.pop()) |pop| { |
| ... | ... | @@ -2479,31 +2017,33 @@ test "pop()" { |
| 2479 | 2017 | } |
| 2480 | 2018 | |
| 2481 | 2019 | test "reIndex" { |
| 2482 | var map = ArrayHashMap(i32, i32, AutoContext(i32), true).init(std.testing.allocator); | |
| 2483 | defer map.deinit(); | |
| 2020 | const gpa = testing.allocator; | |
| 2021 | ||
| 2022 | var map: Custom(i32, i32, AutoContext(i32), true) = .empty; | |
| 2023 | defer map.deinit(gpa); | |
| 2484 | 2024 | |
| 2485 | 2025 | // Populate via the API. |
| 2486 | 2026 | const num_indexed_entries = 200; |
| 2487 | 2027 | var i: i32 = 0; |
| 2488 | 2028 | while (i < num_indexed_entries) : (i += 1) |
| 2489 | try testing.expect((try map.fetchPut(i, i * 10)) == null); | |
| 2029 | try testing.expect((try map.fetchPut(gpa, i, i * 10)) == null); | |
| 2490 | 2030 | |
| 2491 | 2031 | // Make sure we allocated an index header. |
| 2492 | try testing.expect(map.unmanaged.index_header != null); | |
| 2032 | try testing.expect(map.index_header != null); | |
| 2493 | 2033 | |
| 2494 | 2034 | // Now write to the arrays directly. |
| 2495 | 2035 | const num_unindexed_entries = 20; |
| 2496 | try map.unmanaged.entries.resize(std.testing.allocator, num_indexed_entries + num_unindexed_entries); | |
| 2036 | try map.entries.resize(std.testing.allocator, num_indexed_entries + num_unindexed_entries); | |
| 2497 | 2037 | for (map.keys()[num_indexed_entries..], map.values()[num_indexed_entries..], num_indexed_entries..) |*key, *value, j| { |
| 2498 | 2038 | key.* = @intCast(j); |
| 2499 | 2039 | value.* = @intCast(j * 10); |
| 2500 | 2040 | } |
| 2501 | 2041 | |
| 2502 | 2042 | // After reindexing, we should see everything. |
| 2503 | try map.reIndex(); | |
| 2043 | try map.reIndex(gpa); | |
| 2504 | 2044 | i = 0; |
| 2505 | 2045 | while (i < num_indexed_entries + num_unindexed_entries) : (i += 1) { |
| 2506 | const gop = try map.getOrPut(i); | |
| 2046 | const gop = try map.getOrPut(gpa, i); | |
| 2507 | 2047 | try testing.expect(gop.found_existing == true); |
| 2508 | 2048 | try testing.expect(gop.value_ptr.* == i * 10); |
| 2509 | 2049 | try testing.expect(gop.index == i); |
| ... | ... | @@ -2511,23 +2051,20 @@ test "reIndex" { |
| 2511 | 2051 | } |
| 2512 | 2052 | |
| 2513 | 2053 | test "auto store_hash" { |
| 2514 | const HasCheapEql = AutoArrayHashMap(i32, i32); | |
| 2515 | const HasExpensiveEql = AutoArrayHashMap([32]i32, i32); | |
| 2054 | const HasCheapEql = Auto(i32, i32); | |
| 2055 | const HasExpensiveEql = Auto([32]i32, i32); | |
| 2516 | 2056 | try testing.expect(@FieldType(HasCheapEql.Data, "hash") == void); |
| 2517 | 2057 | try testing.expect(@FieldType(HasExpensiveEql.Data, "hash") != void); |
| 2518 | ||
| 2519 | const HasCheapEqlUn = AutoArrayHashMapUnmanaged(i32, i32); | |
| 2520 | const HasExpensiveEqlUn = AutoArrayHashMapUnmanaged([32]i32, i32); | |
| 2521 | try testing.expect(@FieldType(HasCheapEqlUn.Data, "hash") == void); | |
| 2522 | try testing.expect(@FieldType(HasExpensiveEqlUn.Data, "hash") != void); | |
| 2523 | 2058 | } |
| 2524 | 2059 | |
| 2525 | 2060 | test "sort" { |
| 2526 | var map = AutoArrayHashMap(i32, i32).init(std.testing.allocator); | |
| 2527 | defer map.deinit(); | |
| 2061 | const gpa = testing.allocator; | |
| 2062 | ||
| 2063 | var map: Auto(i32, i32) = .empty; | |
| 2064 | defer map.deinit(gpa); | |
| 2528 | 2065 | |
| 2529 | 2066 | for ([_]i32{ 8, 3, 12, 10, 2, 4, 9, 5, 6, 13, 14, 15, 16, 1, 11, 17, 7 }) |x| { |
| 2530 | try map.put(x, x * 3); | |
| 2067 | try map.put(gpa, x, x * 3); | |
| 2531 | 2068 | } |
| 2532 | 2069 | |
| 2533 | 2070 | const C = struct { |
| ... | ... | @@ -2549,15 +2086,17 @@ test "sort" { |
| 2549 | 2086 | } |
| 2550 | 2087 | |
| 2551 | 2088 | test "0 sized key" { |
| 2552 | var map = AutoArrayHashMap(u0, i32).init(std.testing.allocator); | |
| 2553 | defer map.deinit(); | |
| 2089 | const gpa = testing.allocator; | |
| 2090 | ||
| 2091 | var map: Auto(u0, i32) = .empty; | |
| 2092 | defer map.deinit(gpa); | |
| 2554 | 2093 | |
| 2555 | 2094 | try testing.expectEqual(map.get(0), null); |
| 2556 | 2095 | |
| 2557 | try map.put(0, 5); | |
| 2096 | try map.put(gpa, 0, 5); | |
| 2558 | 2097 | try testing.expectEqual(map.get(0), 5); |
| 2559 | 2098 | |
| 2560 | try map.put(0, 10); | |
| 2099 | try map.put(gpa, 0, 10); | |
| 2561 | 2100 | try testing.expectEqual(map.get(0), 10); |
| 2562 | 2101 | |
| 2563 | 2102 | try testing.expectEqual(map.swapRemove(0), true); |
| ... | ... | @@ -2565,12 +2104,14 @@ test "0 sized key" { |
| 2565 | 2104 | } |
| 2566 | 2105 | |
| 2567 | 2106 | test "0 sized key and 0 sized value" { |
| 2568 | var map = AutoArrayHashMap(u0, u0).init(std.testing.allocator); | |
| 2569 | defer map.deinit(); | |
| 2107 | const gpa = testing.allocator; | |
| 2108 | ||
| 2109 | var map: Auto(u0, u0) = .empty; | |
| 2110 | defer map.deinit(gpa); | |
| 2570 | 2111 | |
| 2571 | 2112 | try testing.expectEqual(map.get(0), null); |
| 2572 | 2113 | |
| 2573 | try map.put(0, 0); | |
| 2114 | try map.put(gpa, 0, 0); | |
| 2574 | 2115 | try testing.expectEqual(map.get(0), 0); |
| 2575 | 2116 | |
| 2576 | 2117 | try testing.expectEqual(map.swapRemove(0), true); |
| ... | ... | @@ -2580,7 +2121,7 @@ test "0 sized key and 0 sized value" { |
| 2580 | 2121 | test "setKey storehash true" { |
| 2581 | 2122 | const gpa = std.testing.allocator; |
| 2582 | 2123 | |
| 2583 | var map: ArrayHashMapUnmanaged(i32, i32, AutoContext(i32), true) = .empty; | |
| 2124 | var map: ArrayHashMap(i32, i32, AutoContext(i32), true) = .empty; | |
| 2584 | 2125 | defer map.deinit(gpa); |
| 2585 | 2126 | |
| 2586 | 2127 | try map.put(gpa, 12, 34); |
| ... | ... | @@ -2596,7 +2137,7 @@ test "setKey storehash true" { |
| 2596 | 2137 | test "setKey storehash false" { |
| 2597 | 2138 | const gpa = std.testing.allocator; |
| 2598 | 2139 | |
| 2599 | var map: ArrayHashMapUnmanaged(i32, i32, AutoContext(i32), false) = .empty; | |
| 2140 | var map: ArrayHashMap(i32, i32, AutoContext(i32), false) = .empty; | |
| 2600 | 2141 | defer map.deinit(gpa); |
| 2601 | 2142 | |
| 2602 | 2143 | try map.put(gpa, 12, 34); |
| ... | ... | @@ -2691,7 +2232,7 @@ pub fn getAutoHashStratFn(comptime K: type, comptime Context: type, comptime str |
| 2691 | 2232 | test "orderedRemoveAtMany" { |
| 2692 | 2233 | const gpa = testing.allocator; |
| 2693 | 2234 | |
| 2694 | var map: AutoArrayHashMapUnmanaged(usize, void) = .empty; | |
| 2235 | var map: Auto(usize, void) = .empty; | |
| 2695 | 2236 | defer map.deinit(gpa); |
| 2696 | 2237 | |
| 2697 | 2238 | for (0..10) |n| { |
lib/std/json/Stringify.zig+3-3| ... | ... | @@ -770,9 +770,9 @@ fn testBasicWriteStream(w: *Stringify) !void { |
| 770 | 770 | } |
| 771 | 771 | |
| 772 | 772 | fn getJsonObject(allocator: std.mem.Allocator) !std.json.Value { |
| 773 | var v: std.json.Value = .{ .object = std.json.ObjectMap.init(allocator) }; | |
| 774 | try v.object.put("one", std.json.Value{ .integer = @as(i64, @intCast(1)) }); | |
| 775 | try v.object.put("two", std.json.Value{ .float = 2.0 }); | |
| 773 | var v: std.json.Value = .{ .object = .empty }; | |
| 774 | try v.object.put(allocator, "one", std.json.Value{ .integer = @as(i64, @intCast(1)) }); | |
| 775 | try v.object.put(allocator, "two", std.json.Value{ .float = 2.0 }); | |
| 776 | 776 | return v; |
| 777 | 777 | } |
| 778 | 778 |
lib/std/json/dynamic.zig+4-4| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | const debug = std.debug; |
| 3 | 3 | const ArenaAllocator = std.heap.ArenaAllocator; |
| 4 | const StringArrayHashMap = std.StringArrayHashMap; | |
| 4 | const StringArrayHashMap = std.array_hash_map.String; | |
| 5 | 5 | const Allocator = std.mem.Allocator; |
| 6 | 6 | const json = std.json; |
| 7 | 7 | |
| ... | ... | @@ -103,10 +103,10 @@ pub const Value = union(enum) { |
| 103 | 103 | |
| 104 | 104 | .object_begin => { |
| 105 | 105 | switch (try source.nextAllocMax(allocator, .alloc_always, options.max_value_len.?)) { |
| 106 | .object_end => return try handleCompleteValue(&stack, allocator, source, Value{ .object = ObjectMap.init(allocator) }, options) orelse continue, | |
| 106 | .object_end => return try handleCompleteValue(&stack, allocator, source, Value{ .object = .empty }, options) orelse continue, | |
| 107 | 107 | .allocated_string => |key| { |
| 108 | 108 | try stack.appendSlice(&[_]Value{ |
| 109 | Value{ .object = ObjectMap.init(allocator) }, | |
| 109 | Value{ .object = .empty }, | |
| 110 | 110 | Value{ .string = key }, |
| 111 | 111 | }); |
| 112 | 112 | }, |
| ... | ... | @@ -145,7 +145,7 @@ fn handleCompleteValue(stack: *Array, allocator: Allocator, source: anytype, val |
| 145 | 145 | // stack: [..., .object] |
| 146 | 146 | var object = &stack.items[stack.items.len - 1].object; |
| 147 | 147 | |
| 148 | const gop = try object.getOrPut(key); | |
| 148 | const gop = try object.getOrPut(allocator, key); | |
| 149 | 149 | if (gop.found_existing) { |
| 150 | 150 | switch (options.duplicate_field_behavior) { |
| 151 | 151 | .use_first => {}, |
lib/std/json/dynamic_test.zig+4-3| ... | ... | @@ -220,14 +220,15 @@ test "Value with duplicate fields" { |
| 220 | 220 | } |
| 221 | 221 | |
| 222 | 222 | test "Value.jsonStringify" { |
| 223 | const gpa = testing.allocator; | |
| 223 | 224 | var vals = [_]Value{ |
| 224 | 225 | .{ .integer = 1 }, |
| 225 | 226 | .{ .integer = 2 }, |
| 226 | 227 | .{ .number_string = "3" }, |
| 227 | 228 | }; |
| 228 | var obj = ObjectMap.init(testing.allocator); | |
| 229 | defer obj.deinit(); | |
| 230 | try obj.putNoClobber("a", .{ .string = "b" }); | |
| 229 | var obj: ObjectMap = .empty; | |
| 230 | defer obj.deinit(gpa); | |
| 231 | try obj.putNoClobber(gpa, "a", .{ .string = "b" }); | |
| 231 | 232 | const array = [_]Value{ |
| 232 | 233 | .null, |
| 233 | 234 | .{ .bool = true }, |
lib/std/std.zig+7-6| ... | ... | @@ -1,7 +1,3 @@ |
| 1 | pub const ArrayHashMap = array_hash_map.ArrayHashMap; | |
| 2 | pub const ArrayHashMapUnmanaged = array_hash_map.ArrayHashMapUnmanaged; | |
| 3 | pub const AutoArrayHashMap = array_hash_map.AutoArrayHashMap; | |
| 4 | pub const AutoArrayHashMapUnmanaged = array_hash_map.AutoArrayHashMapUnmanaged; | |
| 5 | 1 | pub const AutoHashMap = hash_map.AutoHashMap; |
| 6 | 2 | pub const AutoHashMapUnmanaged = hash_map.AutoHashMapUnmanaged; |
| 7 | 3 | pub const BitStack = @import("BitStack.zig"); |
| ... | ... | @@ -31,14 +27,19 @@ pub const SinglyLinkedList = @import("SinglyLinkedList.zig"); |
| 31 | 27 | pub const StaticBitSet = bit_set.StaticBitSet; |
| 32 | 28 | pub const StringHashMap = hash_map.StringHashMap; |
| 33 | 29 | pub const StringHashMapUnmanaged = hash_map.StringHashMapUnmanaged; |
| 34 | pub const StringArrayHashMap = array_hash_map.StringArrayHashMap; | |
| 35 | pub const StringArrayHashMapUnmanaged = array_hash_map.StringArrayHashMapUnmanaged; | |
| 36 | 30 | pub const Target = @import("Target.zig"); |
| 37 | 31 | pub const Thread = @import("Thread.zig"); |
| 38 | 32 | pub const Treap = @import("treap.zig").Treap; |
| 39 | 33 | pub const Tz = tz.Tz; |
| 40 | 34 | pub const Uri = @import("Uri.zig"); |
| 41 | 35 | |
| 36 | /// Deprecated; use `array_hash_map.Custom`. | |
| 37 | pub const ArrayHashMapUnmanaged = array_hash_map.Custom; | |
| 38 | /// Deprecated; use `array_hash_map.Auto`. | |
| 39 | pub const AutoArrayHashMapUnmanaged = array_hash_map.Auto; | |
| 40 | /// Deprecated; use `array_hash_map.String`. | |
| 41 | pub const StringArrayHashMapUnmanaged = array_hash_map.String; | |
| 42 | ||
| 42 | 43 | /// A contiguous, growable list of items in memory. This is a wrapper around a |
| 43 | 44 | /// slice of `T` values. |
| 44 | 45 | /// |
lib/std/zig/AstGen.zig+3-3| ... | ... | @@ -1779,8 +1779,8 @@ fn structInitExpr( |
| 1779 | 1779 | var sfba = std.heap.stackFallback(256, astgen.arena); |
| 1780 | 1780 | const sfba_allocator = sfba.get(); |
| 1781 | 1781 | |
| 1782 | var duplicate_names = std.AutoArrayHashMap(Zir.NullTerminatedString, ArrayList(Ast.TokenIndex)).init(sfba_allocator); | |
| 1783 | try duplicate_names.ensureTotalCapacity(@intCast(struct_init.ast.fields.len)); | |
| 1782 | var duplicate_names: std.array_hash_map.Auto(Zir.NullTerminatedString, ArrayList(Ast.TokenIndex)) = .empty; | |
| 1783 | try duplicate_names.ensureTotalCapacity(sfba_allocator, @intCast(struct_init.ast.fields.len)); | |
| 1784 | 1784 | |
| 1785 | 1785 | // When there aren't errors, use this to avoid a second iteration. |
| 1786 | 1786 | var any_duplicate = false; |
| ... | ... | @@ -1789,7 +1789,7 @@ fn structInitExpr( |
| 1789 | 1789 | const name_token = tree.firstToken(field) - 2; |
| 1790 | 1790 | const name_index = try astgen.identAsString(name_token); |
| 1791 | 1791 | |
| 1792 | const gop = try duplicate_names.getOrPut(name_index); | |
| 1792 | const gop = try duplicate_names.getOrPut(sfba_allocator, name_index); | |
| 1793 | 1793 | |
| 1794 | 1794 | if (gop.found_existing) { |
| 1795 | 1795 | try gop.value_ptr.append(sfba_allocator, name_token); |
src/InternPool.zig+3-3| ... | ... | @@ -10552,7 +10552,7 @@ fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !vo |
| 10552 | 10552 | count: usize = 0, |
| 10553 | 10553 | bytes: usize = 0, |
| 10554 | 10554 | }; |
| 10555 | var counts = std.AutoArrayHashMap(Tag, TagStats).init(arena); | |
| 10555 | var counts: std.array_hash_map.Auto(Tag, TagStats) = .empty; | |
| 10556 | 10556 | for (ip.locals) |*local| { |
| 10557 | 10557 | // Early check for length 0, because `view()` is invalid if capacity is 0 |
| 10558 | 10558 | if (local.mutate.items.len == 0) continue; |
| ... | ... | @@ -10563,7 +10563,7 @@ fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !vo |
| 10563 | 10563 | items.items(.tag)[0..local.mutate.items.len], |
| 10564 | 10564 | items.items(.data)[0..local.mutate.items.len], |
| 10565 | 10565 | ) |tag, data| { |
| 10566 | const gop = try counts.getOrPut(tag); | |
| 10566 | const gop = try counts.getOrPut(arena, tag); | |
| 10567 | 10567 | if (!gop.found_existing) gop.value_ptr.* = .{}; |
| 10568 | 10568 | gop.value_ptr.count += 1; |
| 10569 | 10569 | gop.value_ptr.bytes += 1 + 4 + @as(usize, switch (tag) { |
| ... | ... | @@ -10799,7 +10799,7 @@ fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !vo |
| 10799 | 10799 | } |
| 10800 | 10800 | } |
| 10801 | 10801 | const SortContext = struct { |
| 10802 | map: *std.AutoArrayHashMap(Tag, TagStats), | |
| 10802 | map: *std.array_hash_map.Auto(Tag, TagStats), | |
| 10803 | 10803 | pub fn lessThan(ctx: @This(), a_index: usize, b_index: usize) bool { |
| 10804 | 10804 | const values = ctx.map.values(); |
| 10805 | 10805 | return values[a_index].bytes > values[b_index].bytes; |
src/libs/glibc.zig+3-3| ... | ... | @@ -795,7 +795,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 795 | 795 | // |
| 796 | 796 | // If we don't handle this, we end up writing the default `lgammal` symbol for version 2.33 |
| 797 | 797 | // twice, which causes a "duplicate symbol" assembler error. |
| 798 | var versions_written = std.AutoArrayHashMap(Version, void).init(arena); | |
| 798 | var versions_written: std.array_hash_map.Auto(Version, void) = .empty; | |
| 799 | 799 | |
| 800 | 800 | var inc_reader: Io.Reader = .fixed(metadata.inclusions); |
| 801 | 801 | |
| ... | ... | @@ -859,7 +859,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 859 | 859 | } |
| 860 | 860 | |
| 861 | 861 | versions_written.clearRetainingCapacity(); |
| 862 | try versions_written.ensureTotalCapacity(versions_len); | |
| 862 | try versions_written.ensureTotalCapacity(arena, versions_len); | |
| 863 | 863 | |
| 864 | 864 | { |
| 865 | 865 | var ver_buf_i: u8 = 0; |
| ... | ... | @@ -1035,7 +1035,7 @@ pub fn buildSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) anye |
| 1035 | 1035 | } |
| 1036 | 1036 | |
| 1037 | 1037 | versions_written.clearRetainingCapacity(); |
| 1038 | try versions_written.ensureTotalCapacity(versions_len); | |
| 1038 | try versions_written.ensureTotalCapacity(arena, versions_len); | |
| 1039 | 1039 | |
| 1040 | 1040 | { |
| 1041 | 1041 | var ver_buf_i: u8 = 0; |
src/libs/mingw/implib.zig+3-3| ... | ... | @@ -36,14 +36,14 @@ pub fn writeCoffArchive( |
| 36 | 36 | var long_names: StringTable = .{}; |
| 37 | 37 | defer long_names.deinit(allocator); |
| 38 | 38 | |
| 39 | var symbol_to_member_index = std.StringArrayHashMap(usize).init(allocator); | |
| 40 | defer symbol_to_member_index.deinit(); | |
| 39 | var symbol_to_member_index: std.array_hash_map.String(usize) = .empty; | |
| 40 | defer symbol_to_member_index.deinit(allocator); | |
| 41 | 41 | var string_table_len: usize = 0; |
| 42 | 42 | var num_symbols: usize = 0; |
| 43 | 43 | |
| 44 | 44 | for (members.list.items, 0..) |member, i| { |
| 45 | 45 | for (member.symbol_names_for_import_lib) |symbol_name| { |
| 46 | const gop_result = try symbol_to_member_index.getOrPut(symbol_name); | |
| 46 | const gop_result = try symbol_to_member_index.getOrPut(allocator, symbol_name); | |
| 47 | 47 | // When building the symbol map, ignore duplicate symbol names. |
| 48 | 48 | // This can happen in cases like (using .def file syntax): |
| 49 | 49 | // _foo |
src/libs/musl.zig+6-6| ... | ... | @@ -90,10 +90,10 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro |
| 90 | 90 | // Even a .s file can substitute for a .c file. |
| 91 | 91 | const target = comp.getTarget(); |
| 92 | 92 | const arch_name = std.zig.target.muslArchName(target.cpu.arch, target.abi); |
| 93 | var source_table = std.StringArrayHashMap(Ext).init(comp.gpa); | |
| 94 | defer source_table.deinit(); | |
| 93 | var source_table: std.array_hash_map.String(Ext) = .empty; | |
| 94 | defer source_table.deinit(gpa); | |
| 95 | 95 | |
| 96 | try source_table.ensureTotalCapacity(compat_time32_files.len + src_files.len); | |
| 96 | try source_table.ensureTotalCapacity(gpa, compat_time32_files.len + src_files.len); | |
| 97 | 97 | |
| 98 | 98 | for (src_files) |src_file| { |
| 99 | 99 | try addSrcFile(arena, &source_table, src_file); |
| ... | ... | @@ -107,10 +107,10 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro |
| 107 | 107 | } |
| 108 | 108 | } |
| 109 | 109 | |
| 110 | var c_source_files = std.array_list.Managed(Compilation.CSourceFile).init(comp.gpa); | |
| 110 | var c_source_files = std.array_list.Managed(Compilation.CSourceFile).init(gpa); | |
| 111 | 111 | defer c_source_files.deinit(); |
| 112 | 112 | |
| 113 | var override_path = std.array_list.Managed(u8).init(comp.gpa); | |
| 113 | var override_path = std.array_list.Managed(u8).init(gpa); | |
| 114 | 114 | defer override_path.deinit(); |
| 115 | 115 | |
| 116 | 116 | const s = path.sep_str; |
| ... | ... | @@ -349,7 +349,7 @@ const Ext = enum { |
| 349 | 349 | o3, |
| 350 | 350 | }; |
| 351 | 351 | |
| 352 | fn addSrcFile(arena: Allocator, source_table: *std.StringArrayHashMap(Ext), file_path: []const u8) !void { | |
| 352 | fn addSrcFile(arena: Allocator, source_table: *std.array_hash_map.String(Ext), file_path: []const u8) !void { | |
| 353 | 353 | const ext: Ext = ext: { |
| 354 | 354 | if (mem.endsWith(u8, file_path, ".c")) { |
| 355 | 355 | if (mem.startsWith(u8, file_path, "musl/src/string/") or |
src/link/Elf.zig+8-8| ... | ... | @@ -881,10 +881,10 @@ fn flushInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void { |
| 881 | 881 | self.rela_plt.clearRetainingCapacity(); |
| 882 | 882 | |
| 883 | 883 | if (self.zigObjectPtr()) |zo| { |
| 884 | var undefs: std.AutoArrayHashMap(SymbolResolver.Index, std.array_list.Managed(Ref)) = .init(gpa); | |
| 884 | var undefs: std.array_hash_map.Auto(SymbolResolver.Index, std.array_list.Managed(Ref)) = .empty; | |
| 885 | 885 | defer { |
| 886 | 886 | for (undefs.values()) |*refs| refs.deinit(); |
| 887 | undefs.deinit(); | |
| 887 | undefs.deinit(gpa); | |
| 888 | 888 | } |
| 889 | 889 | |
| 890 | 890 | var has_reloc_errors = false; |
| ... | ... | @@ -1332,10 +1332,10 @@ fn scanRelocs(self: *Elf) !void { |
| 1332 | 1332 | const gpa = self.base.comp.gpa; |
| 1333 | 1333 | const shared_objects = self.shared_objects.values(); |
| 1334 | 1334 | |
| 1335 | var undefs: std.AutoArrayHashMap(SymbolResolver.Index, std.array_list.Managed(Ref)) = .init(gpa); | |
| 1335 | var undefs: std.array_hash_map.Auto(SymbolResolver.Index, std.array_list.Managed(Ref)) = .empty; | |
| 1336 | 1336 | defer { |
| 1337 | 1337 | for (undefs.values()) |*refs| refs.deinit(); |
| 1338 | undefs.deinit(); | |
| 1338 | undefs.deinit(gpa); | |
| 1339 | 1339 | } |
| 1340 | 1340 | |
| 1341 | 1341 | var has_reloc_errors = false; |
| ... | ... | @@ -1748,12 +1748,12 @@ pub fn deleteExport( |
| 1748 | 1748 | fn checkDuplicates(self: *Elf) !void { |
| 1749 | 1749 | const gpa = self.base.comp.gpa; |
| 1750 | 1750 | |
| 1751 | var dupes = std.AutoArrayHashMap(SymbolResolver.Index, std.ArrayList(File.Index)).init(gpa); | |
| 1751 | var dupes: std.array_hash_map.Auto(SymbolResolver.Index, std.ArrayList(File.Index)) = .empty; | |
| 1752 | 1752 | defer { |
| 1753 | 1753 | for (dupes.values()) |*list| { |
| 1754 | 1754 | list.deinit(gpa); |
| 1755 | 1755 | } |
| 1756 | dupes.deinit(); | |
| 1756 | dupes.deinit(gpa); | |
| 1757 | 1757 | } |
| 1758 | 1758 | |
| 1759 | 1759 | if (self.zigObjectPtr()) |zig_object| { |
| ... | ... | @@ -2992,10 +2992,10 @@ fn allocateSpecialPhdrs(self: *Elf) void { |
| 2992 | 2992 | fn writeAtoms(self: *Elf) !void { |
| 2993 | 2993 | const gpa = self.base.comp.gpa; |
| 2994 | 2994 | |
| 2995 | var undefs: std.AutoArrayHashMap(SymbolResolver.Index, std.array_list.Managed(Ref)) = .init(gpa); | |
| 2995 | var undefs: std.array_hash_map.Auto(SymbolResolver.Index, std.array_list.Managed(Ref)) = .empty; | |
| 2996 | 2996 | defer { |
| 2997 | 2997 | for (undefs.values()) |*refs| refs.deinit(); |
| 2998 | undefs.deinit(); | |
| 2998 | undefs.deinit(gpa); | |
| 2999 | 2999 | } |
| 3000 | 3000 | |
| 3001 | 3001 | var buffer: std.Io.Writer.Allocating = .init(gpa); |
src/link/Elf/Atom.zig+1-1| ... | ... | @@ -605,7 +605,7 @@ fn reportUndefined( |
| 605 | 605 | .object => |x| x.symbols_resolver.items[rel.r_sym() - x.first_global.?], |
| 606 | 606 | inline else => |x| x.symbols_resolver.items[rel.r_sym()], |
| 607 | 607 | }; |
| 608 | const gop = try undefs.getOrPut(idx); | |
| 608 | const gop = try undefs.getOrPut(gpa, idx); | |
| 609 | 609 | if (!gop.found_existing) { |
| 610 | 610 | gop.value_ptr.* = std.array_list.Managed(Elf.Ref).init(gpa); |
| 611 | 611 | } |
src/link/Elf/Object.zig+4-2| ... | ... | @@ -753,6 +753,8 @@ pub fn markImportsExports(self: *Object, elf_file: *Elf) void { |
| 753 | 753 | } |
| 754 | 754 | |
| 755 | 755 | pub fn checkDuplicates(self: *Object, dupes: anytype, elf_file: *Elf) error{OutOfMemory}!void { |
| 756 | const gpa = elf_file.base.comp.gpa; | |
| 757 | ||
| 756 | 758 | const first_global = self.first_global orelse return; |
| 757 | 759 | for (0..self.globals().len) |i| { |
| 758 | 760 | const esym_idx = first_global + i; |
| ... | ... | @@ -772,11 +774,11 @@ pub fn checkDuplicates(self: *Object, dupes: anytype, elf_file: *Elf) error{OutO |
| 772 | 774 | if (!atom_ptr.alive) continue; |
| 773 | 775 | } |
| 774 | 776 | |
| 775 | const gop = try dupes.getOrPut(self.symbols_resolver.items[i]); | |
| 777 | const gop = try dupes.getOrPut(gpa, self.symbols_resolver.items[i]); | |
| 776 | 778 | if (!gop.found_existing) { |
| 777 | 779 | gop.value_ptr.* = .empty; |
| 778 | 780 | } |
| 779 | try gop.value_ptr.append(elf_file.base.comp.gpa, self.index); | |
| 781 | try gop.value_ptr.append(gpa, self.index); | |
| 780 | 782 | } |
| 781 | 783 | } |
| 782 | 784 |
src/link/Elf/ZigObject.zig+3-1| ... | ... | @@ -710,6 +710,8 @@ pub fn markImportsExports(self: *ZigObject, elf_file: *Elf) void { |
| 710 | 710 | } |
| 711 | 711 | |
| 712 | 712 | pub fn checkDuplicates(self: *ZigObject, dupes: anytype, elf_file: *Elf) error{OutOfMemory}!void { |
| 713 | const gpa = elf_file.base.comp.gpa; | |
| 714 | ||
| 713 | 715 | for (self.global_symbols.items, 0..) |index, i| { |
| 714 | 716 | const esym = self.symtab.items(.elf_sym)[index]; |
| 715 | 717 | const shndx = self.symtab.items(.shndx)[index]; |
| ... | ... | @@ -727,7 +729,7 @@ pub fn checkDuplicates(self: *ZigObject, dupes: anytype, elf_file: *Elf) error{O |
| 727 | 729 | if (!atom_ptr.alive) continue; |
| 728 | 730 | } |
| 729 | 731 | |
| 730 | const gop = try dupes.getOrPut(self.symbols_resolver.items[i]); | |
| 732 | const gop = try dupes.getOrPut(gpa, self.symbols_resolver.items[i]); | |
| 731 | 733 | if (!gop.found_existing) { |
| 732 | 734 | gop.value_ptr.* = .empty; |
| 733 | 735 | } |
src/link/MachO/InternalObject.zig+6-6| ... | ... | @@ -164,8 +164,8 @@ pub fn resolveBoundarySymbols(self: *InternalObject, macho_file: *MachO) !void { |
| 164 | 164 | defer tracy.end(); |
| 165 | 165 | |
| 166 | 166 | const gpa = macho_file.base.comp.gpa; |
| 167 | var boundary_symbols = std.StringArrayHashMap(MachO.Ref).init(gpa); | |
| 168 | defer boundary_symbols.deinit(); | |
| 167 | var boundary_symbols: std.array_hash_map.String(MachO.Ref) = .empty; | |
| 168 | defer boundary_symbols.deinit(gpa); | |
| 169 | 169 | |
| 170 | 170 | for (macho_file.objects.items) |index| { |
| 171 | 171 | const object = macho_file.getFile(index).?.object; |
| ... | ... | @@ -180,7 +180,7 @@ pub fn resolveBoundarySymbols(self: *InternalObject, macho_file: *MachO) !void { |
| 180 | 180 | mem.startsWith(u8, name, "section$start$") or |
| 181 | 181 | mem.startsWith(u8, name, "section$end$")) |
| 182 | 182 | { |
| 183 | const gop = try boundary_symbols.getOrPut(name); | |
| 183 | const gop = try boundary_symbols.getOrPut(gpa, name); | |
| 184 | 184 | if (!gop.found_existing) { |
| 185 | 185 | gop.value_ptr.* = .{ .index = @intCast(i), .file = index }; |
| 186 | 186 | } |
| ... | ... | @@ -344,8 +344,8 @@ pub fn resolveObjcMsgSendSymbols(self: *InternalObject, macho_file: *MachO) !voi |
| 344 | 344 | |
| 345 | 345 | const gpa = macho_file.base.comp.gpa; |
| 346 | 346 | |
| 347 | var objc_msgsend_syms = std.StringArrayHashMap(MachO.Ref).init(gpa); | |
| 348 | defer objc_msgsend_syms.deinit(); | |
| 347 | var objc_msgsend_syms: std.array_hash_map.String(MachO.Ref) = .empty; | |
| 348 | defer objc_msgsend_syms.deinit(gpa); | |
| 349 | 349 | |
| 350 | 350 | for (macho_file.objects.items) |index| { |
| 351 | 351 | const object = macho_file.getFile(index).?.object; |
| ... | ... | @@ -360,7 +360,7 @@ pub fn resolveObjcMsgSendSymbols(self: *InternalObject, macho_file: *MachO) !voi |
| 360 | 360 | |
| 361 | 361 | const name = sym.getName(macho_file); |
| 362 | 362 | if (mem.startsWith(u8, name, "_objc_msgSend$")) { |
| 363 | const gop = try objc_msgsend_syms.getOrPut(name); | |
| 363 | const gop = try objc_msgsend_syms.getOrPut(gpa, name); | |
| 364 | 364 | if (!gop.found_existing) { |
| 365 | 365 | gop.value_ptr.* = .{ .index = @intCast(i), .file = index }; |
| 366 | 366 | } |
src/link/MachO/Object.zig+5-5| ... | ... | @@ -1292,8 +1292,8 @@ fn parseUnwindRecords(self: *Object, allocator: Allocator, cpu_arch: std.Target. |
| 1292 | 1292 | |
| 1293 | 1293 | const Superposition = struct { atom: Atom.Index, size: u64, cu: ?UnwindInfo.Record.Index = null, fde: ?Fde.Index = null }; |
| 1294 | 1294 | |
| 1295 | var superposition = std.AutoArrayHashMap(u64, Superposition).init(allocator); | |
| 1296 | defer superposition.deinit(); | |
| 1295 | var superposition: std.array_hash_map.Auto(u64, Superposition) = .empty; | |
| 1296 | defer superposition.deinit(allocator); | |
| 1297 | 1297 | |
| 1298 | 1298 | const slice = self.symtab.slice(); |
| 1299 | 1299 | for (slice.items(.nlist), slice.items(.atom), slice.items(.size)) |nlist, atom, size| { |
| ... | ... | @@ -1301,7 +1301,7 @@ fn parseUnwindRecords(self: *Object, allocator: Allocator, cpu_arch: std.Target. |
| 1301 | 1301 | if (nlist.n_type.bits.type != .sect) continue; |
| 1302 | 1302 | const sect = self.sections.items(.header)[nlist.n_sect - 1]; |
| 1303 | 1303 | if (sect.isCode() and sect.size > 0) { |
| 1304 | try superposition.ensureUnusedCapacity(1); | |
| 1304 | try superposition.ensureUnusedCapacity(allocator, 1); | |
| 1305 | 1305 | const gop = superposition.getOrPutAssumeCapacity(nlist.n_value); |
| 1306 | 1306 | if (gop.found_existing) { |
| 1307 | 1307 | assert(gop.value_ptr.atom == atom and gop.value_ptr.size == size); |
| ... | ... | @@ -1315,7 +1315,7 @@ fn parseUnwindRecords(self: *Object, allocator: Allocator, cpu_arch: std.Target. |
| 1315 | 1315 | const atom = rec.getAtom(macho_file); |
| 1316 | 1316 | const addr = atom.getInputAddress(macho_file) + rec.atom_offset; |
| 1317 | 1317 | |
| 1318 | try superposition.ensureUnusedCapacity(1); | |
| 1318 | try superposition.ensureUnusedCapacity(allocator, 1); | |
| 1319 | 1319 | const gop = superposition.getOrPutAssumeCapacity(addr); |
| 1320 | 1320 | if (!gop.found_existing) { |
| 1321 | 1321 | gop.value_ptr.* = .{ .atom = rec.atom, .size = rec.length }; |
| ... | ... | @@ -1331,7 +1331,7 @@ fn parseUnwindRecords(self: *Object, allocator: Allocator, cpu_arch: std.Target. |
| 1331 | 1331 | const atom = fde.getAtom(macho_file); |
| 1332 | 1332 | const addr = atom.getInputAddress(macho_file) + fde.atom_offset; |
| 1333 | 1333 | |
| 1334 | try superposition.ensureUnusedCapacity(1); | |
| 1334 | try superposition.ensureUnusedCapacity(allocator, 1); | |
| 1335 | 1335 | const gop = superposition.getOrPutAssumeCapacity(addr); |
| 1336 | 1336 | if (!gop.found_existing) { |
| 1337 | 1337 | gop.value_ptr.* = .{ .atom = fde.atom, .size = fde.pc_range }; |
src/link/MachO/UnwindInfo.zig+4-4| ... | ... | @@ -173,18 +173,18 @@ pub fn generate(info: *UnwindInfo, macho_file: *MachO) !void { |
| 173 | 173 | } |
| 174 | 174 | }; |
| 175 | 175 | |
| 176 | var common_encodings_counts = std.ArrayHashMap( | |
| 176 | var common_encodings_counts: std.array_hash_map.Custom( | |
| 177 | 177 | Encoding, |
| 178 | 178 | CommonEncWithCount, |
| 179 | 179 | Context, |
| 180 | 180 | false, |
| 181 | ).init(gpa); | |
| 182 | defer common_encodings_counts.deinit(); | |
| 181 | ) = .empty; | |
| 182 | defer common_encodings_counts.deinit(gpa); | |
| 183 | 183 | |
| 184 | 184 | for (info.records.items) |ref| { |
| 185 | 185 | const rec = ref.getUnwindRecord(macho_file); |
| 186 | 186 | if (rec.enc.isDwarf(macho_file)) continue; |
| 187 | const gop = try common_encodings_counts.getOrPut(rec.enc); | |
| 187 | const gop = try common_encodings_counts.getOrPut(gpa, rec.enc); | |
| 188 | 188 | if (!gop.found_existing) { |
| 189 | 189 | gop.value_ptr.* = .{ |
| 190 | 190 | .enc = rec.enc, |
src/link/SpirV/lower_invocation_globals.zig+28-27| ... | ... | @@ -67,17 +67,17 @@ const ModuleInfo = struct { |
| 67 | 67 | parser: *BinaryModule.Parser, |
| 68 | 68 | binary: BinaryModule, |
| 69 | 69 | ) BinaryModule.ParseError!ModuleInfo { |
| 70 | var entry_points = std.AutoArrayHashMap(ResultId, void).init(arena); | |
| 71 | var functions = std.AutoArrayHashMap(ResultId, Fn).init(arena); | |
| 70 | var entry_points: std.array_hash_map.Auto(ResultId, void) = .empty; | |
| 71 | var functions: std.array_hash_map.Auto(ResultId, Fn) = .empty; | |
| 72 | 72 | var fn_types = std.AutoHashMap(ResultId, struct { |
| 73 | 73 | return_type: ResultId, |
| 74 | 74 | param_types: []const ResultId, |
| 75 | 75 | }).init(arena); |
| 76 | var calls = std.AutoArrayHashMap(ResultId, void).init(arena); | |
| 76 | var calls: std.array_hash_map.Auto(ResultId, void) = .empty; | |
| 77 | 77 | var callee_store = std.array_list.Managed(ResultId).init(arena); |
| 78 | var function_invocation_globals = std.AutoArrayHashMap(ResultId, void).init(arena); | |
| 78 | var function_invocation_globals: std.array_hash_map.Auto(ResultId, void) = .empty; | |
| 79 | 79 | var result_id_offsets = std.array_list.Managed(u16).init(arena); |
| 80 | var invocation_globals = std.AutoArrayHashMap(ResultId, InvocationGlobal).init(arena); | |
| 80 | var invocation_globals: std.array_hash_map.Auto(ResultId, InvocationGlobal) = .empty; | |
| 81 | 81 | |
| 82 | 82 | var maybe_current_function: ?ResultId = null; |
| 83 | 83 | var fn_ty_id: ResultId = undefined; |
| ... | ... | @@ -90,7 +90,7 @@ const ModuleInfo = struct { |
| 90 | 90 | switch (inst.opcode) { |
| 91 | 91 | .OpEntryPoint => { |
| 92 | 92 | const entry_point: ResultId = @enumFromInt(inst.operands[1]); |
| 93 | const entry = try entry_points.getOrPut(entry_point); | |
| 93 | const entry = try entry_points.getOrPut(arena, entry_point); | |
| 94 | 94 | if (entry.found_existing) { |
| 95 | 95 | log.err("Entry point type {f} has duplicate definition", .{entry_point}); |
| 96 | 96 | return error.DuplicateId; |
| ... | ... | @@ -126,7 +126,7 @@ const ModuleInfo = struct { |
| 126 | 126 | else |
| 127 | 127 | .none; |
| 128 | 128 | |
| 129 | try invocation_globals.put(result_id, .{ | |
| 129 | try invocation_globals.put(arena, result_id, .{ | |
| 130 | 130 | .dependencies = .{}, |
| 131 | 131 | .ty = global_type, |
| 132 | 132 | .initializer = initializer, |
| ... | ... | @@ -145,14 +145,14 @@ const ModuleInfo = struct { |
| 145 | 145 | }, |
| 146 | 146 | .OpFunctionCall => { |
| 147 | 147 | const callee: ResultId = @enumFromInt(inst.operands[2]); |
| 148 | try calls.put(callee, {}); | |
| 148 | try calls.put(arena, callee, {}); | |
| 149 | 149 | }, |
| 150 | 150 | .OpFunctionEnd => { |
| 151 | 151 | const current_function = maybe_current_function orelse { |
| 152 | 152 | log.err("encountered OpFunctionEnd without corresponding OpFunction", .{}); |
| 153 | 153 | return error.InvalidPhysicalFormat; |
| 154 | 154 | }; |
| 155 | const entry = try functions.getOrPut(current_function); | |
| 155 | const entry = try functions.getOrPut(arena, current_function); | |
| 156 | 156 | if (entry.found_existing) { |
| 157 | 157 | log.err("Function {f} has duplicate definition", .{current_function}); |
| 158 | 158 | return error.DuplicateId; |
| ... | ... | @@ -170,7 +170,7 @@ const ModuleInfo = struct { |
| 170 | 170 | .first_callee = first_callee, |
| 171 | 171 | .return_type = fn_type.return_type, |
| 172 | 172 | .param_types = fn_type.param_types, |
| 173 | .invocation_globals = try function_invocation_globals.unmanaged.clone(arena), | |
| 173 | .invocation_globals = try function_invocation_globals.clone(arena), | |
| 174 | 174 | }; |
| 175 | 175 | maybe_current_function = null; |
| 176 | 176 | calls.clearRetainingCapacity(); |
| ... | ... | @@ -181,7 +181,7 @@ const ModuleInfo = struct { |
| 181 | 181 | for (result_id_offsets.items) |off| { |
| 182 | 182 | const result_id: ResultId = @enumFromInt(inst.operands[off]); |
| 183 | 183 | if (invocation_globals.contains(result_id)) { |
| 184 | try function_invocation_globals.put(result_id, {}); | |
| 184 | try function_invocation_globals.put(arena, result_id, {}); | |
| 185 | 185 | } |
| 186 | 186 | } |
| 187 | 187 | } |
| ... | ... | @@ -191,11 +191,11 @@ const ModuleInfo = struct { |
| 191 | 191 | return error.InvalidPhysicalFormat; |
| 192 | 192 | } |
| 193 | 193 | |
| 194 | return ModuleInfo{ | |
| 195 | .functions = functions.unmanaged, | |
| 196 | .entry_points = entry_points.unmanaged, | |
| 194 | return .{ | |
| 195 | .functions = functions, | |
| 196 | .entry_points = entry_points, | |
| 197 | 197 | .callee_store = callee_store.items, |
| 198 | .invocation_globals = invocation_globals.unmanaged, | |
| 198 | .invocation_globals = invocation_globals, | |
| 199 | 199 | }; |
| 200 | 200 | } |
| 201 | 201 | |
| ... | ... | @@ -583,7 +583,8 @@ const ModuleBuilder = struct { |
| 583 | 583 | } |
| 584 | 584 | |
| 585 | 585 | fn emitNewEntryPoints(self: *ModuleBuilder, info: ModuleInfo) !void { |
| 586 | var all_function_invocation_globals = std.AutoArrayHashMap(ResultId, void).init(self.arena); | |
| 586 | const arena = self.arena; | |
| 587 | var all_function_invocation_globals: std.array_hash_map.Auto(ResultId, void) = .empty; | |
| 587 | 588 | |
| 588 | 589 | for (info.entry_points.keys(), 0..) |func, entry_point_index| { |
| 589 | 590 | const fn_info = info.functions.get(func).?; |
| ... | ... | @@ -593,7 +594,7 @@ const ModuleBuilder = struct { |
| 593 | 594 | .param_types = fn_info.param_types, |
| 594 | 595 | }).?; |
| 595 | 596 | |
| 596 | try self.section.emit(self.arena, .OpFunction, .{ | |
| 597 | try self.section.emit(arena, .OpFunction, .{ | |
| 597 | 598 | .id_result_type = fn_info.return_type, |
| 598 | 599 | .id_result = ep_id, |
| 599 | 600 | .function_control = .{}, // TODO: Copy the attributes from the original function maybe? |
| ... | ... | @@ -604,13 +605,13 @@ const ModuleBuilder = struct { |
| 604 | 605 | const params_id_base: u32 = @intFromEnum(self.allocIds(@intCast(fn_info.param_types.len))); |
| 605 | 606 | for (fn_info.param_types, 0..) |param_type, i| { |
| 606 | 607 | const id: ResultId = @enumFromInt(params_id_base + @as(u32, @intCast(i))); |
| 607 | try self.section.emit(self.arena, .OpFunctionParameter, .{ | |
| 608 | try self.section.emit(arena, .OpFunctionParameter, .{ | |
| 608 | 609 | .id_result_type = param_type, |
| 609 | 610 | .id_result = id, |
| 610 | 611 | }); |
| 611 | 612 | } |
| 612 | 613 | |
| 613 | try self.section.emit(self.arena, .OpLabel, .{ | |
| 614 | try self.section.emit(arena, .OpLabel, .{ | |
| 614 | 615 | .id_result = self.allocId(), |
| 615 | 616 | }); |
| 616 | 617 | |
| ... | ... | @@ -619,10 +620,10 @@ const ModuleBuilder = struct { |
| 619 | 620 | // Just quickly construct that set here. |
| 620 | 621 | all_function_invocation_globals.clearRetainingCapacity(); |
| 621 | 622 | for (fn_info.invocation_globals.keys()) |global| { |
| 622 | try all_function_invocation_globals.put(global, {}); | |
| 623 | try all_function_invocation_globals.put(arena, global, {}); | |
| 623 | 624 | const global_info = info.invocation_globals.get(global).?; |
| 624 | 625 | for (global_info.dependencies.keys()) |dependency| { |
| 625 | try all_function_invocation_globals.put(dependency, {}); | |
| 626 | try all_function_invocation_globals.put(arena, dependency, {}); | |
| 626 | 627 | } |
| 627 | 628 | } |
| 628 | 629 | |
| ... | ... | @@ -632,7 +633,7 @@ const ModuleBuilder = struct { |
| 632 | 633 | const global_info = info.invocation_globals.get(global).?; |
| 633 | 634 | |
| 634 | 635 | const id: ResultId = @enumFromInt(global_id_base + @as(u32, @intCast(i))); |
| 635 | try self.section.emit(self.arena, .OpVariable, .{ | |
| 636 | try self.section.emit(arena, .OpVariable, .{ | |
| 636 | 637 | .id_result_type = global_info.ty, |
| 637 | 638 | .id_result = id, |
| 638 | 639 | .storage_class = .function, |
| ... | ... | @@ -649,7 +650,7 @@ const ModuleBuilder = struct { |
| 649 | 650 | assert(initializer_info.param_types.len == 0); |
| 650 | 651 | |
| 651 | 652 | try self.callWithGlobalsAndLinearParams( |
| 652 | all_function_invocation_globals, | |
| 653 | &all_function_invocation_globals, | |
| 653 | 654 | global_info.initializer, |
| 654 | 655 | initializer_info, |
| 655 | 656 | global_id_base, |
| ... | ... | @@ -659,21 +660,21 @@ const ModuleBuilder = struct { |
| 659 | 660 | |
| 660 | 661 | // Call the main kernel entry |
| 661 | 662 | try self.callWithGlobalsAndLinearParams( |
| 662 | all_function_invocation_globals, | |
| 663 | &all_function_invocation_globals, | |
| 663 | 664 | func, |
| 664 | 665 | fn_info, |
| 665 | 666 | global_id_base, |
| 666 | 667 | params_id_base, |
| 667 | 668 | ); |
| 668 | 669 | |
| 669 | try self.section.emit(self.arena, .OpReturn, {}); | |
| 670 | try self.section.emit(self.arena, .OpFunctionEnd, {}); | |
| 670 | try self.section.emit(arena, .OpReturn, {}); | |
| 671 | try self.section.emit(arena, .OpFunctionEnd, {}); | |
| 671 | 672 | } |
| 672 | 673 | } |
| 673 | 674 | |
| 674 | 675 | fn callWithGlobalsAndLinearParams( |
| 675 | 676 | self: *ModuleBuilder, |
| 676 | all_globals: std.AutoArrayHashMap(ResultId, void), | |
| 677 | all_globals: *const std.array_hash_map.Auto(ResultId, void), | |
| 677 | 678 | func: ResultId, |
| 678 | 679 | callee_info: ModuleInfo.Fn, |
| 679 | 680 | global_id_base: u32, |
src/link/Wasm.zig+3-3| ... | ... | @@ -3088,11 +3088,11 @@ fn parseArchive(wasm: *Wasm, obj: link.Input.Object) !void { |
| 3088 | 3088 | // In this case we must force link all embedded object files within the archive |
| 3089 | 3089 | // We loop over all symbols, and then group them by offset as the offset |
| 3090 | 3090 | // notates where the object file starts. |
| 3091 | var offsets = std.AutoArrayHashMap(u32, void).init(gpa); | |
| 3092 | defer offsets.deinit(); | |
| 3091 | var offsets: std.array_hash_map.Auto(u32, void) = .empty; | |
| 3092 | defer offsets.deinit(gpa); | |
| 3093 | 3093 | for (archive.toc.values()) |symbol_offsets| { |
| 3094 | 3094 | for (symbol_offsets.items) |sym_offset| { |
| 3095 | try offsets.put(sym_offset, {}); | |
| 3095 | try offsets.put(gpa, sym_offset, {}); | |
| 3096 | 3096 | } |
| 3097 | 3097 | } |
| 3098 | 3098 |
tools/gen_spirv_spec.zig+11-11| ... | ... | @@ -44,7 +44,7 @@ const StringPairContext = struct { |
| 44 | 44 | } |
| 45 | 45 | }; |
| 46 | 46 | |
| 47 | const OperandKindMap = std.ArrayHashMap(StringPair, OperandKind, StringPairContext, true); | |
| 47 | const OperandKindMap = std.array_hash_map.Custom(StringPair, OperandKind, StringPairContext, true); | |
| 48 | 48 | |
| 49 | 49 | /// Khronos made it so that these names are not defined explicitly, so |
| 50 | 50 | /// we need to hardcode it (like they did). |
| ... | ... | @@ -295,9 +295,9 @@ fn render( |
| 295 | 295 | ); |
| 296 | 296 | |
| 297 | 297 | // Merge the operand kinds from all extensions together. |
| 298 | var all_operand_kinds = OperandKindMap.init(arena); | |
| 298 | var all_operand_kinds: OperandKindMap = .empty; | |
| 299 | 299 | for (registry.operand_kinds) |kind| { |
| 300 | try all_operand_kinds.putNoClobber(.{ "core", kind.kind }, kind); | |
| 300 | try all_operand_kinds.putNoClobber(arena, .{ "core", kind.kind }, kind); | |
| 301 | 301 | } |
| 302 | 302 | for (extensions) |ext| { |
| 303 | 303 | // Note: extensions may define the same operand kind, with different |
| ... | ... | @@ -305,11 +305,11 @@ fn render( |
| 305 | 305 | // using the name of the extension. This is similar to what |
| 306 | 306 | // the official headers do. |
| 307 | 307 | |
| 308 | try all_operand_kinds.ensureUnusedCapacity(ext.spec.operand_kinds.len); | |
| 308 | try all_operand_kinds.ensureUnusedCapacity(arena, ext.spec.operand_kinds.len); | |
| 309 | 309 | for (ext.spec.operand_kinds) |kind| { |
| 310 | 310 | var new_kind = kind; |
| 311 | 311 | new_kind.kind = try std.mem.join(arena, ".", &.{ ext.name, kind.kind }); |
| 312 | try all_operand_kinds.putNoClobber(.{ ext.name, kind.kind }, new_kind); | |
| 312 | try all_operand_kinds.putNoClobber(arena, .{ ext.name, kind.kind }, new_kind); | |
| 313 | 313 | } |
| 314 | 314 | } |
| 315 | 315 | |
| ... | ... | @@ -411,11 +411,11 @@ fn renderInstructionsCase( |
| 411 | 411 | } |
| 412 | 412 | |
| 413 | 413 | fn renderClass(arena: Allocator, writer: *std.Io.Writer, instructions: []const Instruction) !void { |
| 414 | var class_map = std.StringArrayHashMap(void).init(arena); | |
| 414 | var class_map: std.array_hash_map.String(void) = .empty; | |
| 415 | 415 | |
| 416 | 416 | for (instructions) |inst| { |
| 417 | 417 | if (std.mem.eql(u8, inst.class.?, "@exclude")) continue; |
| 418 | try class_map.put(inst.class.?, {}); | |
| 418 | try class_map.put(arena, inst.class.?, {}); | |
| 419 | 419 | } |
| 420 | 420 | |
| 421 | 421 | try writer.writeAll("pub const Class = enum {\n"); |
| ... | ... | @@ -538,8 +538,8 @@ fn renderOpcodes( |
| 538 | 538 | instructions: []const Instruction, |
| 539 | 539 | extended_structs: ExtendedStructSet, |
| 540 | 540 | ) !void { |
| 541 | var inst_map = std.AutoArrayHashMap(u32, usize).init(arena); | |
| 542 | try inst_map.ensureTotalCapacity(instructions.len); | |
| 541 | var inst_map: std.array_hash_map.Auto(u32, usize) = .empty; | |
| 542 | try inst_map.ensureTotalCapacity(arena, instructions.len); | |
| 543 | 543 | |
| 544 | 544 | var aliases = std.array_list.Managed(struct { inst: usize, alias: usize }).init(arena); |
| 545 | 545 | try aliases.ensureTotalCapacity(instructions.len); |
| ... | ... | @@ -653,8 +653,8 @@ fn renderValueEnum( |
| 653 | 653 | ) !void { |
| 654 | 654 | const enumerants = enumeration.enumerants orelse return error.InvalidRegistry; |
| 655 | 655 | |
| 656 | var enum_map = std.AutoArrayHashMap(u32, usize).init(arena); | |
| 657 | try enum_map.ensureTotalCapacity(enumerants.len); | |
| 656 | var enum_map: std.array_hash_map.Auto(u32, usize) = .empty; | |
| 657 | try enum_map.ensureTotalCapacity(arena, enumerants.len); | |
| 658 | 658 | |
| 659 | 659 | var aliases = std.array_list.Managed(struct { enumerant: usize, alias: usize }).init(arena); |
| 660 | 660 | try aliases.ensureTotalCapacity(enumerants.len); |
tools/gen_stubs.zig+10-14| ... | ... | @@ -274,8 +274,8 @@ const MultiSym = struct { |
| 274 | 274 | |
| 275 | 275 | const Parse = struct { |
| 276 | 276 | arena: mem.Allocator, |
| 277 | sym_table: *std.StringArrayHashMap(MultiSym), | |
| 278 | sections: *std.StringArrayHashMap(void), | |
| 277 | sym_table: *std.array_hash_map.String(MultiSym), | |
| 278 | sections: *std.array_hash_map.String(void), | |
| 279 | 279 | elf_bytes: []align(@alignOf(elf.Elf64_Ehdr)) u8, |
| 280 | 280 | header: elf.Header, |
| 281 | 281 | arch: Arch, |
| ... | ... | @@ -289,13 +289,11 @@ pub fn main(init: std.process.Init) !void { |
| 289 | 289 | |
| 290 | 290 | var build_all_dir = try Io.Dir.cwd().openDir(io, build_all_path, .{}); |
| 291 | 291 | |
| 292 | var sym_table = std.StringArrayHashMap(MultiSym).init(arena); | |
| 293 | var sections = std.StringArrayHashMap(void).init(arena); | |
| 292 | var sym_table: std.array_hash_map.String(MultiSym) = .empty; | |
| 293 | var sections: std.array_hash_map.String(void) = .empty; | |
| 294 | 294 | |
| 295 | 295 | for (arches) |arch| { |
| 296 | const libc_so_path = try std.fmt.allocPrint(arena, "{s}/lib/libc.so", .{ | |
| 297 | @tagName(arch), | |
| 298 | }); | |
| 296 | const libc_so_path = try std.fmt.allocPrint(arena, "{t}/lib/libc.so", .{arch}); | |
| 299 | 297 | |
| 300 | 298 | // Read the ELF header. |
| 301 | 299 | const elf_bytes = build_all_dir.readFileAllocOptions( |
| ... | ... | @@ -306,9 +304,7 @@ pub fn main(init: std.process.Init) !void { |
| 306 | 304 | .of(elf.Elf64_Ehdr), |
| 307 | 305 | null, |
| 308 | 306 | ) catch |err| { |
| 309 | std.debug.panic("unable to read '{s}/{s}': {s}", .{ | |
| 310 | build_all_path, libc_so_path, @errorName(err), | |
| 311 | }); | |
| 307 | std.debug.panic("unable to read '{s}/{s}': {t}", .{ build_all_path, libc_so_path, err }); | |
| 312 | 308 | }; |
| 313 | 309 | var stream: std.Io.Reader = .fixed(elf_bytes); |
| 314 | 310 | const header = try elf.Header.read(&stream); |
| ... | ... | @@ -359,8 +355,8 @@ pub fn main(init: std.process.Init) !void { |
| 359 | 355 | |
| 360 | 356 | // Sort the symbols for deterministic output and cleaner vcs diffs. |
| 361 | 357 | const SymTableSort = struct { |
| 362 | sections: *const std.StringArrayHashMap(void), | |
| 363 | sym_table: *const std.StringArrayHashMap(MultiSym), | |
| 358 | sections: *const std.array_hash_map.String(void), | |
| 359 | sym_table: *const std.array_hash_map.String(MultiSym), | |
| 364 | 360 | |
| 365 | 361 | /// Sort first by section name, then by symbol name |
| 366 | 362 | pub fn lessThan(ctx: @This(), index_a: usize, index_b: usize) bool { |
| ... | ... | @@ -580,7 +576,7 @@ fn parseElf(parse: Parse, comptime is_64: bool, comptime endian: std.builtin.End |
| 580 | 576 | if (mem.eql(u8, sh_name, ".dynsym")) { |
| 581 | 577 | dynsym_index = @as(u16, @intCast(i)); |
| 582 | 578 | } |
| 583 | const gop = try parse.sections.getOrPut(sh_name); | |
| 579 | const gop = try parse.sections.getOrPut(arena, sh_name); | |
| 584 | 580 | section_index_map[i] = @as(u16, @intCast(gop.index)); |
| 585 | 581 | } |
| 586 | 582 | if (dynsym_index == 0) @panic("did not find the .dynsym section"); |
| ... | ... | @@ -653,7 +649,7 @@ fn parseElf(parse: Parse, comptime is_64: bool, comptime endian: std.builtin.End |
| 653 | 649 | }, |
| 654 | 650 | } |
| 655 | 651 | |
| 656 | const gop = try parse.sym_table.getOrPut(name); | |
| 652 | const gop = try parse.sym_table.getOrPut(arena, name); | |
| 657 | 653 | if (gop.found_existing) { |
| 658 | 654 | if (gop.value_ptr.section != section_index_map[this_section]) { |
| 659 | 655 | const sh_name = mem.sliceTo(shstrtab[s(shdrs[this_section].sh_name)..], 0); |
tools/process_headers.zig+4-4| ... | ... | @@ -130,7 +130,7 @@ const Contents = struct { |
| 130 | 130 | }; |
| 131 | 131 | |
| 132 | 132 | const HashToContents = std.StringHashMap(Contents); |
| 133 | const TargetToHash = std.StringArrayHashMap([]const u8); | |
| 133 | const TargetToHash = std.array_hash_map.String([]const u8); | |
| 134 | 134 | const PathTable = std.StringHashMap(*TargetToHash); |
| 135 | 135 | |
| 136 | 136 | const LibCVendor = enum { |
| ... | ... | @@ -317,7 +317,7 @@ pub fn main(init: std.process.Init) !void { |
| 317 | 317 | const path_gop = try path_table.getOrPut(rel_path); |
| 318 | 318 | const target_to_hash = if (path_gop.found_existing) path_gop.value_ptr.* else blk: { |
| 319 | 319 | const ptr = try arena.create(TargetToHash); |
| 320 | ptr.* = TargetToHash.init(arena); | |
| 320 | ptr.* = .empty; | |
| 321 | 321 | path_gop.value_ptr.* = ptr; |
| 322 | 322 | break :blk ptr; |
| 323 | 323 | }; |
| ... | ... | @@ -327,14 +327,14 @@ pub fn main(init: std.process.Init) !void { |
| 327 | 327 | // such cases, we manually patch the affected header after processing, so it's fine that |
| 328 | 328 | // only one header wins here. |
| 329 | 329 | if (libc_target.dest != null) { |
| 330 | const hash_gop = try target_to_hash.getOrPut(dest_target); | |
| 330 | const hash_gop = try target_to_hash.getOrPut(arena, dest_target); | |
| 331 | 331 | if (hash_gop.found_existing) std.debug.print("overwrote: {s} {s} {s}\n", .{ |
| 332 | 332 | libc_dir, |
| 333 | 333 | rel_path, |
| 334 | 334 | dest_target, |
| 335 | 335 | }) else hash_gop.value_ptr.* = hash; |
| 336 | 336 | } else { |
| 337 | try target_to_hash.putNoClobber(dest_target, hash); | |
| 337 | try target_to_hash.putNoClobber(arena, dest_target, hash); | |
| 338 | 338 | } |
| 339 | 339 | }, |
| 340 | 340 | else => std.debug.print("warning: weird file: {s}\n", .{full_path}), |
tools/update-linux-headers.zig+3-3| ... | ... | @@ -138,7 +138,7 @@ const Contents = struct { |
| 138 | 138 | }; |
| 139 | 139 | |
| 140 | 140 | const HashToContents = std.StringHashMap(Contents); |
| 141 | const TargetToHash = std.ArrayHashMap(DestTarget, []const u8, DestTarget.HashContext, true); | |
| 141 | const TargetToHash = std.array_hash_map.Custom(DestTarget, []const u8, DestTarget.HashContext, true); | |
| 142 | 142 | const PathTable = std.StringHashMap(*TargetToHash); |
| 143 | 143 | |
| 144 | 144 | pub fn main(init: std.process.Init) !void { |
| ... | ... | @@ -239,11 +239,11 @@ pub fn main(init: std.process.Init) !void { |
| 239 | 239 | const path_gop = try path_table.getOrPut(rel_path); |
| 240 | 240 | const target_to_hash = if (path_gop.found_existing) path_gop.value_ptr.* else blk: { |
| 241 | 241 | const ptr = try arena.create(TargetToHash); |
| 242 | ptr.* = TargetToHash.init(arena); | |
| 242 | ptr.* = .empty; | |
| 243 | 243 | path_gop.value_ptr.* = ptr; |
| 244 | 244 | break :blk ptr; |
| 245 | 245 | }; |
| 246 | try target_to_hash.putNoClobber(dest_target, hash); | |
| 246 | try target_to_hash.putNoClobber(arena, dest_target, hash); | |
| 247 | 247 | }, |
| 248 | 248 | else => std.debug.print("warning: weird file: {s}\n", .{full_path}), |
| 249 | 249 | } |