mirror of
https://github.com/ziglang/zig.git
synced 2025-12-25 15:43:06 +00:00
- hash/eql functions moved into a Context object
- *Context functions pass an explicit context
- *Adapted functions pass specialized keys and contexts
- new getPtr() function returns a pointer to value
- remove functions renamed to fetchRemove
- new remove functions return bool
- removeAssertDiscard deleted, use assert(remove(...)) instead
- Keys and values are stored in separate arrays
- Entry is now {*K, *V}, the new KV is {K, V}
- BufSet/BufMap functions renamed to match other set/map types
- fixed iterating-while-modifying bug in src/link/C.zig
124 lines
3.7 KiB
Zig
124 lines
3.7 KiB
Zig
const Package = @This();
|
|
|
|
const std = @import("std");
|
|
const fs = std.fs;
|
|
const mem = std.mem;
|
|
const Allocator = mem.Allocator;
|
|
const assert = std.debug.assert;
|
|
|
|
const Compilation = @import("Compilation.zig");
|
|
const Module = @import("Module.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,
|
|
/// Whether to free `root_src_directory` on `destroy`.
|
|
root_src_directory_owned: bool = false,
|
|
|
|
/// 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,
|
|
.root_src_directory_owned = true,
|
|
};
|
|
|
|
return ptr;
|
|
}
|
|
|
|
pub fn createWithDir(
|
|
gpa: *Allocator,
|
|
directory: Compilation.Directory,
|
|
/// Relative to `directory`. If null, means `directory` is the root src dir
|
|
/// and is owned externally.
|
|
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_src_path = try gpa.dupe(u8, root_src_path);
|
|
errdefer gpa.free(owned_src_path);
|
|
|
|
if (root_src_dir_path) |p| {
|
|
const owned_dir_path = try directory.join(gpa, &[1][]const u8{p});
|
|
errdefer gpa.free(owned_dir_path);
|
|
|
|
ptr.* = .{
|
|
.root_src_directory = .{
|
|
.path = owned_dir_path,
|
|
.handle = try directory.handle.openDir(p, .{}),
|
|
},
|
|
.root_src_directory_owned = true,
|
|
.root_src_path = owned_src_path,
|
|
};
|
|
} else {
|
|
ptr.* = .{
|
|
.root_src_directory = directory,
|
|
.root_src_directory_owned = false,
|
|
.root_src_path = owned_src_path,
|
|
};
|
|
}
|
|
return ptr;
|
|
}
|
|
|
|
/// Free all memory associated with this package. It does not destroy any packages
|
|
/// inside its table; the caller is responsible for calling destroy() on them.
|
|
pub fn destroy(pkg: *Package, gpa: *Allocator) void {
|
|
gpa.free(pkg.root_src_path);
|
|
|
|
if (pkg.root_src_directory_owned) {
|
|
// 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.keyIterator();
|
|
while (it.next()) |key| {
|
|
gpa.free(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);
|
|
}
|
|
|
|
pub fn addAndAdopt(parent: *Package, gpa: *Allocator, name: []const u8, child: *Package) !void {
|
|
assert(child.parent == null); // make up your mind, who is the parent??
|
|
child.parent = parent;
|
|
return parent.add(gpa, name, child);
|
|
}
|