zig/src/Package.zig
Isaac Freund c102eb83e6
stage2: free Package resources
Without this commit we leak file descriptors and memory
2020-12-17 19:32:40 +01:00

75 lines
2.1 KiB
Zig

const Package = @This();
const std = @import("std");
const fs = std.fs;
const mem = std.mem;
const Allocator = mem.Allocator;
const Compilation = @import("Compilation.zig");
pub const Table = std.StringHashMapUnmanaged(*Package);
root_src_directory: Compilation.Directory,
/// Relative to `root_src_directory`. May contain path separators.
root_src_path: []const u8,
table: Table = .{},
parent: ?*Package = null,
/// Allocate a Package. No references to the slices passed are kept.
pub fn create(
gpa: *Allocator,
/// Null indicates the current working directory
root_src_dir_path: ?[]const u8,
/// Relative to root_src_dir_path
root_src_path: []const u8,
) !*Package {
const ptr = try gpa.create(Package);
errdefer gpa.destroy(ptr);
const owned_dir_path = if (root_src_dir_path) |p| try gpa.dupe(u8, p) else null;
errdefer if (owned_dir_path) |p| gpa.free(p);
const owned_src_path = try gpa.dupe(u8, root_src_path);
errdefer gpa.free(owned_src_path);
ptr.* = .{
.root_src_directory = .{
.path = owned_dir_path,
.handle = if (owned_dir_path) |p| try fs.cwd().openDir(p, .{}) else fs.cwd(),
},
.root_src_path = owned_src_path,
};
return ptr;
}
/// Free all memory associated with this package and recursively call destroy
/// on all packages in its table
pub fn destroy(pkg: *Package, gpa: *Allocator) void {
gpa.free(pkg.root_src_path);
// If root_src_directory.path is null then the handle is the cwd()
// which shouldn't be closed.
if (pkg.root_src_directory.path) |p| {
gpa.free(p);
pkg.root_src_directory.handle.close();
}
{
var it = pkg.table.iterator();
while (it.next()) |kv| {
kv.value.destroy(gpa);
gpa.free(kv.key);
}
}
pkg.table.deinit(gpa);
gpa.destroy(pkg);
}
pub fn add(pkg: *Package, gpa: *Allocator, name: []const u8, package: *Package) !void {
try pkg.table.ensureCapacity(gpa, pkg.table.count() + 1);
const name_dupe = try mem.dupe(gpa, u8, name);
pkg.table.putAssumeCapacityNoClobber(name_dupe, package);
}