Started work on data readers
This commit is contained in:
+29
-16
@@ -3,23 +3,25 @@ const io = std.io;
|
||||
|
||||
const inode = @import("inode/inode.zig");
|
||||
const directory = @import("directory.zig");
|
||||
const data = @import("readers/data.zig");
|
||||
|
||||
const Reader = @import("reader.zig").Reader;
|
||||
const DirEntry = @import("directory.zig").DirEntry;
|
||||
const MetadataReader = @import("readers/metadata.zig").MetadataReader;
|
||||
|
||||
const FileError = error{
|
||||
pub const File = struct {
|
||||
name: []const u8,
|
||||
inode: inode.Inode,
|
||||
dirEntries: ?std.StringHashMap(DirEntry) = null,
|
||||
|
||||
data_rdr: ?data.DataReader = null,
|
||||
|
||||
pub const FileError = error{
|
||||
NotDirectory,
|
||||
NotNormalFile,
|
||||
NotSymlink,
|
||||
NotFound,
|
||||
};
|
||||
|
||||
pub const File = struct {
|
||||
name: []const u8,
|
||||
inode: inode.Inode,
|
||||
dirEntries: std.StringHashMap(DirEntry) = undefined,
|
||||
hasEntries: bool = false,
|
||||
};
|
||||
|
||||
pub fn deinit(self: *File, alloc: std.mem.Allocator) void {
|
||||
self.inode.deinit();
|
||||
@@ -47,9 +49,7 @@ pub const File = struct {
|
||||
.dir, .ext_dir => {},
|
||||
else => return FileError.NotDirectory,
|
||||
}
|
||||
if (!self.hasEntries) {
|
||||
try self.readDirEntries(reader);
|
||||
}
|
||||
const split_idx = std.mem.indexOf(u8, clean_path, "/") orelse clean_path.len;
|
||||
const name = clean_path[0..split_idx];
|
||||
const ent = self.dirEntries.get(name);
|
||||
@@ -69,6 +69,7 @@ pub const File = struct {
|
||||
}
|
||||
|
||||
fn readDirEntries(self: *File, reader: *Reader) !void {
|
||||
if (self.dirEntries != null) return;
|
||||
var block_start: u32 = 0;
|
||||
var offset: u16 = 0;
|
||||
var size: u32 = 0;
|
||||
@@ -86,36 +87,48 @@ pub const File = struct {
|
||||
else => return FileError.NotDirectory,
|
||||
}
|
||||
var offset_rdr = reader.holder.readerAt(reader.super.dir_table_start + block_start);
|
||||
var meta_rdr: MetadataReader = try .init(
|
||||
var meta_rdr: MetadataReader = .init(
|
||||
reader.alloc,
|
||||
offset_rdr.any(),
|
||||
reader.super.decomp,
|
||||
offset_rdr.any(),
|
||||
);
|
||||
defer meta_rdr.deinit();
|
||||
try meta_rdr.skip(offset);
|
||||
self.dirEntries = try directory.readDirectory(reader.alloc, meta_rdr.any(), size);
|
||||
self.hasEntries = true;
|
||||
}
|
||||
|
||||
pub fn read(self: *File, bytes: []u8) !usize {
|
||||
if (self.data_rdr == null) {
|
||||
return FileError.NotNormalFile;
|
||||
}
|
||||
return self.data_rdr.?.read(bytes);
|
||||
}
|
||||
};
|
||||
|
||||
fn fileFromDirEntry(read: *Reader, ent: DirEntry) !File {
|
||||
var offset_rdr = read.holder.readerAt(ent.block_start + read.super.inode_table_start);
|
||||
var meta_rdr: MetadataReader = try .init(
|
||||
var meta_rdr: MetadataReader = .init(
|
||||
read.alloc,
|
||||
offset_rdr.any(),
|
||||
read.super.decomp,
|
||||
offset_rdr.any(),
|
||||
);
|
||||
defer meta_rdr.deinit();
|
||||
try meta_rdr.skip(ent.offset);
|
||||
// Copy name so we can clean-up the DirEntrys without causing issues.
|
||||
const name = try read.alloc.alloc(u8, ent.name.len);
|
||||
std.mem.copyForwards(u8, name, ent.name);
|
||||
return .{
|
||||
var out: File = .{
|
||||
.name = name,
|
||||
.inode = try .init(
|
||||
.inode = .init(
|
||||
read.alloc,
|
||||
meta_rdr.any(),
|
||||
read.super.block_size,
|
||||
),
|
||||
};
|
||||
out.data_rdr = switch (out.inode.data) {
|
||||
.file, .ext_file => try .init(&out, read),
|
||||
else => null,
|
||||
};
|
||||
return out;
|
||||
}
|
||||
|
||||
+2
-2
@@ -34,10 +34,10 @@ pub const Reader = struct {
|
||||
|
||||
fn fileFromRef(self: *Reader, ref: inode.InodeRef, name: []const u8) !File {
|
||||
var offset_rdr = self.holder.readerAt(ref.block_start + self.super.inode_table_start);
|
||||
var meta_rdr: MetadataReader = try .init(
|
||||
var meta_rdr: MetadataReader = .init(
|
||||
self.alloc,
|
||||
offset_rdr.any(),
|
||||
self.super.decomp,
|
||||
offset_rdr.any(),
|
||||
);
|
||||
defer meta_rdr.deinit();
|
||||
try meta_rdr.skip(ref.offset);
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
const std = @import("std");
|
||||
const io = std.io;
|
||||
|
||||
const File = @import("../file.zig").File;
|
||||
const Reader = @import("../reader.zig").Reader;
|
||||
const BlockSize = @import("../inode/file.zig").BlockSize;
|
||||
const DecompressionType = @import("../decompress.zig").DecompressType;
|
||||
|
||||
const DataReaderError = error{
|
||||
EOF,
|
||||
};
|
||||
|
||||
pub const DataReader = struct {
|
||||
alloc: std.mem.Allocator,
|
||||
decomp: DecompressionType,
|
||||
rdr: io.AnyReader,
|
||||
block_size: u32,
|
||||
sizes: []BlockSize,
|
||||
frag_rdr: ?io.AnyReader,
|
||||
|
||||
next_block_num: u32 = 0,
|
||||
cur_bloc: []u8 = undefined,
|
||||
cur_offset: u32 = 0,
|
||||
|
||||
pub fn init(fil: *File, reader: *Reader) !DataReader {
|
||||
const data_start: u64 = 0;
|
||||
const sizes: []BlockSize = undefined;
|
||||
const size: u64 = 0;
|
||||
const frag_idx: u32 = 0;
|
||||
const frag_offset: u32 = 0;
|
||||
switch (fil.inode.data) {
|
||||
.file => |f| {
|
||||
sizes = try reader.alloc.alloc(BlockSize, f.blocks.len);
|
||||
std.mem.copyForwards(BlockSize, sizes, f.blocks);
|
||||
data_start = f.data_start;
|
||||
size = f.size;
|
||||
frag_idx = f.frag_idx;
|
||||
frag_offset = f.frag_offset;
|
||||
},
|
||||
.ext_file => |f| {
|
||||
sizes = try reader.alloc.alloc(BlockSize, f.blocks.len);
|
||||
std.mem.copyForwards(BlockSize, sizes, f.blocks);
|
||||
data_start = f.data_start;
|
||||
size = f.size;
|
||||
frag_idx = f.frag_idx;
|
||||
frag_offset = f.frag_offset;
|
||||
},
|
||||
else => return File.FileError.NotNormalFile,
|
||||
}
|
||||
//TODO: set-up frag_rdr
|
||||
}
|
||||
|
||||
pub fn deinit(self: *DataReader) void {
|
||||
if (self.cur_bloc.len > 0) self.alloc.free(self.cur_bloc);
|
||||
}
|
||||
|
||||
pub fn skip(self: *DataReader, offset: u32) !void {
|
||||
var cur_skip: u32 = 0;
|
||||
var to_skip: u32 = 0;
|
||||
while (cur_skip < offset) {
|
||||
if (self.offset >= self.block.len) try self.readNextBlock();
|
||||
to_skip = @min(offset - cur_skip, self.block.len - self.offset);
|
||||
cur_skip += to_skip;
|
||||
self.offset += to_skip;
|
||||
}
|
||||
}
|
||||
|
||||
fn readNextBlock(self: *DataReader) !void {
|
||||
if (self.next_block_num == self.sizes.len) {
|
||||
if (self.cur_bloc.len > 0) self.alloc.free(self.cur_bloc);
|
||||
return DataReaderError.EOF;
|
||||
}
|
||||
const siz = self.sizes[self.next_block_num];
|
||||
self.next_block_num += 1;
|
||||
if (self.next_block_num == self.sizes.len - 1 and self.frag_rdr != null) {
|
||||
_ = try self.frag_rdr.?.readAll(self.cur_bloc);
|
||||
return;
|
||||
}
|
||||
if (siz.size == 0) {}
|
||||
if (siz.not_compressed) {}
|
||||
}
|
||||
|
||||
pub fn read(self: *DataReader, bytes: []u8) !usize {
|
||||
var cur_read: usize = 0;
|
||||
var to_read: usize = 0;
|
||||
while (cur_read < bytes.len) {
|
||||
if (self.offset >= self.block.len) {
|
||||
if (self.readNextBlock()) |err| {
|
||||
if (err == DataReaderError.EOF) return cur_read;
|
||||
return err;
|
||||
}
|
||||
}
|
||||
to_read = @min(bytes.len - cur_read, self.block.len - self.offset);
|
||||
std.mem.copyForwards(u8, bytes[cur_read..], self.block[self.offset .. @as(usize, self.offset) + to_read]);
|
||||
self.offset += @truncate(to_read);
|
||||
cur_read += to_read;
|
||||
}
|
||||
return cur_read;
|
||||
}
|
||||
|
||||
pub fn any(self: *DataReader) io.AnyReader {
|
||||
return .{
|
||||
.context = @ptrCast(self),
|
||||
.readFn = readOpaque,
|
||||
};
|
||||
}
|
||||
|
||||
fn readOpaque(context: *const anyopaque, bytes: []u8) !usize {
|
||||
var self: *DataReader = @constCast(@ptrCast(@alignCast(context)));
|
||||
return self.read(bytes);
|
||||
}
|
||||
};
|
||||
|
||||
pub const DataExtractor = struct {};
|
||||
@@ -2,8 +2,10 @@ const std = @import("std");
|
||||
const fs = std.fs;
|
||||
const io = std.io;
|
||||
|
||||
const File = std.fs.File;
|
||||
|
||||
pub const FileHolder = struct {
|
||||
file: fs.File,
|
||||
file: File,
|
||||
offset: u64,
|
||||
|
||||
pub fn init(path: []const u8, offset: u64) !FileHolder {
|
||||
@@ -16,7 +18,7 @@ pub const FileHolder = struct {
|
||||
self.file.close();
|
||||
}
|
||||
|
||||
pub fn reader(self: *FileHolder) fs.File.Reader {
|
||||
pub fn reader(self: *FileHolder) File.Reader {
|
||||
return self.file.reader();
|
||||
}
|
||||
pub fn readerAt(self: *FileHolder, offset: u64) FileOffsetReader {
|
||||
@@ -28,7 +30,7 @@ pub const FileHolder = struct {
|
||||
};
|
||||
|
||||
const FileOffsetReader = struct {
|
||||
file: *fs.File,
|
||||
file: *File,
|
||||
offset: u64,
|
||||
|
||||
pub fn read(self: *FileOffsetReader, bytes: []u8) !usize {
|
||||
|
||||
@@ -10,21 +10,17 @@ const MetadataHeader = packed struct {
|
||||
|
||||
pub const MetadataReader = struct {
|
||||
alloc: std.mem.Allocator,
|
||||
reader: io.AnyReader,
|
||||
block: []u8,
|
||||
decomp: DecompressType,
|
||||
offset: u32,
|
||||
reader: io.AnyReader,
|
||||
block: []u8 = &[0]u8{},
|
||||
offset: u32 = 0,
|
||||
|
||||
pub fn init(alloc: std.mem.Allocator, rdr: io.AnyReader, decomp: DecompressType) !MetadataReader {
|
||||
var out: MetadataReader = .{
|
||||
pub fn init(alloc: std.mem.Allocator, decomp: DecompressType, rdr: io.AnyReader) MetadataReader {
|
||||
return .{
|
||||
.alloc = alloc,
|
||||
.reader = rdr,
|
||||
.block = &[0]u8{},
|
||||
.decomp = decomp,
|
||||
.offset = 0,
|
||||
.reader = rdr,
|
||||
};
|
||||
try out.readNextBlock();
|
||||
return out;
|
||||
}
|
||||
pub fn deinit(self: *MetadataReader) void {
|
||||
self.alloc.free(self.block);
|
||||
|
||||
@@ -1,3 +1 @@
|
||||
pub const Reader = @import("reader.zig").Reader;
|
||||
|
||||
pub const File = @import("file.zig").File;
|
||||
|
||||
Reference in New Issue
Block a user