diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2023-04-18 17:11:27 +0200 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2023-04-21 22:44:27 +0200 |
| commit | 8e3100ae02fef20ce08a679f6212b3d673a5c8f0 (patch) | |
| tree | 899bb927fc750896681134079364610c4843ed20 /src/link/table_section.zig | |
| parent | 8a3ad3f6204747b5621e14cae0564ee7929a7cd8 (diff) | |
| download | zig-8e3100ae02fef20ce08a679f6212b3d673a5c8f0.tar.gz zig-8e3100ae02fef20ce08a679f6212b3d673a5c8f0.zip | |
elf: make TableSection a generic construct
Diffstat (limited to 'src/link/table_section.zig')
| -rw-r--r-- | src/link/table_section.zig | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/src/link/table_section.zig b/src/link/table_section.zig new file mode 100644 index 0000000000..4d5838adb9 --- /dev/null +++ b/src/link/table_section.zig @@ -0,0 +1,65 @@ +pub fn TableSection(comptime Entry: type) type { + return struct { + entries: std.ArrayListUnmanaged(Entry) = .{}, + free_list: std.ArrayListUnmanaged(Index) = .{}, + lookup: std.AutoHashMapUnmanaged(Entry, Index) = .{}, + + pub fn deinit(self: *Self, allocator: Allocator) void { + self.entries.deinit(allocator); + self.free_list.deinit(allocator); + self.lookup.deinit(allocator); + } + + pub fn allocateEntry(self: *Self, allocator: Allocator, entry: Entry) Allocator.Error!Index { + try self.entries.ensureUnusedCapacity(allocator, 1); + const index = blk: { + if (self.free_list.popOrNull()) |index| { + log.debug(" (reusing entry index {d})", .{index}); + break :blk index; + } else { + log.debug(" (allocating entry at index {d})", .{self.entries.items.len}); + const index = @intCast(u32, self.entries.items.len); + _ = self.entries.addOneAssumeCapacity(); + break :blk index; + } + }; + self.entries.items[index] = entry; + try self.lookup.putNoClobber(allocator, entry, index); + return index; + } + + pub fn freeEntry(self: *Self, allocator: Allocator, entry: Entry) void { + const index = self.lookup.get(entry) orelse return; + self.free_list.append(allocator, index) catch {}; + self.entries.items[index] = undefined; + _ = self.lookup.remove(entry); + } + + pub fn count(self: Self) usize { + return self.entries.items.len; + } + + pub fn format( + self: Self, + comptime unused_format_string: []const u8, + options: std.fmt.FormatOptions, + writer: anytype, + ) !void { + _ = options; + comptime assert(unused_format_string.len == 0); + try writer.writeAll("SectionTable:\n"); + for (self.entries.items, 0..) |entry, i| { + try writer.print(" {d} => {}\n", .{ i, entry }); + } + } + + const Self = @This(); + pub const Index = u32; + }; +} + +const std = @import("std"); +const assert = std.debug.assert; +const log = std.log.scoped(.link); + +const Allocator = std.mem.Allocator; |
