Lookup tables!
This commit is contained in:
+1
-1
@@ -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,
|
||||||
|
|||||||
@@ -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];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user