commit 6e56868c2a71bd7aece81349f3fe5ec4271dc61c
parent 398e4c23008c4a1f3ac90be31f1c0727984d053f
Author: Drew DeVault <sir@cmpwn.com>
Date: Sat, 27 Feb 2021 09:50:23 -0500
path: add basename, dirname
Diffstat:
2 files changed, 58 insertions(+), 0 deletions(-)
diff --git a/path/names.ha b/path/names.ha
@@ -0,0 +1,52 @@
+use bytes;
+use strings;
+use io;
+
+// Returns the directory name for a given path. For a path to a file name, this
+// returns the directory in which that file resides. For a path to a directory,
+// this returns the path to its parent directory. The return value is borrowed
+// from the input, use [dup] to extend its lifetime.
+export fn dirname(path: path::path) path::path = {
+ let b = pathbytes(normalize(path));
+ let i = bytes::rindex(b, PATHSEP) as size;
+ if (i == 0) {
+ b = [PATHSEP];
+ i += 1;
+ };
+ return
+ if (path is str) strings::from_utf8_unsafe(b[..i])
+ else b[..i];
+};
+
+@test fn dirname() void = {
+ let p: path = "/foo/bar";
+ assert(dirname(p) as str == "/foo");
+ let p: path = "/foo";
+ assert(dirname(p) as str == "/");
+ let p: path = "/";
+ assert(dirname(p) as str == "/");
+};
+
+// Returns the final component of a given path. For a path to a file name, this
+// returns the file name. For a path to a directory, this returns the directory
+// name. The return value is borrowed from the input, use [dup] to extend its
+// lifetime.
+export fn basename(path: path::path) path::path = {
+ let b = pathbytes(normalize(path));
+ let i = if (len(b) == 1) {
+ b = [PATHSEP];
+ 0z;
+ } else bytes::rindex(b, PATHSEP) as size + 1;
+ return
+ if (path is str) strings::from_utf8_unsafe(b[i..])
+ else b[i..];
+};
+
+@test fn basename() void = {
+ let p: path = "/foo/bar";
+ assert(basename(p) as str == "bar");
+ let p: path = "/foo";
+ assert(basename(p) as str == "foo");
+ let p: path = "/";
+ assert(basename(p) as str == "/");
+};
diff --git a/path/norm.ha b/path/norm.ha
@@ -0,0 +1,6 @@
+// Normalizes a path, merging successive path separators, and resolving . and ..
+// components. Modifies the path in-place and returns the same object.
+export fn normalize(p: path::path) path::path = {
+ // TODO
+ return p;
+};