diff options
| author | Zuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian> | 2026-01-11 17:47:30 +0000 |
|---|---|---|
| committer | Zuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian> | 2026-01-11 17:47:30 +0000 |
| commit | ba5ee94871e670fbe1ea091dd5731e593df0b29f (patch) | |
| tree | 3b706a9ab11effa4acb094482f3d657c986ef501 /std/path.zc | |
| parent | aba9191ab3ef0699b0f9507ee3d03161f9ee7771 (diff) | |
Some std for you
Diffstat (limited to 'std/path.zc')
| -rw-r--r-- | std/path.zc | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/std/path.zc b/std/path.zc new file mode 100644 index 0000000..6a9531d --- /dev/null +++ b/std/path.zc @@ -0,0 +1,117 @@ + +import "./core.zc" +import "./string.zc" +import "./option.zc" +import "./vec.zc" + +struct Path { + str: String; +} + +impl Path { + fn new(s: char*) -> Path { + return Path { str: String::new(s) }; + } + + fn from_string(s: String) -> Path { + return Path { str: s }; + } + + fn c_str(self) -> char* { + return self.str.c_str(); + } + + fn clone(self) -> Path { + return Path { str: String::new(self.str.c_str()) }; + } + + fn join(self, other: char*) -> Path { + var base_len = self.str.length(); + var new_s = String::from(self.str.c_str()); + + if (base_len > 0) { + var last = self.str.vec.get(base_len - 1); + if (last != '/' && last != '\\') { + var sep = String::new("/"); + new_s.append(sep); + } + } + + var other_str = String::new(other); + new_s.append(other_str); + + return Path { str: new_s }; + } + + + fn extension(self) -> Option<String> { + var s = self.c_str(); + var len = self.str.length(); + + for (var i: usize = len; i > 0; i = i - 1) { + var 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(); + } + + fn file_name(self) -> Option<String> { + var s = self.c_str(); + var len = self.str.length(); + + if (len == 0) return Option<String>::None(); + + // Remove trailing separators + var end = len; + while (end > 0 && (s[end-1] == '/' || s[end-1] == '\\')) { + end = end - 1; + } + if (end == 0) return Option<String>::None(); // Root + + var start = end; + while (start > 0 && s[start-1] != '/' && s[start-1] != '\\') { + start = start - 1; + } + + return Option<String>::Some(self.str.substring(start, end - start)); + } + + fn parent(self) -> Option<Path> { + var s = self.c_str(); + var len = self.str.length(); + if (len == 0) return Option<Path>::None(); + + // Trim trailing separators + var 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("/")); + } + + var parent_str = self.str.substring(0, end); + return Option<Path>::Some(Path { str: parent_str }); + } +} |
