diff --git a/src/os/cpath/cpath.c b/src/os/cpath/cpath.c index 02057c4..a4cdc4e 100644 --- a/src/os/cpath/cpath.c +++ b/src/os/cpath/cpath.c @@ -1,5 +1,6 @@ #include "cpath.h" #include "aliases.h" +#include "str8.h" #include <stdarg.h> #include <stdbool.h> #include <stdio.h> @@ -7,16 +8,48 @@ 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); +u32 wapp_cpath_join_path(Str8 *dst, const Str8List *parts) { + if (!dst || !parts) { + return CPATH_JOIN_INVALID_ARGS; } - va_end(args); + if (parts->node_count == 0) { + return CPATH_JOIN_EMPTY_PARTS; + } + + Str8 separator = wapp_str8_buf(4); + wapp_str8_push_back(&separator, PATH_SEP); + + u64 required_capacity = parts->node_count * separator.size + parts->total_size; + if (dst->capacity < required_capacity) { + return CPATH_JOIN_INSUFFICIENT_DST_CAPACITY; + } + + // Handle first node + const Str8Node *first_node = wapp_str8_list_get(parts, 0); + wapp_str8_copy_str8_capped(dst, first_node->string); + + const Str8Node *node = first_node; + for (u64 i = 1; i < parts->node_count; ++i) { + node = node->next; + if (node->string->size == 0) { + continue; + } + + if (dst->size > 0) { + char dst_last = wapp_str8_get(dst, dst->size - 1); + char node_start = wapp_str8_get(node->string, 0); + bool add_path_sep = dst_last != PATH_SEP && node_start != PATH_SEP; + + if (add_path_sep) { + wapp_str8_concat_capped(dst, &separator); + } + } + + wapp_str8_concat_capped(dst, node->string); + } + + return CPATH_JOIN_SUCCESS; } void dirup(char *dst, u64 levels, const char *path) { diff --git a/src/os/cpath/cpath.h b/src/os/cpath/cpath.h index 13d565c..f3c1ee5 100644 --- a/src/os/cpath/cpath.h +++ b/src/os/cpath/cpath.h @@ -3,6 +3,7 @@ #include "aliases.h" #include "platform.h" +#include "str8.h" #ifdef __cplusplus BEGIN_C_LINKAGE @@ -16,13 +17,17 @@ BEGIN_C_LINKAGE #error "Unrecognised platform" #endif -#define NUMPARTS(...) (sizeof((const char *[]){"", __VA_ARGS__}) / sizeof(const char *) - 1) - -#define wapp_cpath_join_path(DST, ...) join_path(DST, NUMPARTS(__VA_ARGS__), __VA_ARGS__) #define wapp_cpath_dirname(DST, PATH) dirup(DST, 1, PATH) #define wapp_cpath_dirup(DST, COUNT, PATH) dirup(DST, COUNT, PATH) -void join_path(char *dst, u64 count, ...); +enum { + CPATH_JOIN_SUCCESS = 0, + CPATH_JOIN_INVALID_ARGS, + CPATH_JOIN_EMPTY_PARTS, + CPATH_JOIN_INSUFFICIENT_DST_CAPACITY, +}; + +u32 wapp_cpath_join_path(Str8 *dst, const Str8List *parts); void dirup(char *dst, u64 levels, const char *path); #ifdef __cplusplus diff --git a/tests/cpath/test_cpath.c b/tests/cpath/test_cpath.c index e112c33..d7c5db3 100644 --- a/tests/cpath/test_cpath.c +++ b/tests/cpath/test_cpath.c @@ -1,5 +1,6 @@ #include "test_cpath.h" #include "cpath.h" +#include "str8.h" #include "tester.h" #include <string.h> #include <stdio.h> @@ -9,77 +10,76 @@ #define TMP_BUF_SIZE 1024 TestFuncResult test_cpath_join_path(void) { - char expected[MAIN_BUF_SIZE] = {0}; - char out[MAIN_BUF_SIZE] = {0}; - char tmp[TMP_BUF_SIZE] = {0}; + bool result; - snprintf(expected, MAIN_BUF_SIZE, "%chome%cabdelrahman%cDocuments", PATH_SEP, PATH_SEP, PATH_SEP); - snprintf(tmp, 2, "%c", PATH_SEP); - wapp_cpath_join_path(out, tmp, "home", "abdelrahman", "Documents"); + Str8 expected = wapp_str8_buf(MAIN_BUF_SIZE); + Str8 out = wapp_str8_buf(MAIN_BUF_SIZE); + Str8 tmp = wapp_str8_buf(TMP_BUF_SIZE); - bool result = strcmp(out, expected) == 0; - if (!result) { - goto TEST_JOIN_PATH_EXIT; - } + wapp_str8_format(&expected, "%chome%cabdelrahman%cDocuments", PATH_SEP, PATH_SEP, PATH_SEP); + wapp_str8_format(&tmp, "%c", PATH_SEP); - memset(out, 0, strlen(out)); - snprintf(expected, MAIN_BUF_SIZE, "home%cabdelrahman%cDocuments", PATH_SEP, PATH_SEP); - wapp_cpath_join_path(out, "home", "abdelrahman", "Documents"); + Str8List parts = {0}; + wapp_str8_list_push_back(&parts, &wapp_str8_node_from_str8(tmp)); + wapp_str8_list_push_back(&parts, &wapp_str8_node_from_cstr("home")); + wapp_str8_list_push_back(&parts, &wapp_str8_node_from_cstr("abdelrahman")); + wapp_str8_list_push_back(&parts, &wapp_str8_node_from_cstr("Documents")); - result = result && strcmp(out, expected) == 0; - if (!result) { - goto TEST_JOIN_PATH_EXIT; - } + wapp_cpath_join_path(&out, &parts); + result = wapp_str8_equal(&out, &expected); - memset(out, 0, strlen(out)); - memset(tmp, 0, strlen(tmp)); - snprintf(expected, MAIN_BUF_SIZE, "%chome%cabdelrahman%cDocuments", PATH_SEP, PATH_SEP, PATH_SEP); - snprintf(tmp, TMP_BUF_SIZE, "%chome", PATH_SEP); - wapp_cpath_join_path(out, tmp, "abdelrahman", "Documents"); + wapp_str8_list_pop_front(&parts); - result = result && strcmp(out, expected) == 0; - if (!result) { - goto TEST_JOIN_PATH_EXIT; - } + wapp_str8_format(&expected, "home%cabdelrahman%cDocuments", PATH_SEP, PATH_SEP); - memset(out, 0, strlen(out)); - memset(tmp, 0, strlen(tmp)); - snprintf(expected, MAIN_BUF_SIZE, "home%cabdelrahman%cDocuments", PATH_SEP, PATH_SEP); - snprintf(tmp, TMP_BUF_SIZE, "home%c", PATH_SEP); - wapp_cpath_join_path(out, tmp, "abdelrahman", "Documents"); + wapp_cpath_join_path(&out, &parts); + result = result && wapp_str8_equal(&out, &expected); - result = result && strcmp(out, expected) == 0; - if (!result) { - goto TEST_JOIN_PATH_EXIT; - } + wapp_str8_concat_capped(&tmp, &wapp_str8_lit_ro("home")); + wapp_str8_list_pop_front(&parts); + wapp_str8_list_push_front(&parts, &wapp_str8_node_from_str8(tmp)); - memset(out, 0, strlen(out)); - memset(tmp, 0, strlen(tmp)); - snprintf(expected, MAIN_BUF_SIZE, "%chome", PATH_SEP); - snprintf(tmp, TMP_BUF_SIZE, "%chome", PATH_SEP); - wapp_cpath_join_path(out, tmp, ""); + wapp_str8_format(&expected, "%chome%cabdelrahman%cDocuments", PATH_SEP, PATH_SEP, PATH_SEP); - result = result && strcmp(out, expected) == 0; - if (!result) { - goto TEST_JOIN_PATH_EXIT; - } + wapp_cpath_join_path(&out, &parts); + result = result && wapp_str8_equal(&out, &expected); - memset(out, 0, strlen(out)); - snprintf(expected, 1, "%s", ""); - wapp_cpath_join_path(out, "", ""); + wapp_str8_format(&tmp, "home%c", PATH_SEP); + wapp_str8_list_pop_front(&parts); + wapp_str8_list_push_front(&parts, &wapp_str8_node_from_cstr("home")); - result = result && strcmp(out, expected) == 0; - if (!result) { - goto TEST_JOIN_PATH_EXIT; - } + wapp_str8_format(&expected, "home%cabdelrahman%cDocuments", PATH_SEP, PATH_SEP); - memset(out, 0, strlen(out)); - snprintf(expected, MAIN_BUF_SIZE, "home"); - wapp_cpath_join_path(out, "", "home"); + wapp_cpath_join_path(&out, &parts); + result = result && wapp_str8_equal(&out, &expected); - result = result && strcmp(out, expected) == 0; + wapp_str8_list_empty(&parts); + + wapp_str8_format(&tmp, "%chome", PATH_SEP); + wapp_str8_list_push_back(&parts, &wapp_str8_node_from_str8(tmp)); + wapp_str8_list_push_back(&parts, &wapp_str8_node_from_cstr("")); + + wapp_str8_format(&expected, "%chome", PATH_SEP); + + wapp_cpath_join_path(&out, &parts); + result = result && wapp_str8_equal(&out, &expected); + + wapp_str8_list_pop_front(&parts); + wapp_str8_list_push_back(&parts, &wapp_str8_node_from_cstr("")); + + wapp_str8_format(&expected, "%s", ""); + + wapp_cpath_join_path(&out, &parts); + result = result && wapp_str8_equal(&out, &expected); + + wapp_str8_list_pop_back(&parts); + wapp_str8_list_push_back(&parts, &wapp_str8_node_from_cstr("home")); + + wapp_str8_copy_cstr_capped(&expected, "home"); + + wapp_cpath_join_path(&out, &parts); + result = result && wapp_str8_equal(&out, &expected); -TEST_JOIN_PATH_EXIT: return wapp_tester_result(result); } diff --git a/tests/wapptest.c b/tests/wapptest.c index 77b6fb1..30c6b0a 100644 --- a/tests/wapptest.c +++ b/tests/wapptest.c @@ -44,6 +44,7 @@ int main(void) { test_str8_list_pop_front, test_str8_list_pop_back, test_str8_list_remove, + test_str8_list_empty, test_cpath_join_path, test_cpath_dirname, test_cpath_dirup,