std/path.zc
Rama main · réplica de lectura del repositorio original.
import "./core.zc"
import "./string.zc"
import "./option.zc"
import "./vec.zc"
struct Path {
str: String;
}
impl Path {
/// Creates a Path from a string.
fn new(s: char*) -> Path {
return Path { str: String::new(s) };
}
fn from_string(s: String) -> Path {
return Path { str: s };
}
/// Returns the underlying C string.
fn c_str(self) -> char* {
return self.str.c_str();
}
fn clone(self) -> Path {
return Path { str: String::new(self.str.c_str()) };
}
/// Joins a component onto the path.
fn join(self, other: char*) -> Path {
let base_len = self.str.length();
let new_s = String::from(self.str.c_str());
if (base_len > 0) {
let last = self.str.vec.get(base_len - 1);
if (last != '/' && last != '\\') {
let sep = String::new("/");
new_s.append(&sep);
}
}
let other_str = String::new(other);
new_s.append(&other_str);
return Path { str: new_s };
}
/// Returns the file extension, or `None`.
fn extension(self) -> Option<String> {
let s = self.c_str();
let len = self.str.length();
for (let i: usize = len; i > 0; i = i - 1) {
let c = s[i-1];
if (c == '.') {
// Check if we hit a separator before element
// e.g. /d.ir/file - found dot
// /d.ir/file.txt - found last dot
return Option<String>::Some(self.str.substring(i, len - i));
}
if (c == '/' || c == '\\') {
return Option<String>::None();
}
}
return Option<String>::None();
}
/// Returns the final path component, or `None`.
fn file_name(self) -> Option<String> {
let s = self.c_str();
let len = self.str.length();
if (len == 0) return Option<String>::None();
// Remove trailing separators
let end = len;
while (end > 0 && (s[end-1] == '/' || s[end-1] == '\\')) {
end = end - 1;
}
if (end == 0) return Option<String>::None(); // Root
let start = end;
while (start > 0 && s[start-1] != '/' && s[start-1] != '\\') {
start = start - 1;
}
return Option<String>::Some(self.str.substring(start, end - start));
}
/// Returns the parent directory, or `None`.
fn parent(self) -> Option<Path> {
let s = self.c_str();
let len = self.str.length();
if (len == 0) return Option<Path>::None();
// Trim trailing separators
let end = len;
while (end > 0 && (s[end-1] == '/' || s[end-1] == '\\')) {
end = end - 1;
}
// Scan back to separator
while (end > 0 && s[end-1] != '/' && s[end-1] != '\\') {
end = end - 1;
}
if (end == 0) return Option<Path>::None();
while (end > 0 && (s[end-1] == '/' || s[end-1] == '\\')) {
end = end - 1;
}
if (end == 0) {
// Must be root
return Option<Path>::Some(Path::new("/"));
}
let parent_str = self.str.substring(0, end);
return Option<Path>::Some(Path { str: parent_str });
}
/// Frees the path memory.
fn free(self) {
self.str.free();
}
}