From 04e3ded4c28c0b559620609daaae7b939d776b61 Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Sat, 15 Jun 2024 11:42:48 -0700 Subject: Add path. --- filesystem/src/filesystem.c | 40 +---------------- filesystem/src/path.c | 104 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 39 deletions(-) create mode 100644 filesystem/src/path.c (limited to 'filesystem/src') diff --git a/filesystem/src/filesystem.c b/filesystem/src/filesystem.c index f6bb693..b228e85 100644 --- a/filesystem/src/filesystem.c +++ b/filesystem/src/filesystem.c @@ -1,6 +1,7 @@ #include #include +#include #include #include @@ -54,42 +55,3 @@ cleanup: } return 0; } - -bool make_relative_path( - const char* filepath, const char* path, char* relative, - size_t relative_length) { - assert(filepath); - assert(path); - assert(relative); - - const size_t filepath_len = strlen(filepath); - const size_t path_len = strlen(path); - assert(filepath_len < relative_length); - assert(path_len < relative_length); - - // Handle empty filepath. - if (filepath_len == 0) { - memcpy(relative, path, path_len); - return true; - } - - // Search for the last / in the file path to get its parent directory. - assert(filepath_len > 0); - size_t tm_dir_len = 0; - for (tm_dir_len = strlen(filepath) - 1; tm_dir_len > 0; --tm_dir_len) { - if (filepath[tm_dir_len] == '/') { - break; - } - } - tm_dir_len++; // Preserve the backslash. - - // Copy the file path where the parent dir ends. - // Make sure there is enough space in the output. - if ((tm_dir_len + path_len + 1) >= relative_length) { - return false; - } - memcpy(relative, filepath, tm_dir_len); - memcpy(&relative[tm_dir_len], path, path_len); - - return true; -} diff --git a/filesystem/src/path.c b/filesystem/src/path.c new file mode 100644 index 0000000..2ce5a04 --- /dev/null +++ b/filesystem/src/path.c @@ -0,0 +1,104 @@ +#include + +#include +#include +#include + +static const path Empty = (path){0, 0}; + +path path_new(const char* str) { + assert(str); + const size_t size = strlen(str); + if (size > 0) { + char* data = calloc(size + 1, sizeof(char)); // +1 for null + memcpy(data, str, size); + data[size] = 0; + return (path){data, size}; + } + return Empty; +} + +void path_del(path* path) { + if (path) { + free(path->data); + path->data = 0; + path->size = 0; + } +} + +path path_parent_dir(path p) { + assert(p.data); + + if (p.size == 0) { + return Empty; + } + size_t i = p.size - 1; + // If the path ends with '/', skip the characters. + while ((i > 0) && (p.data[i] == '/')) { + i--; + } + // Search backwards for the parent dir. + for (; i > 0; --i) { + if (p.data[i] == '/') { + return (path){p.data, i + 1}; + } + } + return Empty; // No parent. +} + +path path_concat(path left, path right) { + assert(left.data); + assert(right.data); + + // +1 for separator. + const size_t out_size = left.size + right.size + 1; + // +1 for null. + char* out = calloc(out_size + 1, sizeof(char)); + ASSERT(out); + + memcpy(out, left.data, left.size); + out[left.size] = '/'; + memcpy(out + left.size + 1, right.data, right.size); + out[out_size] = 0; + + return (path){out, out_size}; +} + +bool path_make_relative( + const char* filepath, const char* path, char* relative, + size_t relative_length) { + assert(filepath); + assert(path); + assert(relative); + + const size_t filepath_len = strlen(filepath); + const size_t path_len = strlen(path); + assert(filepath_len < relative_length); + assert(path_len < relative_length); + + // Handle empty filepath. + if (filepath_len == 0) { + memcpy(relative, path, path_len); + return true; + } + + // Search for the last / in the file path to get its parent directory. + assert(filepath_len > 0); + size_t tm_dir_len = 0; + for (tm_dir_len = strlen(filepath) - 1; tm_dir_len > 0; --tm_dir_len) { + if (filepath[tm_dir_len] == '/') { + break; + } + } + tm_dir_len++; // Preserve the backslash. + + // Copy the file path where the parent dir ends. + // Make sure there is enough space in the output. + if ((tm_dir_len + path_len + 1) >= relative_length) { + return false; + } + memcpy(relative, filepath, tm_dir_len); + memcpy(&relative[tm_dir_len], path, path_len); + + return true; +} -- cgit v1.2.3