One of my projects is a torrent client in Zig. Provided the code below, I am wondering what are the lifetimes of short_path and full_path and where are they allocated (function caller call stack?).
const std = @import("std");
const log = std.log.scoped(.files);
/// `TorrentFile` is a structure representing a torrent file, its paths and contents
pub const TorrentFile = struct {
/// `short_path` is the base name of the file (last segment of the path).
short_path: []const u8,
/// `full_path` is the complete path of the file.
full_path: []const u8,
/// `contents` are the contents of the file read into memory.
contents: []const u8,
/// `allocator` is the allocator used to manage memory for this structure.
allocator: std.mem.Allocator,
/// Opens and reads the contents of a file into memory, returning a `TorrentFile` structure.
///
/// This function takes an allocator and the file path. It opens the file, reads its contents
/// into memory, and returns a `TorrentFile` structure.
/// The caller of the function needs to call `close` to free allocated memory.
pub fn read(allocator: std.mem.Allocator, path: []const u8) !@This() {
log.info("Opening file: {s}", .{path});
const torrent_file = try std.fs.cwd().openFile(path, .{});
defer torrent_file.close();
const basename = std.fs.path.basename(path);
log.debug("File base name is: {s}", .{basename});
const file_size = try torrent_file.getEndPos();
log.debug("Torrent file {s} size is: {d}", .{ basename, file_size });
const buffer = try allocator.alloc(u8, file_size);
errdefer allocator.free(buffer);
const read_bytes = try torrent_file.readAll(buffer);
log.debug("Read {d} bytes from file: {s}:", .{ read_bytes, basename });
return .{
.short_path = basename,
.full_path = path,
.contents = buffer,
.allocator = allocator,
};
}
/// Frees the memory allocated for the file contents.
///
/// This function should be called to release the memory allocated by the `read` function
/// when the `TorrentFile` structure is no longer needed.
pub fn close(self: @This()) void {
self.allocator.free(self.contents);
}
};