commit 5d22b63c9cb0325eeadeddb957f6369439803d43
parent bae714096f1a0571b82261d33644223fb2957cc2
Author: Drew DeVault <sir@cmpwn.com>
Date: Sun, 7 Mar 2021 09:25:06 -0500
path: add path::extension
Diffstat:
2 files changed, 50 insertions(+), 6 deletions(-)
diff --git a/hare/module/scan.ha b/hare/module/scan.ha
@@ -79,19 +79,21 @@ export fn lookup(ctx: *context, name: ast::ident) (version | error) = {
return module_not_found;
};
-// TODO: Filter inputs by build tags
fn eligible(ctx: *context, name: path::path) bool = {
if (!(name is str)) {
return false;
};
- let name = name as str;
+ let eligible = false;
+ const ext = path::extension(name);
static const exts = [".ha", ".s"];
for (let i = 0z; i < len(exts); i += 1) {
- if (strings::has_suffix(name, exts[i])) {
- return true;
+ if (exts[i] == ext) {
+ eligible = true;
+ break;
};
};
- return false;
+ // TODO: Check build tags as well
+ return eligible;
};
fn scan_file(
diff --git a/path/names.ha b/path/names.ha
@@ -1,4 +1,5 @@
use bytes;
+use encoding::utf8;
use strings;
// Returns the directory name for a given path. For a path to a file name, this
@@ -61,4 +62,45 @@ export fn basename(path: path::path) path::path = {
};
// Returns true if the given path is a root directory.
-export fn is_root(path: path::path) bool = len(pathbytes(path)) == 1;
+export fn is_root(path: path::path) bool = {
+ let b = pathbytes(path);
+ if (len(b) == 0) {
+ return false;
+ };
+ return b[0] == PATHSEP;
+};
+
+// Returns the file extension for a path. This presumes that the file extension
+// is a valid UTF-8 string, if not, it will return an empty string. The return
+// value is borrowed from the input, see [strings::dup] to extend its lifetime.
+//
+// The return value includes the '.' character.
+//
+// extension("foo/example") => ""
+// extension("foo/example.txt") => ".txt"
+// extension("foo/example.tar.gz") => ".tar.gz"
+export fn extension(p: path::path) str = {
+ let b = pathbytes(p);
+ if (len(b) == 0 || b[len(b) - 1] == PATHSEP) {
+ return "";
+ };
+ let b = pathbytes(basename(p));
+ let i = match (bytes::index(b, '.': u32: u8)) {
+ void => return "",
+ z: size => z,
+ };
+ let e = b[i..];
+ return match (strings::try_from_utf8(e)) {
+ utf8::invalid => "",
+ s: str => s,
+ };
+};
+
+@test fn extension() void = {
+ assert(extension("") == "");
+ assert(extension("foo/") == "");
+ assert(extension("foo/bar") == "");
+ assert(extension("foo/bar.txt") == ".txt");
+ assert(extension("foo/bar.tar.gz") == ".tar.gz");
+ assert(extension("foo.bar/baz.ha") == ".ha");
+};