diff --git a/engine/common/common.cpp b/engine/common/common.cpp index 3340bad..01860a1 100644 --- a/engine/common/common.cpp +++ b/engine/common/common.cpp @@ -484,7 +484,7 @@ IndexedUTF32String IndexUTF8ToUTF32(std::string_view input) byteIdx += 4; } else { - codepoints.push_back(0xFFFDu); + codepoint = 0xFFFDu; byteIdx += 1; } codepoints.push_back(codepoint); diff --git a/engine/system/sys_main.h b/engine/system/sys_main.h index 1e662f1..5d83fc7 100644 --- a/engine/system/sys_main.h +++ b/engine/system/sys_main.h @@ -69,6 +69,7 @@ class sys_IMain { int processorCount = 0; std::filesystem::path basePath; std::optional userPath; + std::optional userPathReason; virtual int GetTime() = 0; virtual void Sleep(int msec) = 0; diff --git a/engine/system/win/sys_main.cpp b/engine/system/win/sys_main.cpp index 51dec7e..3078e0d 100644 --- a/engine/system/win/sys_main.cpp +++ b/engine/system/win/sys_main.cpp @@ -564,9 +564,9 @@ std::filesystem::path FindBasePath() progPath = basePath.data(); #elif __linux__ char basePath[PATH_MAX]; - ssize_t len = ::readlink("/proc/self/exe", basePath, sizeof(basePath)); - if (len == -1 || len == sizeof(basePath)) - len = 0; + ssize_t len = ::readlink("/proc/self/exe", basePath, sizeof(basePath)); + if (len == -1 || len == sizeof(basePath)) + len = 0; basePath[len] = '\0'; progPath = basePath; #elif __APPLE__ && __MACH__ @@ -575,34 +575,34 @@ std::filesystem::path FindBasePath() proc_pidpath(pid, basePath, sizeof(basePath)); progPath = basePath; #endif - progPath = canonical(progPath); + progPath = weakly_canonical(progPath); return progPath.parent_path(); } -std::optional FindUserPath() +std::tuple, std::optional> FindUserPath() { #ifdef _WIN32 - PWSTR osPath{}; - HRESULT hr = SHGetKnownFolderPath(FOLDERID_Documents, KF_FLAG_DEFAULT, nullptr, &osPath); + PWSTR osPath{}; + HRESULT hr = SHGetKnownFolderPath(FOLDERID_Documents, KF_FLAG_DEFAULT, nullptr, &osPath); if (FAILED(hr)) { // The path may be inaccessible due to malfunctioning cloud providers. CoTaskMemFree(osPath); - return {}; + return { {}, "Could not obtain Documents path from Windows" }; } std::wstring pathStr = osPath; CoTaskMemFree(osPath); std::filesystem::path path(pathStr); - return canonical(path); + return { weakly_canonical(path), {} }; #else - if (char const* data_home_path = getenv("XDG_DATA_HOME")) { - return data_home_path; - } - if (char const* home_path = getenv("HOME")) { - return std::filesystem::path(home_path) / ".local/share"; - } - uid_t uid = getuid(); - struct passwd *pw = getpwuid(uid); - return std::filesystem::path(pw->pw_dir) / ".local/share"; + if (char const* data_home_path = getenv("XDG_DATA_HOME")) { + return { data_home_path, {} }; + } + if (char const* home_path = getenv("HOME")) { + return { std::filesystem::path(home_path) / ".local/share", {} }; + } + uid_t uid = getuid(); + struct passwd *pw = getpwuid(uid); + return { std::filesystem::path(pw->pw_dir) / ".local/share", {} }; #endif } @@ -628,7 +628,7 @@ sys_main_c::sys_main_c() // Set the local system information basePath = FindBasePath(); - userPath = FindUserPath(); + std::tie(userPath, userPathReason) = FindUserPath(); } bool sys_main_c::Run(int argc, char** argv) diff --git a/ui_api.cpp b/ui_api.cpp index aaa4694..3dba0b1 100644 --- a/ui_api.cpp +++ b/ui_api.cpp @@ -85,9 +85,9 @@ ** compressed = Deflate(uncompressed) ** uncompressed = Inflate(compressed) ** msec = GetTime() -** path = GetScriptPath() -** path = GetRuntimePath() -** path = GetUserPath() -- may return nil if the user path could not be determined +** path[, pathACP[, err]] = GetScriptPath() +** path[, pathACP[, err]] = GetRuntimePath() +** path[, pathACP[, err]] = GetUserPath() -- may return nil if the user path could not be determined ** SetWorkDir("") ** path = GetWorkDir() ** ssID = LaunchSubScript("", "", ""[, ...]) @@ -1544,25 +1544,63 @@ static int l_GetScriptPath(lua_State* L) { ui_main_c* ui = GetUIPtr(L); lua_pushstring(L, ui->scriptPath.generic_u8string().c_str()); - return 1; + try + { + lua_pushstring(L, ui->scriptPath.generic_string().c_str()); + return 2; + } + catch (std::exception& e) + { + lua_pushnil(L); + lua_pushstring(L, e.what()); + return 3; + } } static int l_GetRuntimePath(lua_State* L) { ui_main_c* ui = GetUIPtr(L); lua_pushstring(L, ui->sys->basePath.generic_u8string().c_str()); - return 1; + try + { + lua_pushstring(L, ui->sys->basePath.generic_string().c_str()); + return 2; + } + catch (std::exception& e) + { + lua_pushnil(L); + lua_pushstring(L, e.what()); + return 3; + } } static int l_GetUserPath(lua_State* L) { ui_main_c* ui = GetUIPtr(L); auto& userPath = ui->sys->userPath; - if (userPath) { - lua_pushstring(L, userPath->generic_u8string().c_str()); - return 1; + if (!userPath) { + lua_pushnil(L); + lua_pushnil(L); + if (auto& reason = ui->sys->userPathReason) + { + lua_pushstring(L, reason->c_str()); + return 3; + } + return 2; + } + + lua_pushstring(L, userPath->generic_u8string().c_str()); + try + { + lua_pushstring(L, userPath->generic_string().c_str()); + return 2; + } + catch (std::exception& e) + { + lua_pushnil(L); + lua_pushstring(L, e.what()); + return 3; } - return 0; } static int l_MakeDir(lua_State* L)