65 lines
1.9 KiB
Zig
65 lines
1.9 KiB
Zig
const debug = @import("../debug.zig");
|
|
const assert = debug.assert;
|
|
const mem = @import("../mem.zig");
|
|
const Allocator = mem.Allocator;
|
|
|
|
/// Allocates memory for the result, which must be freed by the caller.
|
|
pub fn join(allocator: &Allocator, paths: ...) -> %[]u8 {
|
|
assert(paths.len >= 2);
|
|
var total_paths_len: usize = paths.len; // 1 slash per path
|
|
{
|
|
comptime var path_i = 0;
|
|
inline while (path_i < paths.len; path_i += 1) {
|
|
const arg = ([]const u8)(paths[path_i]);
|
|
total_paths_len += arg.len;
|
|
}
|
|
}
|
|
|
|
const buf = %return allocator.alloc(u8, total_paths_len);
|
|
%defer allocator.free(buf);
|
|
|
|
var buf_index: usize = 0;
|
|
comptime var path_i = 0;
|
|
inline while (true) {
|
|
const arg = ([]const u8)(paths[path_i]);
|
|
path_i += 1;
|
|
mem.copy(u8, buf[buf_index...], arg);
|
|
buf_index += arg.len;
|
|
if (path_i >= paths.len) break;
|
|
if (arg[arg.len - 1] != '/') {
|
|
buf[buf_index] = '/';
|
|
buf_index += 1;
|
|
}
|
|
}
|
|
|
|
return buf[0...buf_index];
|
|
}
|
|
|
|
test "os.path.join" {
|
|
assert(mem.eql(u8, %%join(&debug.global_allocator, "/a/b", "c"), "/a/b/c"));
|
|
assert(mem.eql(u8, %%join(&debug.global_allocator, "/a/b/", "c"), "/a/b/c"));
|
|
|
|
assert(mem.eql(u8, %%join(&debug.global_allocator, "/", "a", "b/", "c"), "/a/b/c"));
|
|
assert(mem.eql(u8, %%join(&debug.global_allocator, "/a/", "b/", "c"), "/a/b/c"));
|
|
}
|
|
|
|
pub fn dirname(allocator: &Allocator, path: []const u8) -> %[]u8 {
|
|
if (path.len != 0) {
|
|
var last_index: usize = path.len - 1;
|
|
if (path[last_index] == '/')
|
|
last_index -= 1;
|
|
|
|
var i: usize = last_index;
|
|
while (true) {
|
|
const c = path[i];
|
|
if (c == '/')
|
|
return mem.dupe(allocator, u8, path[0...i]);
|
|
if (i == 0)
|
|
break;
|
|
i -= 1;
|
|
}
|
|
}
|
|
|
|
return mem.dupe(allocator, u8, ".");
|
|
}
|