Compare commits

..

No commits in common. "449b56947ed82abfc9d650d59ebde01b46655f01" and "2792f27473c40fb1cd349dc29aa7f53e5ad3b22b" have entirely different histories.

3 changed files with 41 additions and 55 deletions

View File

@ -24,7 +24,7 @@ pub const Archive = struct {
/// ///
/// ///
/// ///
const IndexCache = table.Hashed([]const u8, u64, table.string_context); const IndexCache = table.Hashed([]const u8, Entry.Header, table.string_context);
/// ///
/// Finds an entry matching `entry_path` in `archive`. /// Finds an entry matching `entry_path` in `archive`.
@ -34,50 +34,40 @@ pub const Archive = struct {
pub fn find(archive: *Archive, entry_path: []const u8) FindError!Entry { pub fn find(archive: *Archive, entry_path: []const u8) FindError!Entry {
return Entry{ return Entry{
.header = find_header: { .header = find_header: {
var header = Entry.Header{ if (archive.index_cache.lookup(entry_path)) |entry_header|
break: find_header entry_header.*;
// Start from beginning of archive.
try archive.file_access.seek(0);
var entry_header = Entry.Header{
.revision = 0, .revision = 0,
.file_size = 0, .file_size = 0,
.absolute_offset = 0 .file_offset = 0
}; };
const header_size = @sizeOf(Entry.Header); const read_buffer = std.mem.asBytes(&entry_header);
if (archive.index_cache.lookup(entry_path)) |cursor| { // Read first entry.
try archive.file_access.seek(cursor); while ((try archive.file_access.read(read_buffer)) == @sizeOf(Entry.Header)) {
if (std.mem.eql(u8, entry_path, entry_header.
name_buffer[0 .. entry_header.name_length])) {
if ((try archive.file_access.read(std.mem.asBytes(&header))) != header_size) { // If caching fails... oh well...
std.debug.assert(archive.index_cache.remove(entry_path) != null); archive.index_cache.insert(entry_path, entry_header) catch {};
return error.EntryNotFound; break: find_header entry_header;
} }
break: find_header header; // Move over file data following the entry.
} else { var to_skip = entry_header.file_size;
const mem = std.mem;
// Start from beginning of archive. while (to_skip != 0) {
try archive.file_access.seek(0); const skipped = std.math.min(to_skip, std.math.maxInt(i64));
// Read first entry. try archive.file_access.skip(@intCast(i64, skipped));
while ((try archive.file_access.read(mem.asBytes(&header))) == header_size) {
if (mem.eql(u8, entry_path, header.name_buffer[0 .. header.name_length])) {
// If caching fails... oh well...
archive.index_cache.insert(entry_path, header.absolute_offset) catch {};
break: find_header header; to_skip -= skipped;
}
// Move over file data following the entry.
var to_skip = header.file_size;
while (to_skip != 0) {
const math = std.math;
const skipped = math.min(to_skip, math.maxInt(i64));
try archive.file_access.skip(@intCast(i64, skipped));
to_skip -= skipped;
}
} }
} }
@ -119,7 +109,7 @@ pub const Entry = struct {
name_buffer: [255]u8 = std.mem.zeroes([255]u8), name_buffer: [255]u8 = std.mem.zeroes([255]u8),
name_length: u8 = 0, name_length: u8 = 0,
file_size: u64, file_size: u64,
absolute_offset: u64, file_offset: u64,
padding: [232]u8 = std.mem.zeroes([232]u8), padding: [232]u8 = std.mem.zeroes([232]u8),
comptime { comptime {

View File

@ -487,7 +487,7 @@ pub const FileSystem = union(enum) {
if (archive_entry.cursor >= archive_entry.header.file_size) if (archive_entry.cursor >= archive_entry.header.file_size)
return error.FileInaccessible; return error.FileInaccessible;
try file_access.seek(archive_entry.header.absolute_offset); try file_access.seek(archive_entry.header.file_offset);
return file_access.read(buffer[0 .. std.math.min( return file_access.read(buffer[0 .. std.math.min(
buffer.len, archive_entry.header.file_size)]); buffer.len, archive_entry.header.file_size)]);

View File

@ -56,18 +56,16 @@ pub fn Hashed(comptime Key: type, comptime Value: type,
} }
/// ///
/// Searches for `key` and deletes it from `self. /// Searches for `key` to delete it, returning the deleted value or `null` if no matching
/// key was found.
/// ///
/// The removed value is returned or `null` if no key matching `key` was found. pub fn remove(self: Self, key: Key) ?Value {
///
pub fn remove(self: *Self, key: Key) ?Value {
var bucket = &(self.buckets[@mod(key_context.hash(key), self.buckets.len)]); var bucket = &(self.buckets[@mod(key_context.hash(key), self.buckets.len)]);
if (bucket.maybe_entry) |*entry| if (key_context.equals(entry.key, key)) { if (bucket.maybe_entry) |*entry| if (key_context.equals(entry.key, key)) {
defer { defer entry.value = null;
bucket.maybe_entry = null;
self.filled -= 1; self.filled -= 1;
}
return entry.value; return entry.value;
}; };
@ -76,10 +74,9 @@ pub fn Hashed(comptime Key: type, comptime Value: type,
bucket = &(self.buckets[index]); bucket = &(self.buckets[index]);
if (bucket.maybe_entry) |*entry| if (key_context.equals(entry.key, key)) { if (bucket.maybe_entry) |*entry| if (key_context.equals(entry.key, key)) {
defer { defer entry.value = null;
bucket.maybe_entry = null;
self.filled -= 1; self.filled -= 1;
}
return entry.value; return entry.value;
}; };
@ -132,21 +129,20 @@ pub fn Hashed(comptime Key: type, comptime Value: type,
} }
/// ///
/// Searches for a value indexed with `key` in `self`. /// Searches for a value indexed with `key` in `self`, returning it or `null` if no matching
/// entry was found.
/// ///
/// The found value is returned or `null` if an key matching `key` failed to be found. pub fn lookup(self: Self, key: Key) ?*Value {
///
pub fn lookup(self: Self, key: Key) ?Value {
var bucket = &(self.buckets[@mod(key_context.hash(key), self.buckets.len)]); var bucket = &(self.buckets[@mod(key_context.hash(key), self.buckets.len)]);
if (bucket.maybe_entry) |entry| if (bucket.maybe_entry) |*entry|
if (key_context.equals(entry.key, key)) return entry.value; if (key_context.equals(entry.key, key)) return &entry.value;
while (bucket.maybe_next_index) |index| { while (bucket.maybe_next_index) |index| {
bucket = &(self.buckets[index]); bucket = &(self.buckets[index]);
if (bucket.maybe_entry) |entry| if (bucket.maybe_entry) |*entry|
if (key_context.equals(entry.key, key)) return entry.value; if (key_context.equals(entry.key, key)) return &entry.value;
} }
return null; return null;