summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2020-12-18 16:52:55 +0100
committerDavid Robillard <d@drobilla.net>2020-12-18 17:38:39 +0100
commitb8c3fa9e5476d5d6bb5413f9d52d406475f9e900 (patch)
tree497bfa55734f13801fbddc8b966167b110c0a446
parentdfe0b71df1dde284f1aa9cf7ba3d85e19ce1b5a5 (diff)
downloadlilv-b8c3fa9e5476d5d6bb5413f9d52d406475f9e900.tar.gz
lilv-b8c3fa9e5476d5d6bb5413f9d52d406475f9e900.tar.bz2
lilv-b8c3fa9e5476d5d6bb5413f9d52d406475f9e900.zip
Add lilv_path_filename()
-rw-r--r--src/filesystem.c22
-rw-r--r--src/filesystem.h8
-rw-r--r--test/test_filesystem.c23
3 files changed, 53 insertions, 0 deletions
diff --git a/src/filesystem.c b/src/filesystem.c
index c8a58c1..0ec9802 100644
--- a/src/filesystem.c
+++ b/src/filesystem.c
@@ -193,6 +193,28 @@ lilv_path_parent(const char* path)
}
char*
+lilv_path_filename(const char* path)
+{
+ const size_t path_len = strlen(path);
+ size_t last_sep = path_len;
+ for (size_t i = 0; i < path_len; ++i) {
+ if (lilv_is_dir_sep(path[i])) {
+ last_sep = i;
+ }
+ }
+
+ if (last_sep >= path_len) {
+ return lilv_strdup(path);
+ }
+
+ const size_t ret_len = path_len - last_sep;
+ char* const ret = (char*)calloc(ret_len + 1, 1);
+
+ strncpy(ret, path + last_sep + 1, ret_len);
+ return ret;
+}
+
+char*
lilv_path_join(const char* a, const char* b)
{
if (!a) {
diff --git a/src/filesystem.h b/src/filesystem.h
index 14f25d7..319dd49 100644
--- a/src/filesystem.h
+++ b/src/filesystem.h
@@ -60,6 +60,14 @@ lilv_path_relative_to(const char* path, const char* base);
char*
lilv_path_parent(const char* path);
+/**
+ Return the filename component of `path` without any directories.
+
+ Returns the empty string if `path` is the root path.
+*/
+char*
+lilv_path_filename(const char* path);
+
/// Join path `a` and path `b` with a single directory separator between them
char*
lilv_path_join(const char* a, const char* b);
diff --git a/test/test_filesystem.c b/test/test_filesystem.c
index 8c7b1ba..a3288ed 100644
--- a/test/test_filesystem.c
+++ b/test/test_filesystem.c
@@ -130,6 +130,28 @@ test_path_parent(void)
}
static void
+test_path_filename(void)
+{
+ // Cases from cppreference.com for std::filesystem::path::filename
+ assert(equals(lilv_path_filename("/foo/bar.txt"), "bar.txt"));
+ assert(equals(lilv_path_filename("/foo/.bar"), ".bar"));
+ assert(equals(lilv_path_filename("/foo/bar/"), ""));
+ assert(equals(lilv_path_filename("/foo/."), "."));
+ assert(equals(lilv_path_filename("/foo/.."), ".."));
+ assert(equals(lilv_path_filename("."), "."));
+ assert(equals(lilv_path_filename(".."), ".."));
+ assert(equals(lilv_path_filename("/"), ""));
+ assert(equals(lilv_path_filename("//host"), "host"));
+
+#ifdef _WIN32
+ assert(equals(lilv_path_filename("C:/foo/bar.txt"), "bar.txt"));
+ assert(equals(lilv_path_filename("C:\\foo\\bar.txt"), "bar.txt"));
+ assert(equals(lilv_path_filename("foo/bar.txt"), "bar.txt"));
+ assert(equals(lilv_path_filename("foo\\bar.txt"), "bar.txt"));
+#endif
+}
+
+static void
test_path_join(void)
{
assert(lilv_path_join(NULL, NULL) == NULL);
@@ -458,6 +480,7 @@ main(void)
test_path_absolute();
test_path_relative_to();
test_path_parent();
+ test_path_filename();
test_path_join();
test_path_canonical();
test_path_exists();