From 26de01c3e789638d58bda1ae04dce3be0aefde50 Mon Sep 17 00:00:00 2001 From: Timerix Date: Sun, 21 Dec 2025 20:00:10 +0500 Subject: [PATCH] added path_getUserDir, dir_createParent --- README.md | 2 ++ include/tlibc/filesystem.h | 9 +++++++++ include/tlibc/string/str.h | 6 +++--- project.config | 2 +- src/filesystem/dir.c | 25 +++++++++++++++++++++---- src/filesystem/path.c | 28 +++++++++++++++++++++++++++- src/string/str.c | 7 +++---- 7 files changed, 66 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index faf8408..5374bcb 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,8 @@ C library with collections, strings, exceptions, io... cbuild build_static_lib_dbg ``` +6. If you use tlibc as static library, add `LINKER_LIBS` from tlibc `project.config` to your project. + ## Usage ```c diff --git a/include/tlibc/filesystem.h b/include/tlibc/filesystem.h index 5e5c237..d8f1954 100644 --- a/include/tlibc/filesystem.h +++ b/include/tlibc/filesystem.h @@ -39,6 +39,8 @@ str path_dirname(str path); /// @return pointer to a segment of path.data or path itself if no path_sep has been found str path_basename(str path, bool remove_ext); +/// @return heap-allocated string +Result(char*) path_getUserDir(); ////////////////////////////////////////////////////////////////////////////// // FILE // @@ -145,8 +147,15 @@ Result(void) file_readWholeText(FILE* f, str* out_str); // DIRECTORY // ////////////////////////////////////////////////////////////////////////////// +/// @return true if directory exists or `path` is null or empty or '.' or './' bool dir_exists(cstr path); /// @brief creates directories specified in path recursively +/// EXAMPLE: dir_createParent("a/b/c") -> creates "a", "a/b", "a/b/c" /// @return false if directory was present already, true if it has been created Result(bool) dir_create(cstr path); + +/// @brief creates directories except the last part of path +/// EXAMPLE: dir_createParent("a/b/c") -> creates "a", "a/b" +/// @return false if directory was present already, true if it has been created +Result(bool) dir_createParent(cstr path); diff --git a/include/tlibc/string/str.h b/include/tlibc/string/str.h index e005df5..69c1b95 100755 --- a/include/tlibc/string/str.h +++ b/include/tlibc/string/str.h @@ -16,10 +16,10 @@ typedef struct str { /* USAGE: str s = STR("something"); -printf(FMT_str"\n", str_expand(s)); +printf(FMT_str"\n", str_unwrap(s)); */ #define FMT_str "%.*s" -#define str_expand(S) (S).len, (S).data +#define str_unwrap(S) (S).len, (S).data /// creates str from a string literal #define STR(LITERAL) str_construct(LITERAL, ARRAY_LEN(LITERAL) - 1, true) @@ -59,7 +59,7 @@ static inline str Array_u8_castTo_str(Array(u8) a, bool isZeroTerminated) { static const str str_null = str_construct(NULL, 0, 0); -/// copies src content to new string and adds \0 at the end +/// copy str data to new str and add \0 at the end str str_copy(const str self); /// compares two strings, NullPtr-friendly diff --git a/project.config b/project.config index e65132c..ddb9a81 100644 --- a/project.config +++ b/project.config @@ -43,7 +43,7 @@ case "$OS" in EXEC_FILE="$PROJECT.exe" SHARED_LIB_FILE="$PROJECT.dll" INCLUDE="$INCLUDE " - LINKER_LIBS="" + LINKER_LIBS="-luuid" ;; LINUX) EXEC_FILE="$PROJECT" diff --git a/src/filesystem/dir.c b/src/filesystem/dir.c index 6501438..e710365 100644 --- a/src/filesystem/dir.c +++ b/src/filesystem/dir.c @@ -1,6 +1,9 @@ #include "internal.h" bool dir_exists(cstr path){ + if(path == NULL || path[0] == 0) + return true; + if(path[0]=='.'){ if(path[1]==0 || (path[1]==path_sep && path[1]==0)) return true; // dir . or ./ always exists @@ -23,13 +26,12 @@ bool dir_exists(cstr path){ Result(bool) dir_create(cstr path){ Deferral(4); - if (dir_exists(path)){ + + if (path == NULL || path[0] == 0 || dir_exists(path)){ Return RESULT_VALUE(i, false); } - char* parentDir= str_copy(path_dirname(str_from_cstr((void*)path))).data; - Defer(free(parentDir)); - try_void(dir_create(parentDir)); + try_void(dir_createParent(path)); #if TLIBC_FS_USE_WINDOWS_H if(!CreateDirectory(path, NULL)) @@ -47,3 +49,18 @@ Result(bool) dir_create(cstr path){ Return RESULT_VALUE(i, true); } + +Result(bool) dir_createParent(cstr path){ + Deferral(4); + + str parent_dir_str = path_dirname(str_from_cstr((void*)path)); + if(parent_dir_str.len == 0){ + Return RESULT_VALUE(i, false); + } + + char* parent_dir_cstr = str_copy(parent_dir_str).data; + Defer(free(parent_dir_cstr)); + + try(bool result, i, dir_create(parent_dir_cstr)); + Return RESULT_VALUE(i, result); +} diff --git a/src/filesystem/path.c b/src/filesystem/path.c index 1ca48e2..9bce84c 100644 --- a/src/filesystem/path.c +++ b/src/filesystem/path.c @@ -1,4 +1,10 @@ -#include "tlibc/filesystem.h" +#include "internal.h" + +#if TLIBC_FS_USE_WINDOWS_H +#include +#include +#else +#endif str path_dirname(str path){ if(path.len == 0) @@ -43,3 +49,23 @@ str path_basename(str path, bool remove_ext){ } return path; } + +Result(char*) path_getUserDir(){ +#if TLIBC_FS_USE_WINDOWS_H + PWSTR wpath = NULL; + HRESULT reslut = SHGetKnownFolderPath(&FOLDERID_Profile, 0, NULL, &wpath); + if(!SUCCEEDED(reslut)){ + return RESULT_ERROR_LITERAL("can't get user directory by SHGetKnownFolderPath()"); + } + size_t char_len = wcslen(wpath) * 4 + 1; + char* path = (char*)malloc(char_len); + wcstombs(path, wpath, char_len); + return RESULT_VALUE(p, path); +#else + const char *home = getenv("HOME"); + if(home == NULL){ + return RESULT_ERROR_LITERAL("can't get user directory by getenv(\"HOME\")"); + } + return RESULT_VALUE(p, cstr_copy(home)); +#endif +} diff --git a/src/string/str.c b/src/string/str.c index 3898491..dbd553f 100755 --- a/src/string/str.c +++ b/src/string/str.c @@ -2,11 +2,10 @@ #include "tlibc/string/StringBuilder.h" str str_copy(const str self){ - if(self.data == NULL || self.len == 0) - return self; - str copy = str_construct((char*)malloc(self.len + 1), self.len, true); - memcpy(copy.data, self.data, self.len); + if(self.len != 0){ + memcpy(copy.data, self.data, self.len); + } copy.data[copy.len] = '\0'; return copy; }