diff --git a/src/engine/sys.zig b/src/engine/sys.zig index 79167f1..4dc6cdf 100644 --- a/src/engine/sys.zig +++ b/src/engine/sys.zig @@ -281,8 +281,7 @@ pub const FileSystem = union(enum) { /// pub const Path = struct { file_system: *FileSystem, - length: u8, - buffer: [max]u8, + path: oar.Path, /// /// With files typically being backed by a block device, they can produce a variety of @@ -430,11 +429,10 @@ pub const FileSystem = union(enum) { } }; - entry.* = archive.instance.find(path.buffer[0 .. path.length]) catch |err| - return switch (err) { - error.FileInaccessible => error.FileNotFound, - error.EntryNotFound => error.FileNotFound, - }; + entry.* = archive.instance.find(path.path) catch |err| return switch (err) { + error.FileInaccessible => error.FileNotFound, + error.EntryNotFound => error.FileNotFound, + }; return FileAccess{ .context = entry, @@ -460,15 +458,15 @@ pub const FileSystem = union(enum) { var path_buffer = std.mem.zeroes([4096]u8); const seperator_length = @boolToInt(native[native.len - 1] != seperator); - if ((native.len + seperator_length + path.length) >= + if ((native.len + seperator_length + path.path.length) >= path_buffer.len) return error.FileNotFound; std.mem.copy(u8, path_buffer[0 ..], native); if (seperator_length != 0) path_buffer[native.len] = seperator; - std.mem.copy(u8, path_buffer[native.len .. - path_buffer.len], path.buffer[0 .. path.length]); + std.mem.copy(u8, path_buffer[native.len .. path_buffer. + len], path.path.buffer[0 .. path.path.length]); ext.SDL_ClearError(); @@ -592,8 +590,7 @@ pub const FileSystem = union(enum) { pub fn joinedPath(file_system: *FileSystem, sequences: []const []const u8) PathError!Path { var path = Path{ .file_system = file_system, - .buffer = std.mem.zeroes([Path.max]u8), - .length = 0, + .path = oar.Path.empty, }; if (sequences.len != 0) { @@ -607,25 +604,25 @@ pub const FileSystem = union(enum) { while (components.next()) |component| if (component.len != 0) { for (component) |byte| { - if (path.length == Path.max) return error.TooLong; + if (path.path.length == Path.max) return error.TooLong; - path.buffer[path.length] = byte; - path.length += 1; + path.path.buffer[path.path.length] = byte; + path.path.length += 1; } if (components.hasNext()) { - if (path.length == Path.max) return error.TooLong; + if (path.path.length == Path.max) return error.TooLong; - path.buffer[path.length] = '/'; - path.length += 1; + path.path.buffer[path.path.length] = '/'; + path.path.length += 1; } }; if (index < last_sequence_index) { - if (path.length == Path.max) return error.TooLong; + if (path.path.length == Path.max) return error.TooLong; - path.buffer[path.length] = '/'; - path.length += 1; + path.path.buffer[path.path.length] = '/'; + path.path.length += 1; } }; } diff --git a/src/oar/main.zig b/src/oar/main.zig index 8b74a32..98db1a2 100644 --- a/src/oar/main.zig +++ b/src/oar/main.zig @@ -26,7 +26,10 @@ pub const Archive = struct { /// As the archive is queried via [find], the cache is lazily assembled with the absolute /// offsets of each queried file. /// - const IndexCache = ona.table.Hashed([]const u8, u64, ona.table.string_context); + const IndexCache = ona.table.Hashed(Path, u64, .{ + .equals = Path.equals, + .hash = Path.hash, + }); /// /// Deinitializes the index cache of `archive`, freeing all associated memory. @@ -43,12 +46,12 @@ pub const Archive = struct { /// /// The found [Entry] value is returned or a [FindError] if it failed to be found. /// - pub fn find(archive: *Archive, entry_path: []const u8) FindError!Entry { + pub fn find(archive: *Archive, entry_path: Path) FindError!Entry { return Entry{ .header = find_header: { var header = Entry.Header{ .revision = 0, - .path = std.mem.zeroes(Path), + .path = Path.empty, .file_size = 0, .absolute_offset = 0 }; @@ -73,7 +76,7 @@ pub const Archive = struct { // Read first entry. while ((try archive.file_access.read(mem.asBytes(&header))) == header_size) { - if (mem.eql(u8, entry_path, header.path.buffer[0 .. header.path.length])) { + if (entry_path.equals(header.path)) { // If caching fails... oh well... archive.index_cache.insert(entry_path, header.absolute_offset) catch {}; @@ -156,11 +159,33 @@ pub const Entry = struct { }; /// +/// Unique identifier pointing to an entry within an archive. /// +/// A path does not do any verification that the given entry pointed to actually exists. /// pub const Path = extern struct { buffer: [255]u8, length: u8, + + /// + /// An empty [Path] with a length of `0`. + /// + pub const empty = std.mem.zeroes(Path); + + /// + /// Returns `true` if `this_path` is equal to `that_path, otherwise `false`. + /// + pub fn equals(this_path: Path, that_path: Path) bool { + return ona.io.equalsBytes(this_path.buffer[0 ..this_path. + length], that_path.buffer[0 .. that_path.length]); + } + + /// + /// Returns the hash of the text in `path`. + /// + pub fn hash(path: Path) usize { + return ona.io.hashBytes(path.buffer[0 .. path.length]); + } }; ///