lib/sys/src/path.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2 const capabilities = @import("capabilities.zig");
3
4 pub const required_capabilities = capabilities.pure();
5
6 pub const separator = std.fs.path.sep;
7
8 pub fn join(
9 allocator: std.mem.Allocator,
10 parts: []const []const u8,
11 ) std.mem.Allocator.Error![]u8 {
12 return std.fs.path.join(allocator, parts);
13 }
14
15 pub fn dirname(path: []const u8) ?[]const u8 {
16 return std.fs.path.dirname(path);
17 }
18
19 pub fn basename(path: []const u8) []const u8 {
20 return std.fs.path.basename(path);
21 }
22
23 pub fn extension(path: []const u8) []const u8 {
24 return std.fs.path.extension(path);
25 }
26
27 pub fn isAbsolute(path: []const u8) bool {
28 return std.fs.path.isAbsolute(path);
29 }
30
31 pub fn trimTrailingSeparators(path: []const u8) []const u8 {
32 var end = path.len;
33 while (end > 1 and isSeparator(path[end - 1])) : (end -= 1) {}
34 return path[0..end];
35 }
36
37 pub fn isSeparator(byte: u8) bool {
38 return std.fs.path.isSep(byte);
39 }
40
41 test "trimTrailingSeparators preserves root" {
42 try std.testing.expectEqualStrings("/", trimTrailingSeparators("/"));
43 try std.testing.expectEqualStrings("/tmp/tiny", trimTrailingSeparators("/tmp/tiny///"));
44 }
45
46 test "path parts expose std path policy" {
47 try std.testing.expectEqualStrings("file.zig", basename("/tmp/file.zig"));
48 try std.testing.expectEqualStrings(".zig", extension("/tmp/file.zig"));
49 try std.testing.expect(isAbsolute("/tmp"));
50 }