From b3fb3e8f5eea702f8d29c1143863e7e7babd5622 Mon Sep 17 00:00:00 2001 From: Serge Poltavski Date: Sun, 2 Jul 2017 01:46:40 +0300 Subject: [PATCH] home_directory function added --- ceammc/ext/src/lib/CMakeLists.txt | 2 +- ceammc/ext/src/lib/ceammc_platform.cpp | 14 +++++++ ceammc/ext/src/lib/ceammc_platform.h | 3 ++ ceammc/ext/src/lib/ceammc_platform_unix.cpp | 13 +++++++ ceammc/ext/src/lib/ceammc_platform_unix.h | 1 + ceammc/ext/src/lib/ceammc_platform_win.cpp | 42 +++++++++++++++++++++ ceammc/ext/src/lib/ceammc_platform_win.h | 2 + ceammc/ext/src/path/path_listdir.cpp | 7 ++++ ceammc/ext/src/tests/test_platform.cpp | 27 +++++++++++++ 9 files changed, 110 insertions(+), 1 deletion(-) diff --git a/ceammc/ext/src/lib/CMakeLists.txt b/ceammc/ext/src/lib/CMakeLists.txt index 2b11b2712f..211f36060d 100644 --- a/ceammc/ext/src/lib/CMakeLists.txt +++ b/ceammc/ext/src/lib/CMakeLists.txt @@ -68,7 +68,7 @@ set_target_properties(ceammc_core PROPERTIES LINK_FLAGS "${LIBCEAMMC_LINK_FLAGS}") if(WIN32) - target_link_libraries(ceammc_core psapi shlwapi msvcr100 puredata-core) + target_link_libraries(ceammc_core psapi shlwapi userenv msvcr100 puredata-core) # copy library to tests folder add_custom_command(TARGET ceammc_core POST_BUILD diff --git a/ceammc/ext/src/lib/ceammc_platform.cpp b/ceammc/ext/src/lib/ceammc_platform.cpp index 3a4f925ed0..13e60b3129 100644 --- a/ceammc/ext/src/lib/ceammc_platform.cpp +++ b/ceammc/ext/src/lib/ceammc_platform.cpp @@ -131,5 +131,19 @@ namespace platform { { return NS(rmdir)(path); } + + std::string home_directory() + { + return NS(home_directory)(); + } + + std::string expand_tilde_path(const std::string& path) + { + if (path.empty() || path[0] != '~') + return path; + + std::string res(path); + return res.replace(0, 1, home_directory()); + } } } diff --git a/ceammc/ext/src/lib/ceammc_platform.h b/ceammc/ext/src/lib/ceammc_platform.h index e7281c23e2..60982f2529 100644 --- a/ceammc/ext/src/lib/ceammc_platform.h +++ b/ceammc/ext/src/lib/ceammc_platform.h @@ -38,6 +38,9 @@ namespace platform { bool mkdir(const char* path, int flags = -1); bool rmdir(const char* path); + + std::string home_directory(); + std::string expand_tilde_path(const std::string& path); } } diff --git a/ceammc/ext/src/lib/ceammc_platform_unix.cpp b/ceammc/ext/src/lib/ceammc_platform_unix.cpp index 05cf70a9a3..b3366ad47d 100644 --- a/ceammc/ext/src/lib/ceammc_platform_unix.cpp +++ b/ceammc/ext/src/lib/ceammc_platform_unix.cpp @@ -17,7 +17,9 @@ #include #include #include +#include #include +#include #include bool ceammc::unix_is_path_relative(const char* path) @@ -71,3 +73,14 @@ bool ceammc::unix_rmdir(const char* path) { return rmdir(path) == 0; } + +std::string ceammc::unix_home_directory() +{ + const char* homedir = 0; + + if ((homedir = getenv("HOME")) == NULL) { + homedir = getpwuid(getuid())->pw_dir; + } + + return homedir ? homedir : ""; +} diff --git a/ceammc/ext/src/lib/ceammc_platform_unix.h b/ceammc/ext/src/lib/ceammc_platform_unix.h index 17dde9395d..c959a67597 100644 --- a/ceammc/ext/src/lib/ceammc_platform_unix.h +++ b/ceammc/ext/src/lib/ceammc_platform_unix.h @@ -24,6 +24,7 @@ bool unix_fnmatch(const char* pattern, const char* str); bool unix_path_exists(const char* path); bool unix_mkdir(const char* path, int flags = -1); bool unix_rmdir(const char* path); +std::string unix_home_directory(); } #endif // CEAMMC_PLATFORM_UNIX_H diff --git a/ceammc/ext/src/lib/ceammc_platform_win.cpp b/ceammc/ext/src/lib/ceammc_platform_win.cpp index af5946e573..06d0754699 100644 --- a/ceammc/ext/src/lib/ceammc_platform_win.cpp +++ b/ceammc/ext/src/lib/ceammc_platform_win.cpp @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -137,4 +138,45 @@ bool win_rmdir(const char* path) free(wpath); return err == 0; } + +std::string win_home_directory() +{ + WCHAR buf[MAX_PATH] = { 0 }; + + // We need a process with query permission set + HANDLE token = 0; + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) + return ""; + + // Returns a path like C:/Documents and Settings/nibu if my user name is nibu + DWORD buf_size = MAX_PATH; + GetUserProfileDirectoryW(token, buf, &buf_size); + CloseHandle(token); + + char* path; + if (!wch_to_mb(buf, &path)) + return ""; + + std::string home(path); + free(path); + return home; +} + +bool wch_to_mb(const wchar_t* wstr, char** res) +{ + const int wstr_len = wcslen(wstr) + 1; + int str_len = WideCharToMultiByte(CP_ACP, 0, wstr, wstr_len, 0, 0, 0, 0); + if (str_len == 0) + return false; + + char* str = static_cast(malloc(str_len)); + int rc = WideCharToMultiByte(CP_ACP, 0, wstr, wstr_len, str, str_len, 0, 0); + if (!rc) { + free(str); + return false; + } else { + *res = str; + return true; + } +} } diff --git a/ceammc/ext/src/lib/ceammc_platform_win.h b/ceammc/ext/src/lib/ceammc_platform_win.h index f9d99c84b6..8e049b3635 100644 --- a/ceammc/ext/src/lib/ceammc_platform_win.h +++ b/ceammc/ext/src/lib/ceammc_platform_win.h @@ -23,8 +23,10 @@ std::string win_dirname(const char* path); bool win_fnmatch(const char* pattern, const char* str); bool win_path_exists(const char* path); bool mb_to_wch(const char* str, wchar_t** res); +bool wch_to_mb(const wchar_t* str, char** res); bool win_mkdir(const char* path, int flags = -1); bool win_rmdir(const char* path); +std::string win_home_directory(); } #endif // CEAMMC_PLATFORM_WIN_H diff --git a/ceammc/ext/src/path/path_listdir.cpp b/ceammc/ext/src/path/path_listdir.cpp index e6f1accaa8..dbc106c7f0 100644 --- a/ceammc/ext/src/path/path_listdir.cpp +++ b/ceammc/ext/src/path/path_listdir.cpp @@ -1,6 +1,7 @@ #include "path_listdir.h" #include "../string/datatype_string.h" #include "ceammc_factory.h" +#include "ceammc_format.h" #include "ceammc_platform.h" #include "config.h" @@ -21,6 +22,9 @@ PathListDir::PathListDir(const PdArgs& a) createOutlet(); createProperty(new PointerProperty("@match", &match_, false)); + + path_ = to_string(positionalArguments()); + readDirList(); } void PathListDir::onBang() @@ -55,6 +59,9 @@ void PathListDir::m_match(t_symbol*, const AtomList& lst) void PathListDir::readDirList() { + if (path_.empty()) + return; + ls_.clear(); std::string path = path_; diff --git a/ceammc/ext/src/tests/test_platform.cpp b/ceammc/ext/src/tests/test_platform.cpp index 8a65b67b11..f66308e8a6 100644 --- a/ceammc/ext/src/tests/test_platform.cpp +++ b/ceammc/ext/src/tests/test_platform.cpp @@ -236,6 +236,33 @@ TEST_CASE("ceammc::platform", "[ceammc::lib]") ceammc::platform::mkdir("тест"); REQUIRE(path_exists("тест")); ceammc::platform::rmdir("тест"); +#endif + } + + SECTION("home_directory") + { +#ifdef __APPLE__ + REQUIRE(ceammc::platform::home_directory().substr(0, 6) == "/Users"); +#endif + +#ifdef __WIN32 + REQUIRE(ceammc::platform::home_directory().substr(0, 3) == "C:\\"); +#endif + } + + SECTION("expand_tilde_path") + { + REQUIRE(ceammc::platform::expand_tilde_path("") == ""); + REQUIRE(ceammc::platform::expand_tilde_path("/full/path") == "/full/path"); + REQUIRE(ceammc::platform::expand_tilde_path("relative path") == "relative path"); + REQUIRE(ceammc::platform::expand_tilde_path("./~") == "./~"); + +#ifdef __APPLE__ + REQUIRE(ceammc::platform::expand_tilde_path("~/").substr(0, 7) == "/Users/"); +#endif + +#ifdef __WIN32 + REQUIRE(ceammc::platform::expand_tilde_path("~/").substr(0, 3) == "C:\\"); #endif } }