From b8c3fa9e5476d5d6bb5413f9d52d406475f9e900 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Fri, 18 Dec 2020 16:52:55 +0100 Subject: Add lilv_path_filename() --- src/filesystem.c | 22 ++++++++++++++++++++++ src/filesystem.h | 8 ++++++++ test/test_filesystem.c | 23 +++++++++++++++++++++++ 3 files changed, 53 insertions(+) diff --git a/src/filesystem.c b/src/filesystem.c index c8a58c1..0ec9802 100644 --- a/src/filesystem.c +++ b/src/filesystem.c @@ -192,6 +192,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) { 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 @@ -129,6 +129,28 @@ test_path_parent(void) assert(equals(lilv_path_parent("a"), ".")); } +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) { @@ -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(); -- cgit v1.2.1