summaryrefslogtreecommitdiff
path: root/std/path.zc
diff options
context:
space:
mode:
authorZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-01-11 17:47:30 +0000
committerZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-01-11 17:47:30 +0000
commitba5ee94871e670fbe1ea091dd5731e593df0b29f (patch)
tree3b706a9ab11effa4acb094482f3d657c986ef501 /std/path.zc
parentaba9191ab3ef0699b0f9507ee3d03161f9ee7771 (diff)
Some std for you
Diffstat (limited to 'std/path.zc')
-rw-r--r--std/path.zc117
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 });
+ }
+}