zig/std/os/path.zig

65 lines
1.9 KiB
Zig
Raw Normal View History

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, ".");
}