Extraction Finished-ish
This commit is contained in:
+49
-24
@@ -18,7 +18,7 @@ block_size: u32,
|
||||
|
||||
blocks: []BlockSize,
|
||||
|
||||
frag: ?FragEntry, // TODO: do something better?
|
||||
frag: ?FragEntry = null, // TODO: do something better?
|
||||
frag_offset: u32 = 0,
|
||||
size: u64,
|
||||
|
||||
@@ -49,7 +49,9 @@ pub fn init(archive: *Archive, blocks: []BlockSize, start: u64, size: u64) DataR
|
||||
};
|
||||
}
|
||||
pub fn deinit(self: *DataReader) void {
|
||||
self.alloc.free(self.inteface.buffer);
|
||||
self.alloc.free(self.interface.buffer);
|
||||
self.interface.end = 0;
|
||||
self.interface.seek = 0;
|
||||
}
|
||||
|
||||
pub fn addFragment(self: *DataReader, entry: FragEntry, frag_offset: u32) void {
|
||||
@@ -57,21 +59,29 @@ pub fn addFragment(self: *DataReader, entry: FragEntry, frag_offset: u32) void {
|
||||
self.frag_offset = frag_offset;
|
||||
}
|
||||
|
||||
fn blockNum(self: DataReader) u32 {
|
||||
fn numBlocks(self: DataReader) usize {
|
||||
var res = self.blocks.len;
|
||||
if (self.frag != null) res += 1;
|
||||
return res;
|
||||
}
|
||||
|
||||
fn advance(self: *DataReader) !void {
|
||||
if (self.block_idx > self.blocks.len or (self.block_idx == self.blocks.len and self.frag == null)) return Reader.Error.EndOfStream;
|
||||
if (self.block_idx > self.blocks.len or (self.block_idx == self.blocks.len and self.frag == null)) {
|
||||
if (self.interface.buffer.len > 0) {
|
||||
self.alloc.free(self.interface.buffer);
|
||||
self.interface.buffer = &[0]u8{};
|
||||
self.interface.end = 0;
|
||||
self.interface.seek = 0;
|
||||
}
|
||||
return Reader.Error.EndOfStream;
|
||||
}
|
||||
defer self.block_idx += 1;
|
||||
const cur_block_size = if (self.block_idx == self.numBlocks() - 1) self.size % self.block_size else self.block_size;
|
||||
try self.resizeBuffer(cur_block_size);
|
||||
self.interface.seek = 0;
|
||||
self.alloc.free(self.interface.buffer);
|
||||
self.interface.end = cur_block_size;
|
||||
if (self.block_idx == self.blocks.len) { // fragment
|
||||
var rdr = try self.fil.readerAt(self.frag.?.start + self.frag_offset, &[0]u8);
|
||||
self.interface.buffer = try rdr.interface.readAlloc(self.alloc, self.size % self.block_size);
|
||||
self.interface.end = self.interface.buffer.len;
|
||||
var rdr = try self.fil.readerAt(self.frag.?.start, &[0]u8{});
|
||||
if (self.frag.?.size.uncompressed) {
|
||||
try rdr.interface.discardAll(self.frag_offset);
|
||||
try rdr.interface.readSliceAll(self.interface.buffer);
|
||||
@@ -79,30 +89,45 @@ fn advance(self: *DataReader) !void {
|
||||
}
|
||||
const tmp_buf = try self.alloc.alloc(u8, self.frag.?.size.size);
|
||||
defer self.alloc.free(tmp_buf);
|
||||
var limit_rdr = Reader.limited(&rdr.interface, self.frag.?.size.size, tmp_buf);
|
||||
const needed_block = try self.alloc.alloc(u8, self.frag_offset + self.interface.buffer.len);
|
||||
var limit_rdr = Reader.limited(&rdr.interface, @enumFromInt(self.frag.?.size.size), tmp_buf);
|
||||
const needed_block = try self.alloc.alloc(u8, self.frag_offset + cur_block_size);
|
||||
defer self.alloc.free(needed_block);
|
||||
_ = try self.decomp.decompReader(&limit_rdr.interface, needed_block);
|
||||
@memcpy(self.interface.buffer, needed_block[self.frag_offset..]);
|
||||
return;
|
||||
}
|
||||
const cur_block_size = if (self.block_idx == self.blockNum() - 1) self.size % self.block_size else self.block_size;
|
||||
const block = self.blocks[self.block_idx];
|
||||
var rdr = try self.fil.readerAt(self.cur_offset, &[0]u8);
|
||||
self.interface.end = cur_block_size;
|
||||
if (block.uncompressed) {
|
||||
self.interface.buffer = try rdr.interface.readAlloc(self.alloc, cur_block_size);
|
||||
if (block.size == 0) {
|
||||
@memset(self.interface.buffer, 0);
|
||||
return;
|
||||
}
|
||||
var buf: [8192]u8 = undefined;
|
||||
var limit_rdr = Reader.limited(&rdr.interface, block.size, &buf);
|
||||
var rdr = try self.fil.readerAt(self.cur_offset, &[0]u8{});
|
||||
if (block.uncompressed) {
|
||||
try rdr.interface.readSliceAll(self.interface.buffer);
|
||||
return;
|
||||
}
|
||||
var buf: [8192]u8 = undefined; //TODO: possibly change for better performance/memory usage. Might need to be a full block in size.
|
||||
var limit_rdr = Reader.limited(&rdr.interface, @enumFromInt(block.size), &buf);
|
||||
_ = try self.decomp.decompReader(&limit_rdr.interface, self.interface.buffer);
|
||||
}
|
||||
/// Does not guarentee that data currently in the buffer is retained.
|
||||
fn resizeBuffer(self: *DataReader, size: usize) !void {
|
||||
if (self.interface.buffer.len == size) return;
|
||||
if (!self.alloc.resize(self.interface.buffer, size)) {
|
||||
self.alloc.free(self.interface.buffer);
|
||||
self.interface.buffer = self.alloc.alloc(u8, size) catch |err| {
|
||||
self.interface.buffer = &[0]u8{};
|
||||
return err;
|
||||
};
|
||||
} else {
|
||||
self.interface.buffer.len = size;
|
||||
}
|
||||
}
|
||||
|
||||
fn stream(rdr: *Reader, wrt: *Writer, limit: Limit) Reader.StreamError!usize {
|
||||
var self: *DataReader = @fieldParentPtr("interface", rdr);
|
||||
var self: *DataReader = @alignCast(@fieldParentPtr("interface", rdr));
|
||||
if (rdr.seek >= rdr.end) self.advance() catch |err| {
|
||||
if (err == .EndOfStream) return err;
|
||||
if (err == error.EndOfStream) return error.EndOfStream;
|
||||
std.log.err("Error advancing data reader: {}\n", .{err});
|
||||
return Reader.Error.ReadFailed;
|
||||
};
|
||||
@@ -114,9 +139,9 @@ fn stream(rdr: *Reader, wrt: *Writer, limit: Limit) Reader.StreamError!usize {
|
||||
}
|
||||
|
||||
fn discard(rdr: *Reader, limit: Limit) Reader.Error!usize {
|
||||
var self: *DataReader = @fieldParentPtr("interface", rdr);
|
||||
var self: *DataReader = @alignCast(@fieldParentPtr("interface", rdr));
|
||||
if (rdr.seek >= rdr.end) self.advance() catch |err| {
|
||||
if (err == .EndOfStream) return err;
|
||||
if (err == error.EndOfStream) return error.EndOfStream;
|
||||
std.log.err("Error advancing data reader: {}\n", .{err});
|
||||
return Reader.Error.ReadFailed;
|
||||
};
|
||||
@@ -127,16 +152,16 @@ fn discard(rdr: *Reader, limit: Limit) Reader.Error!usize {
|
||||
}
|
||||
|
||||
fn readVec(rdr: *Reader, vec: [][]u8) Reader.Error!usize {
|
||||
var self: *DataReader = @fieldParentPtr("interface", rdr);
|
||||
var self: *DataReader = @alignCast(@fieldParentPtr("interface", rdr));
|
||||
if (rdr.seek >= rdr.end) self.advance() catch |err| {
|
||||
if (err == .EndOfStream) return err;
|
||||
if (err == error.EndOfStream) return error.EndOfStream;
|
||||
std.log.err("Error advancing data reader: {}\n", .{err});
|
||||
return Reader.Error.ReadFailed;
|
||||
};
|
||||
var cur_red: usize = 0;
|
||||
for (vec) |s| {
|
||||
const to_copy: usize = @min(rdr.end - rdr.seek, s.len);
|
||||
@memcpy(s[0..to_copy], self.buf[rdr.seek .. rdr.seek + to_copy]);
|
||||
@memcpy(s[0..to_copy], rdr.buffer[rdr.seek .. rdr.seek + to_copy]);
|
||||
rdr.seek += to_copy;
|
||||
cur_red += to_copy;
|
||||
if (rdr.end == rdr.seek) break;
|
||||
|
||||
Reference in New Issue
Block a user