init
After init, next will return the first component after the root
(there is no need to call first after init).
To iterate backwards (from the end of the path to the beginning), call last
after init and then iterate via previous calls.
For Windows paths, error.BadPathName is returned if the path has an explicit
namespace prefix (\\.\, \\?\, or \??\) or if it is a UNC path with more
than two path separators at the beginning.
Function parameters
Parameters
- path:[]const T
Type definitions in this namespace
Types
Returns if the given byte is a valid path separator
Functions
- isSep
- Returns if the given byte is a valid path separator
- join
- Naively combines a series of paths with the native path separator.
- joinZ
- Naively combines a series of paths with the native path separator and null terminator.
- resolve
- On Windows, this calls `resolveWindows` and on POSIX it calls `resolvePosix`.
- resolveWindows
- This function is like a series of `cd` statements executed one after another.
- resolvePosix
- This function is like a series of `cd` statements executed one after another.
- dirname
- Strip the last component from a file path.
- relative
- Returns the relative path from `from` to `to`.
- extension
- Searches for a file extension separated by a `.` and returns the string after that `.`.
- stem
- Returns the last component of this path without its extension (if any):
- ComponentIterator
- A path component iterator that can move forwards and backwards.
- fmtAsUtf8Lossy
- Format a path encoded as bytes for display as UTF-8.
- fmtWtf16LeAsUtf8Lossy
- Format a path encoded as WTF-16 LE for display as UTF-8.
= '\\'
Values
- sep_windows
- = '\\'
- sep_posix
- = '/'
- sep
- = switch (native_os) { .windows, .uefi => sep_windows, else => sep_posix, }
- sep_str_windows
- = "\\"
- sep_str_posix
- = "/"
- sep_str
- = switch (native_os) { .windows, .uefi => sep_str_windows, else => sep_str_posix, }
- delimiter_windows
- = ';'
- delimiter_posix
- = ':'
- delimiter
- = if (native_os == .windows) delimiter_windows else delimiter_posix
Source
Implementation
pub fn init(path: []const T) InitError!Self {
const root_end_index: usize = switch (path_type) {
.posix, .uefi => posix: {
// Root on UEFI and POSIX only differs by the path separator
var root_end_index: usize = 0;
while (true) : (root_end_index += 1) {
if (root_end_index >= path.len or !path_type.isSep(T, path[root_end_index])) {
break;
}
}
break :posix root_end_index;
},
.windows => windows: {
// Namespaces other than the Win32 file namespace are tricky
// and basically impossible to determine a 'root' for, since it's
// possible to construct an effectively arbitrarily long 'root',
// e.g. `\\.\GLOBALROOT\??\UNC\localhost\C$\foo` is a
// possible path that would be effectively equivalent to
// `C:\foo`, and the `GLOBALROOT\??\` part can also be recursive,
// so `GLOBALROOT\??\GLOBALROOT\??\...` would work for any number
// of repetitions. Therefore, paths with an explicit namespace prefix
// (\\.\, \??\, \\?\) are not allowed here.
if (std.os.windows.getNamespacePrefix(T, path) != .none) {
return error.BadPathName;
}
const windows_path_type = std.os.windows.getUnprefixedPathType(T, path);
break :windows switch (windows_path_type) {
.relative => 0,
.root_local_device => path.len,
.rooted => 1,
.unc_absolute => unc: {
var end_index: usize = 2;
// Any extra separators between the first two and the server name are not allowed
// and will always lead to STATUS_OBJECT_PATH_INVALID if it is attempted
// to be used.
if (end_index < path.len and path_type.isSep(T, path[end_index])) {
return error.BadPathName;
}
// Server
while (end_index < path.len and !path_type.isSep(T, path[end_index])) {
end_index += 1;
}
// Slash(es) after server
while (end_index < path.len and path_type.isSep(T, path[end_index])) {
end_index += 1;
}
// Share
while (end_index < path.len and !path_type.isSep(T, path[end_index])) {
end_index += 1;
}
// Slash(es) after share
while (end_index < path.len and path_type.isSep(T, path[end_index])) {
end_index += 1;
}
break :unc end_index;
},
.drive_absolute => drive: {
var end_index: usize = 3;
while (end_index < path.len and path_type.isSep(T, path[end_index])) {
end_index += 1;
}
break :drive end_index;
},
.drive_relative => 2,
};
},
};
return .{
.path = path,
.root_end_index = root_end_index,
.start_index = root_end_index,
.end_index = root_end_index,
};
}