Several fixes for File.extract
Tweaks and fixes.
This commit is contained in:
+50
-24
@@ -1,6 +1,7 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const io = std.io;
|
const io = std.io;
|
||||||
const fs = std.fs;
|
const fs = std.fs;
|
||||||
|
const builtin = @import("builtin");
|
||||||
|
|
||||||
const inode = @import("inode/inode.zig");
|
const inode = @import("inode/inode.zig");
|
||||||
const directory = @import("directory.zig");
|
const directory = @import("directory.zig");
|
||||||
@@ -36,16 +37,17 @@ pub const File = struct {
|
|||||||
);
|
);
|
||||||
defer meta_rdr.deinit();
|
defer meta_rdr.deinit();
|
||||||
try meta_rdr.skip(ent.offset);
|
try meta_rdr.skip(ent.offset);
|
||||||
const out: File = .{
|
const name = try rdr.alloc.alloc(u8, ent.name.len);
|
||||||
.name = try rdr.alloc.alloc(u8, ent.name.len),
|
errdefer rdr.alloc.free(name);
|
||||||
|
@memcpy(name, ent.name);
|
||||||
|
return .{
|
||||||
|
.name = name,
|
||||||
.inode = try .init(
|
.inode = try .init(
|
||||||
rdr.alloc,
|
rdr.alloc,
|
||||||
meta_rdr.any(),
|
meta_rdr.any(),
|
||||||
rdr.super.block_size,
|
rdr.super.block_size,
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
@memcpy(out.name, ent.name);
|
|
||||||
return out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *File, alloc: std.mem.Allocator) void {
|
pub fn deinit(self: *File, alloc: std.mem.Allocator) void {
|
||||||
@@ -159,7 +161,7 @@ pub const File = struct {
|
|||||||
return self.data_rdr.?.read(bytes);
|
return self.data_rdr.?.read(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const FileReader = io.GenericReader(*File, (FileError || anyerror), read);
|
const FileReader = io.GenericReader(*File, (FileError || anyerror), read);
|
||||||
|
|
||||||
pub fn reader(self: *File) FileReader {
|
pub fn reader(self: *File) FileReader {
|
||||||
return .{
|
return .{
|
||||||
@@ -199,30 +201,54 @@ pub const File = struct {
|
|||||||
}
|
}
|
||||||
var iter = try self.iterator(rdr);
|
var iter = try self.iterator(rdr);
|
||||||
defer iter.deinit();
|
defer iter.deinit();
|
||||||
while (iter.next()) |f| {
|
while (iter.next()) |*f| {
|
||||||
//TODO: Threading
|
const extr_path = try std.mem.concat(rdr.alloc, u8, &[3][]const u8{ real_path, "/", f.name });
|
||||||
try f.extractReal(rdr, path + "/" + f.name, false);
|
defer rdr.alloc.free(extr_path);
|
||||||
|
try @constCast(f).extractReal(rdr, extr_path, false);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.file, .ext_file => {
|
.file, .ext_file => {
|
||||||
if (exists) {
|
if ((!first and exists) or
|
||||||
if (!first) {
|
(first and exists and stat.?.kind != .directory)) return ExtractError.FileExists;
|
||||||
return ExtractError.FileExists;
|
const extr_path = if (first and exists and stat.?.kind == .directory) blk: {
|
||||||
} else {
|
break :blk try std.mem.concat(rdr.alloc, u8, &[3][]const u8{ real_path, "/", self.name });
|
||||||
if (stat.?.kind == .directory) {
|
} else blk: {
|
||||||
real_path += "/" + self.name;
|
const tmp = try rdr.alloc.alloc(u8, real_path.len);
|
||||||
} else {
|
@memcpy(tmp, real_path);
|
||||||
return ExtractError.FileExists;
|
break :blk tmp;
|
||||||
}
|
};
|
||||||
}
|
defer rdr.alloc.free(extr_path);
|
||||||
}
|
var ext = try self.extractor(rdr);
|
||||||
const ext = try self.extractor(rdr);
|
|
||||||
defer ext.deinit();
|
defer ext.deinit();
|
||||||
const fil = try fs.cwd().createFile(real_path, .{});
|
const fil = try fs.cwd().createFile(extr_path, .{});
|
||||||
try ext.writeToFile(fil);
|
defer fil.close();
|
||||||
|
try ext.writeToFile(try .init(), &fil);
|
||||||
},
|
},
|
||||||
.sym, .ext_sym => {},
|
.sym, .ext_sym => {
|
||||||
.block, .ext_block, .char, .ext_char => {},
|
if (exists) return ExtractError.FileExists;
|
||||||
|
try fs.cwd().symLink(try self.symPath(), real_path, .{});
|
||||||
|
},
|
||||||
|
.block, .ext_block, .char, .ext_char, .fifo, .ext_fifo => {
|
||||||
|
if (exists) return ExtractError.FileExists;
|
||||||
|
comptime if (builtin.os.tag != .linux) return;
|
||||||
|
const IFCHR: u32 = 0o020000;
|
||||||
|
const IFBLK: u32 = 0o060000;
|
||||||
|
const IFIFO: u32 = 0o010000;
|
||||||
|
const mode = switch (self.inode.header.inode_type) {
|
||||||
|
.block, .ext_block => IFBLK,
|
||||||
|
.char, .ext_char => IFCHR,
|
||||||
|
.fifo, .ext_fifo => IFIFO,
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
|
const dev = switch (self.inode.data) {
|
||||||
|
.block, .char => |b| b.device,
|
||||||
|
.ext_block, .ext_char => |b| b.device,
|
||||||
|
.fifo, .ext_fifo => 0,
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
|
_ = std.os.linux.mknod(@ptrCast(real_path), mode, dev);
|
||||||
|
},
|
||||||
|
.sock, .ext_sock => {},
|
||||||
}
|
}
|
||||||
//TODO: permissions
|
//TODO: permissions
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -15,7 +15,7 @@ pub const FileInode = struct {
|
|||||||
blocks: []const BlockSize,
|
blocks: []const BlockSize,
|
||||||
|
|
||||||
pub fn init(alloc: std.mem.Allocator, rdr: io.AnyReader, block_size: u32) !FileInode {
|
pub fn init(alloc: std.mem.Allocator, rdr: io.AnyReader, block_size: u32) !FileInode {
|
||||||
const fixed_buf = [16]u8{};
|
var fixed_buf = [1]u8{0} ** 16;
|
||||||
_ = try rdr.readAll(&fixed_buf);
|
_ = try rdr.readAll(&fixed_buf);
|
||||||
const frag_idx = std.mem.bytesToValue(u32, fixed_buf[4..8]);
|
const frag_idx = std.mem.bytesToValue(u32, fixed_buf[4..8]);
|
||||||
const size = std.mem.bytesToValue(u32, fixed_buf[12..16]);
|
const size = std.mem.bytesToValue(u32, fixed_buf[12..16]);
|
||||||
@@ -49,7 +49,7 @@ pub const ExtFileInode = struct {
|
|||||||
blocks: []const BlockSize,
|
blocks: []const BlockSize,
|
||||||
|
|
||||||
pub fn init(alloc: std.mem.Allocator, rdr: io.AnyReader, block_size: u32) !ExtFileInode {
|
pub fn init(alloc: std.mem.Allocator, rdr: io.AnyReader, block_size: u32) !ExtFileInode {
|
||||||
var fixed_buf = [40]u8{};
|
var fixed_buf = [1]u8{0} ** 40;
|
||||||
_ = try rdr.readAll(&fixed_buf);
|
_ = try rdr.readAll(&fixed_buf);
|
||||||
const size = std.mem.bytesToValue(u64, fixed_buf[8..16]);
|
const size = std.mem.bytesToValue(u64, fixed_buf[8..16]);
|
||||||
const frag_idx = std.mem.bytesToValue(u32, fixed_buf[28..32]);
|
const frag_idx = std.mem.bytesToValue(u32, fixed_buf[28..32]);
|
||||||
|
|||||||
+9
-2
@@ -80,8 +80,6 @@ pub const Reader = struct {
|
|||||||
|
|
||||||
test "root iter" {
|
test "root iter" {
|
||||||
const test_sfs_path = "testing/LinuxPATest.sfs";
|
const test_sfs_path = "testing/LinuxPATest.sfs";
|
||||||
// const test_file_path = "PortableApps/PortableApps.com/Data/PortableAppsMenu.ini";
|
|
||||||
|
|
||||||
var rdr: Reader = try .init(std.testing.allocator, test_sfs_path, 0);
|
var rdr: Reader = try .init(std.testing.allocator, test_sfs_path, 0);
|
||||||
defer rdr.deinit();
|
defer rdr.deinit();
|
||||||
var rootIter = try rdr.root.iterator(&rdr);
|
var rootIter = try rdr.root.iterator(&rdr);
|
||||||
@@ -90,3 +88,12 @@ test "root iter" {
|
|||||||
std.debug.print("{s}\n", .{f.name});
|
std.debug.print("{s}\n", .{f.name});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "extract" {
|
||||||
|
const test_sfs_path = "testing/LinuxPATest.sfs";
|
||||||
|
const extract_path = "testing/testExtract";
|
||||||
|
try std.fs.cwd().deleteTree(extract_path);
|
||||||
|
var rdr: Reader = try .init(std.testing.allocator, test_sfs_path, 0);
|
||||||
|
defer rdr.deinit();
|
||||||
|
try rdr.root.extract(&rdr, extract_path);
|
||||||
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ pub const DataExtractor = struct {
|
|||||||
max_mem: u64,
|
max_mem: u64,
|
||||||
pub fn init() !Config {
|
pub fn init() !Config {
|
||||||
return .{
|
return .{
|
||||||
.thread_count = try std.Thread.getCpuCount(),
|
.thread_count = @truncate(try std.Thread.getCpuCount()),
|
||||||
.max_mem = comptime 1024 * 1024 * 1024,
|
.max_mem = comptime 1024 * 1024 * 1024,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -42,17 +42,17 @@ pub const DataExtractor = struct {
|
|||||||
var frag_offset: u32 = 0;
|
var frag_offset: u32 = 0;
|
||||||
switch (fil.inode.data) {
|
switch (fil.inode.data) {
|
||||||
.file => |f| {
|
.file => |f| {
|
||||||
|
data_start = f.data_start;
|
||||||
sizes = try reader.alloc.alloc(BlockSize, f.blocks.len);
|
sizes = try reader.alloc.alloc(BlockSize, f.blocks.len);
|
||||||
@memcpy(sizes, f.blocks);
|
@memcpy(sizes, f.blocks);
|
||||||
data_start = f.data_start;
|
|
||||||
size = f.size;
|
size = f.size;
|
||||||
frag_idx = f.frag_idx;
|
frag_idx = f.frag_idx;
|
||||||
frag_offset = f.frag_offset;
|
frag_offset = f.frag_offset;
|
||||||
},
|
},
|
||||||
.ext_file => |f| {
|
.ext_file => |f| {
|
||||||
|
data_start = f.data_start;
|
||||||
sizes = try reader.alloc.alloc(BlockSize, f.blocks.len);
|
sizes = try reader.alloc.alloc(BlockSize, f.blocks.len);
|
||||||
@memcpy(sizes, f.blocks);
|
@memcpy(sizes, f.blocks);
|
||||||
data_start = f.data_start;
|
|
||||||
size = f.size;
|
size = f.size;
|
||||||
frag_idx = f.frag_idx;
|
frag_idx = f.frag_idx;
|
||||||
frag_offset = f.frag_offset;
|
frag_offset = f.frag_offset;
|
||||||
@@ -62,25 +62,25 @@ pub const DataExtractor = struct {
|
|||||||
var out: DataExtractor = .{
|
var out: DataExtractor = .{
|
||||||
.alloc = reader.alloc,
|
.alloc = reader.alloc,
|
||||||
.decomp = reader.super.decomp,
|
.decomp = reader.super.decomp,
|
||||||
.holder = reader.holder,
|
.holder = &reader.holder,
|
||||||
.block_size = reader.super.block_size,
|
.block_size = reader.super.block_size,
|
||||||
.sizes = sizes,
|
.sizes = sizes,
|
||||||
.block_offset = try reader.alloc.alloc(u64, sizes.len),
|
.block_offset = try reader.alloc.alloc(u64, sizes.len),
|
||||||
.data_start = data_start,
|
|
||||||
};
|
};
|
||||||
errdefer out.deinit();
|
errdefer out.deinit();
|
||||||
var offset: u64 = data_start;
|
var offset: u64 = data_start;
|
||||||
for (0..out.block_offset) |i| {
|
for (0.., out.block_offset) |i, _| {
|
||||||
out.block_offset[i] = offset;
|
out.block_offset[i] = offset;
|
||||||
offset += out.sizes[i].size;
|
offset += out.sizes[i].size;
|
||||||
}
|
}
|
||||||
if (frag_idx != 0xFFFFFFFF) {
|
if (frag_idx != 0xFFFFFFFF) {
|
||||||
const frag_entry = try reader.frag_table.getValue(frag_idx);
|
const frag_entry = try reader.frag_table.getValue(reader, frag_idx);
|
||||||
var frag_rdr: DataReader = try .fromFragEntry(reader, frag_entry);
|
var frag_rdr: DataReader = try .fromFragEntry(reader, frag_entry);
|
||||||
|
std.debug.print("{} {}\n", .{ frag_offset, frag_entry });
|
||||||
defer frag_rdr.deinit();
|
defer frag_rdr.deinit();
|
||||||
try frag_rdr.skip(frag_offset);
|
try frag_rdr.skip(frag_offset);
|
||||||
out.frag_data = try reader.alloc.alloc(u8, size % out.block_size);
|
out.frag_data = try reader.alloc.alloc(u8, size % out.block_size);
|
||||||
_ = try frag_rdr.any().readAll(out.frag_data);
|
_ = try frag_rdr.any().readAll(out.frag_data.?);
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@@ -88,8 +88,7 @@ pub const DataExtractor = struct {
|
|||||||
pub fn deinit(self: *DataExtractor) void {
|
pub fn deinit(self: *DataExtractor) void {
|
||||||
self.alloc.free(self.sizes);
|
self.alloc.free(self.sizes);
|
||||||
self.alloc.free(self.block_offset);
|
self.alloc.free(self.block_offset);
|
||||||
if (self.cur_bloc.len > 0) self.alloc.free(self.cur_bloc);
|
if (self.frag_data != null) self.alloc.free(self.frag_data.?);
|
||||||
if (self.frag_data != null) self.alloc.free(self.frag_data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn processBlock(self: DataExtractor, block_ind: u32) ![]u8 {
|
fn processBlock(self: DataExtractor, block_ind: u32) ![]u8 {
|
||||||
@@ -98,7 +97,7 @@ pub const DataExtractor = struct {
|
|||||||
//TODO
|
//TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
fn processBlockToFile(self: DataExtractor, block_ind: u32, fil: *fs.File) !void {
|
fn processBlockToFile(self: DataExtractor, block_ind: u32, fil: *const fs.File) !void {
|
||||||
_ = self;
|
_ = self;
|
||||||
_ = block_ind;
|
_ = block_ind;
|
||||||
_ = fil;
|
_ = fil;
|
||||||
@@ -110,7 +109,7 @@ pub const DataExtractor = struct {
|
|||||||
/// Returns the amount of bytes written.
|
/// Returns the amount of bytes written.
|
||||||
///
|
///
|
||||||
/// Optimized for lower memory usage by using File.pwrite.
|
/// Optimized for lower memory usage by using File.pwrite.
|
||||||
pub fn writeToFile(self: DataExtractor, conf: Config, fil: *fs.File) !void {
|
pub fn writeToFile(self: DataExtractor, conf: Config, fil: *const fs.File) !void {
|
||||||
_ = self;
|
_ = self;
|
||||||
_ = fil;
|
_ = fil;
|
||||||
_ = conf;
|
_ = conf;
|
||||||
|
|||||||
+17
-17
@@ -23,7 +23,7 @@ pub const DataReader = struct {
|
|||||||
frag_data: ?[]u8 = null,
|
frag_data: ?[]u8 = null,
|
||||||
|
|
||||||
next_block_num: u32 = 0,
|
next_block_num: u32 = 0,
|
||||||
cur_bloc: []u8 = undefined,
|
cur_bloc: []u8 = &[0]u8{},
|
||||||
cur_offset: u32 = 0,
|
cur_offset: u32 = 0,
|
||||||
|
|
||||||
pub fn init(fil: *File, reader: *Reader) !DataReader {
|
pub fn init(fil: *File, reader: *Reader) !DataReader {
|
||||||
@@ -84,17 +84,17 @@ pub const DataReader = struct {
|
|||||||
pub fn deinit(self: *DataReader) void {
|
pub fn deinit(self: *DataReader) void {
|
||||||
self.alloc.free(self.sizes);
|
self.alloc.free(self.sizes);
|
||||||
if (self.cur_bloc.len > 0) self.alloc.free(self.cur_bloc);
|
if (self.cur_bloc.len > 0) self.alloc.free(self.cur_bloc);
|
||||||
if (self.frag_data != null) self.alloc.free(self.frag_data);
|
if (self.frag_data != null) self.alloc.free(self.frag_data.?);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn skip(self: *DataReader, offset: u32) !void {
|
pub fn skip(self: *DataReader, offset: u32) !void {
|
||||||
var cur_skip: u32 = 0;
|
var cur_skip: u32 = 0;
|
||||||
var to_skip: u32 = 0;
|
var to_skip: u32 = 0;
|
||||||
while (cur_skip < offset) {
|
while (cur_skip < offset) {
|
||||||
if (self.offset >= self.block.len) try self.readNextBlock();
|
if (self.cur_offset >= self.cur_bloc.len) try self.readNextBlock();
|
||||||
to_skip = @min(offset - cur_skip, self.block.len - self.offset);
|
to_skip = @min(offset - cur_skip, self.cur_bloc.len - self.cur_offset);
|
||||||
cur_skip += to_skip;
|
cur_skip += to_skip;
|
||||||
self.offset += to_skip;
|
self.cur_offset += to_skip;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,8 +106,8 @@ pub const DataReader = struct {
|
|||||||
const siz = self.sizes[self.next_block_num];
|
const siz = self.sizes[self.next_block_num];
|
||||||
self.next_block_num += 1;
|
self.next_block_num += 1;
|
||||||
if (self.next_block_num == self.sizes.len - 1 and self.frag_data != null) {
|
if (self.next_block_num == self.sizes.len - 1 and self.frag_data != null) {
|
||||||
try self.sizeBlock(self.frag_data.len);
|
try self.sizeBlock(self.frag_data.?.len);
|
||||||
@memcpy(self.cur_bloc, self.frag_data);
|
@memcpy(self.cur_bloc, self.frag_data.?);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (siz.size == 0) {
|
if (siz.size == 0) {
|
||||||
@@ -120,14 +120,14 @@ pub const DataReader = struct {
|
|||||||
_ = try self.rdr.any().readAll(self.cur_bloc);
|
_ = try self.rdr.any().readAll(self.cur_bloc);
|
||||||
} else {
|
} else {
|
||||||
self.alloc.free(self.cur_bloc);
|
self.alloc.free(self.cur_bloc);
|
||||||
var limit = std.io.limitedReader(self.reader, siz.size);
|
var limit = std.io.limitedReader(self.rdr, siz.size);
|
||||||
var dat = try self.decomp.decompress(self.alloc, limit.reader().any());
|
var dat = try self.decomp.decompress(self.alloc, limit.reader().any());
|
||||||
self.block = try dat.toOwnedSlice();
|
self.cur_bloc = try dat.toOwnedSlice();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sizeBlock(self: *DataReader, size: u32) !void {
|
fn sizeBlock(self: *DataReader, size: usize) !void {
|
||||||
if (!self.alloc.resize(u8, size)) {
|
if (!self.alloc.resize(self.cur_bloc, size)) {
|
||||||
self.alloc.free(self.cur_bloc);
|
self.alloc.free(self.cur_bloc);
|
||||||
self.cur_bloc = try self.alloc.alloc(u8, size);
|
self.cur_bloc = try self.alloc.alloc(u8, size);
|
||||||
}
|
}
|
||||||
@@ -137,15 +137,15 @@ pub const DataReader = struct {
|
|||||||
var cur_read: usize = 0;
|
var cur_read: usize = 0;
|
||||||
var to_read: usize = 0;
|
var to_read: usize = 0;
|
||||||
while (cur_read < bytes.len) {
|
while (cur_read < bytes.len) {
|
||||||
if (self.offset >= self.block.len) {
|
if (self.cur_offset >= self.cur_bloc.len) {
|
||||||
if (self.readNextBlock()) |err| {
|
self.readNextBlock() catch |err| {
|
||||||
if (err == DataReaderError.EOF) return cur_read;
|
if (err == DataReaderError.EOF) return cur_read;
|
||||||
return err;
|
return err;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
to_read = @min(bytes.len - cur_read, self.block.len - self.offset);
|
to_read = @min(bytes.len - cur_read, self.cur_bloc.len - self.cur_offset);
|
||||||
@memcpy(bytes[cur_read..], self.block[self.offset .. @as(usize, self.offset) + to_read]);
|
@memcpy(bytes[cur_read..], self.cur_bloc[self.cur_offset .. @as(usize, self.cur_offset) + to_read]);
|
||||||
self.offset += @truncate(to_read);
|
self.cur_offset += @truncate(to_read);
|
||||||
cur_read += to_read;
|
cur_read += to_read;
|
||||||
}
|
}
|
||||||
return cur_read;
|
return cur_read;
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ pub const FileOffsetReader = struct {
|
|||||||
file: *File,
|
file: *File,
|
||||||
offset: u64,
|
offset: u64,
|
||||||
|
|
||||||
|
pub const Error = fs.File.PReadError;
|
||||||
|
|
||||||
pub fn read(self: *FileOffsetReader, bytes: []u8) !usize {
|
pub fn read(self: *FileOffsetReader, bytes: []u8) !usize {
|
||||||
const red = try self.file.preadAll(bytes, self.offset);
|
const red = try self.file.preadAll(bytes, self.offset);
|
||||||
self.offset += red;
|
self.offset += red;
|
||||||
|
|||||||
+10
-14
@@ -13,7 +13,6 @@ pub fn Table(
|
|||||||
comptime T: type,
|
comptime T: type,
|
||||||
) type {
|
) type {
|
||||||
return struct {
|
return struct {
|
||||||
alloc: std.mem.Allocator,
|
|
||||||
decomp: DecompressType,
|
decomp: DecompressType,
|
||||||
table: []T = &[0]T{},
|
table: []T = &[0]T{},
|
||||||
offset: u64,
|
offset: u64,
|
||||||
@@ -21,14 +20,13 @@ pub fn Table(
|
|||||||
|
|
||||||
pub fn init(read: *Reader, offset: u64, item_count: u32) Self {
|
pub fn init(read: *Reader, offset: u64, item_count: u32) Self {
|
||||||
return .{
|
return .{
|
||||||
.alloc = read.alloc,
|
|
||||||
.decomp = read.super.decomp,
|
.decomp = read.super.decomp,
|
||||||
.offset = offset,
|
.offset = offset,
|
||||||
.item_count = item_count,
|
.item_count = item_count,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
pub fn deinit(self: *Self, alloc: std.mem.Allocator) void {
|
pub fn deinit(self: *Self, alloc: std.mem.Allocator) void {
|
||||||
alloc.free(self.table);
|
if (self.table.len == 0) alloc.free(self.table);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getValue(self: *Self, read: *Reader, i: u64) !T {
|
pub fn getValue(self: *Self, read: *Reader, i: u64) !T {
|
||||||
@@ -36,23 +34,21 @@ pub fn Table(
|
|||||||
if (self.table.len > i) return self.table[i];
|
if (self.table.len > i) return self.table[i];
|
||||||
var meta_rdr: MetadataReader = undefined;
|
var meta_rdr: MetadataReader = undefined;
|
||||||
var offset_rdr: FileOffsetReader = undefined;
|
var offset_rdr: FileOffsetReader = undefined;
|
||||||
|
var meta_buf: [8]u8 = [1]u8{0} ** 8;
|
||||||
var meta_offset: u64 = 0;
|
var meta_offset: u64 = 0;
|
||||||
var to_read: u32 = 0;
|
var to_read: u32 = 0;
|
||||||
while (self.table.len <= i) {
|
while (self.table.len <= i) {
|
||||||
_ = try read.holder.file.preadAll(std.mem.sliceAsBytes(&meta_offset), self.offset);
|
_ = try read.holder.file.preadAll(&meta_buf, self.offset);
|
||||||
self.offset += 8;
|
self.offset += 8;
|
||||||
|
meta_offset = std.mem.bytesToValue(u8, &meta_buf);
|
||||||
offset_rdr = read.holder.readerAt(meta_offset);
|
offset_rdr = read.holder.readerAt(meta_offset);
|
||||||
meta_rdr = .init(self.alloc, self.decomp, offset_rdr.any());
|
meta_rdr = .init(read.alloc, self.decomp, offset_rdr.any());
|
||||||
defer meta_rdr.deinit();
|
defer meta_rdr.deinit();
|
||||||
to_read = @min(self.item_count - self.table.len, comptime blk: {
|
to_read = @min(self.item_count - self.table.len, comptime 8192 / @sizeOf(T));
|
||||||
break :blk 8192 / @sizeOf(T);
|
const alloc_size = self.table.len + to_read;
|
||||||
});
|
if (self.table.len != 0) read.alloc.free(self.table);
|
||||||
if (!self.alloc.resize(self.table, self.table.len + to_read)) {
|
self.table = try read.alloc.alloc(T, alloc_size);
|
||||||
const alloc_size = self.table.len + to_read;
|
_ = try meta_rdr.any().readAll(@ptrCast(self.table[self.table.len - to_read ..]));
|
||||||
self.alloc.free(self.table);
|
|
||||||
self.table = try self.alloc.alloc(T, alloc_size);
|
|
||||||
}
|
|
||||||
_ = try meta_rdr.any().readAll(std.mem.asBytes(self.table[self.table.len - to_read ..]));
|
|
||||||
}
|
}
|
||||||
return self.table[i];
|
return self.table[i];
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user