Lookup tables!

This commit is contained in:
Caleb J. Gardner
2026-04-04 01:37:36 -05:00
parent d0787a5200
commit e07f11d195
3 changed files with 91 additions and 4 deletions
+1 -1
View File
@@ -2,8 +2,8 @@ const std = @import("std");
const DecompTypes = @import("decomp/types.zig"); const DecompTypes = @import("decomp/types.zig");
const Decompressor = @import("decomp.zig"); const Decompressor = @import("decomp.zig");
const Inode = @import("inode.zig");
const ExtractionOptions = @import("options.zig"); const ExtractionOptions = @import("options.zig");
const Inode = @import("inode.zig");
pub const Error = error{ pub const Error = error{
BadMagic, BadMagic,
+87
View File
@@ -0,0 +1,87 @@
const std = @import("std");
const Decompressor = @import("decomp.zig");
const MetadataReader = @import("util/metadata.zig");
const OffsetFile = @import("util/offset_file.zig");
pub fn stateless(comptime T: anytype, fil: OffsetFile, decomp: *const Decompressor, table_start: u64, idx: u32) !T {
const VALS_PER_BLOCK = 8192 / @sizeOf(T);
const block = idx / VALS_PER_BLOCK;
const block_idx = idx % VALS_PER_BLOCK;
const offset = try fil.valueAt(u64, table_start + (8 * block));
var buf: [8192]u8 = undefined;
var rdr = try fil.readerAt(offset, &buf);
var meta_rdr: MetadataReader = .init(&rdr.interface, decomp);
try meta_rdr.interface.discardAll(@sizeOf(T) * block_idx);
var out: T = undefined;
try meta_rdr.interface.readSliceEndian(T, @ptrCast(&out), .little);
return out;
}
pub fn Table(comptime T: anytype) type {
return struct {
const Self = @This();
const VALS_PER_BLOCK = 8192 / @sizeOf(T);
alloc: std.mem.Allocator,
decomp: *const Decompressor,
fil: OffsetFile,
table_start: u64,
num: u32,
cache: std.AutoHashMap(u32, []T),
cache_mut: std.Thread.Mutex = .{},
pub fn init(alloc: std.mem.Allocator, decomp: *const Decompressor, fil: OffsetFile, table_offset: u64, num: u32) !Self {
return .{
.alloc = alloc,
.decomp = decomp,
.fil = fil,
.table_start = table_offset,
.num = num,
.cache = .init(alloc),
};
}
pub fn deinit(self: *Self) void {
var values = self.cache.valueIterator();
while (values.next()) |val|
self.alloc.free(val);
self.cache.deinit();
}
pub fn get(self: *Self, idx: u32) !T {
const block = idx / VALS_PER_BLOCK;
const block_idx = idx % VALS_PER_BLOCK;
if (self.cache.get(block)) |val|
return val[block_idx];
self.cache_mut.lock();
defer self.cache_mut.unlock();
// Double check in case another thread was doing your work.
if (self.cache.get(block)) |val|
return val[block_idx];
const offset = try self.fil.valueAt(u64, self.table_start + (8 * block));
var buf: [8192]u8 = undefined;
var rdr = try self.fil.readerAt(offset, &buf);
var meta_rdr: MetadataReader = .init(&rdr.interface, self.decomp);
const block_size = if (block == (self.num - 1) / VALS_PER_BLOCK)
self.num % VALS_PER_BLOCK
else
VALS_PER_BLOCK;
const new_block = try self.alloc.alloc(T, block_size);
errdefer self.alloc.free(new_block);
try meta_rdr.interface.readSliceEndian(T, new_block, .little);
try self.cache.put(block, new_block);
return new_block[block_idx];
}
};
}
+2 -2
View File
@@ -13,7 +13,7 @@ const Header = packed struct {
const MetadataReader = @This(); const MetadataReader = @This();
rdr: *Reader, rdr: *Reader,
decomp: *Decompressor, decomp: *const Decompressor,
read_buf: [8192]u8 = undefined, read_buf: [8192]u8 = undefined,
interface: Reader = .{ interface: Reader = .{
@@ -27,7 +27,7 @@ interface: Reader = .{
}, },
}, },
pub fn init(rdr: *Reader, decomp: *Decompressor) MetadataReader { pub fn init(rdr: *Reader, decomp: *const Decompressor) MetadataReader {
return .{ .rdr = rdr, .decomp = decomp }; return .{ .rdr = rdr, .decomp = decomp };
} }
fn advanceBuffer(self: *MetadataReader) Reader.Error!void { fn advanceBuffer(self: *MetadataReader) Reader.Error!void {