From 38201cc1bb723a4c44648b86ee1b4bd8a4aedd87 Mon Sep 17 00:00:00 2001 From: Abdelrahman Said Date: Fri, 3 Nov 2023 22:47:42 +0000 Subject: [PATCH] Add path utilties --- include/cpath.h | 18 ++++++++++++ src/cpath.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 include/cpath.h create mode 100644 src/cpath.c diff --git a/include/cpath.h b/include/cpath.h new file mode 100644 index 0000000..06f7018 --- /dev/null +++ b/include/cpath.h @@ -0,0 +1,18 @@ +#ifndef PATH_UTILS_H +#define PATH_UTILS_H + +#include "aliases.h" + +#define NUMPARTS(...) \ + (sizeof((const char *[]){"", __VA_ARGS__}) / sizeof(const char *) - 1) + +#define JOIN_PATH(DST, ...) join_path(DST, NUMPARTS(__VA_ARGS__), __VA_ARGS__) + +void join_path(char *dst, u64 count, ...); + +#define DIRNAME(DST, PATH) dirup(DST, 1, PATH) +#define DIRUP(DST, COUNT, PATH) dirup(DST, COUNT, PATH) + +void dirup(char *dst, u64 levels, const char *path); + +#endif // !PATH_UTILS_H diff --git a/src/cpath.c b/src/cpath.c new file mode 100644 index 0000000..998523f --- /dev/null +++ b/src/cpath.c @@ -0,0 +1,76 @@ +#include "cpath.h" +#include "aliases.h" +#include +#include +#include + +#if defined(__unix__) || defined(__APPLE__) || defined(__ANDROID__) +INTERNAL char path_sep = '/'; +#elif defined(_WIN32) || defined(_WIN64) +INTERNAL char path_sep = '\'; +#endif + +void join_root_and_leaf(const char *root, const char *leaf, char *dst); + +void join_path(char *dst, u64 count, ...) { + va_list args; + + va_start(args, count); + + for (u64 i = 0; i < count; ++i) { + join_root_and_leaf(dst, va_arg(args, const char *), dst); + } + + va_end(args); +} + +void dirup(char *dst, u64 levels, const char *path) { + if (levels < 1) { + return; + } + + u64 end_index = 0; + u64 sep_count = 0; + + u64 length = strlen(path); + if (path[length - 1] == path_sep) { + --length; + } + + for (u64 i = length - 1; i >= 0; --i) { + if (path[i] == path_sep) { + ++sep_count; + end_index = i; + + if (sep_count == levels) { + break; + } + } + } + + if (sep_count < levels) { + end_index = 0; + } + + strncpy(dst, path, end_index); +} + +void join_root_and_leaf(const char *root, const char *leaf, char *dst) { + u64 root_length = strlen(root); + u64 root_end = root_length - 1; + + u64 leaf_length = strlen(leaf); + u64 leaf_start = 0; + + if (root[root_end] == path_sep) { + --root_end; + } + + if (leaf[leaf_start] == path_sep) { + ++leaf_start; + } + + strncpy(dst, root, ++root_end); + dst[root_end] = path_sep; + strncpy(&(dst[++root_end]), &(leaf[leaf_start]), leaf_length - leaf_start); +}