From 116e7326a4a1f954881831e1cbb995d423caf446 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 15 Oct 2022 16:08:27 +0200 Subject: [PATCH] libc: Implement dirname() and basename() --- libs/libc/include/libgen.h | 9 ++++++-- libs/libc/src/libgen.cpp | 44 ++++++++++++++++++++++++++++++++++---- 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/libs/libc/include/libgen.h b/libs/libc/include/libgen.h index c42384f4..a6479447 100644 --- a/libs/libc/include/libgen.h +++ b/libs/libc/include/libgen.h @@ -6,8 +6,13 @@ extern "C" { #endif - char* basename(char*); // Not implemented. - char* dirname(char*); // Not implemented. + /* Returns the last component of a path. This function is allowed to modify the string passed to it, so it should + * probably be a copy of another string. */ + char* basename(char* path); + + /* Returns the parent directory of a path. This function is allowed to modify the string passed to it, so it should + * probably be a copy of another string. */ + char* dirname(char* path); #ifdef __cplusplus } diff --git a/libs/libc/src/libgen.cpp b/libs/libc/src/libgen.cpp index d7aa4630..19c2d717 100644 --- a/libs/libc/src/libgen.cpp +++ b/libs/libc/src/libgen.cpp @@ -1,15 +1,51 @@ #include #include +#include + +static char dot[] = "."; extern "C" { - char* basename(char*) + char* basename(char* path) { - NOT_IMPLEMENTED("basename"); + // If path is NULL, or the string's length is 0, return . + if (!path) return dot; + size_t len = strlen(path); + if (!len) return dot; + + // Strip trailing slashes. + char* it = path + len - 1; + while (*it == '/' && it != path) { it--; } + *(it + 1) = 0; + if (it == path) return path; + + // Return path from the first character if there are no more slashes, or from the first character after the last + // slash. + char* beg = strrchr(path, '/'); + if (!beg) return path; + return beg + 1; } - char* dirname(char*) + char* dirname(char* path) { - NOT_IMPLEMENTED("dirname"); + // If path is NULL, or the string's length is 0, return . + if (!path) return dot; + size_t len = strlen(path); + if (!len) return dot; + + // Strip trailing slashes. + char* it = path + len - 1; + while (*it == '/' && it != path) { it--; } + *(char*)(it + 1) = 0; + if (it == path) return path; + + // Search for the last slash. If there is none, return . + // Otherwise, we end the string there and return. + char* end = strrchr(path, '/'); + if (!end) return dot; + if (end != path) *end = 0; + else + *(end + 1) = 0; + return path; } } \ No newline at end of file