Skip to content

Commit 683facc

Browse files
committed
feat: expose root paths as both UTF-8 and ACP
The standard encoding for all the top level paths (base, script, user) in SimpleGraphic is UTF-8. For some purposes it's useful to know if the path can be expressed in the user's active codepage as well, the updater can use it to form absolute paths that the OS understands. As the user path is fallible, we also expose a human-readable reason as to why it could not be obtained. All paths are made weakly canonical rather than fully canonical as the full flavour requires paths to fully exist.
1 parent fc4de14 commit 683facc

File tree

3 files changed

+67
-28
lines changed

3 files changed

+67
-28
lines changed

engine/system/sys_main.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ class sys_IMain {
6969
int processorCount = 0;
7070
std::filesystem::path basePath;
7171
std::optional<std::filesystem::path> userPath;
72+
std::optional<std::string> userPathReason;
7273

7374
virtual int GetTime() = 0;
7475
virtual void Sleep(int msec) = 0;

engine/system/win/sys_main.cpp

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -564,9 +564,9 @@ std::filesystem::path FindBasePath()
564564
progPath = basePath.data();
565565
#elif __linux__
566566
char basePath[PATH_MAX];
567-
ssize_t len = ::readlink("/proc/self/exe", basePath, sizeof(basePath));
568-
if (len == -1 || len == sizeof(basePath))
569-
len = 0;
567+
ssize_t len = ::readlink("/proc/self/exe", basePath, sizeof(basePath));
568+
if (len == -1 || len == sizeof(basePath))
569+
len = 0;
570570
basePath[len] = '\0';
571571
progPath = basePath;
572572
#elif __APPLE__ && __MACH__
@@ -575,34 +575,34 @@ std::filesystem::path FindBasePath()
575575
proc_pidpath(pid, basePath, sizeof(basePath));
576576
progPath = basePath;
577577
#endif
578-
progPath = canonical(progPath);
578+
progPath = weakly_canonical(progPath);
579579
return progPath.parent_path();
580580
}
581581

582-
std::optional<std::filesystem::path> FindUserPath()
582+
std::tuple<std::optional<std::filesystem::path>, std::optional<std::string>> FindUserPath()
583583
{
584584
#ifdef _WIN32
585-
PWSTR osPath{};
586-
HRESULT hr = SHGetKnownFolderPath(FOLDERID_Documents, KF_FLAG_DEFAULT, nullptr, &osPath);
585+
PWSTR osPath{};
586+
HRESULT hr = SHGetKnownFolderPath(FOLDERID_Documents, KF_FLAG_DEFAULT, nullptr, &osPath);
587587
if (FAILED(hr)) {
588588
// The path may be inaccessible due to malfunctioning cloud providers.
589589
CoTaskMemFree(osPath);
590-
return {};
590+
return { {}, "Could not obtain Documents path from Windows" };
591591
}
592592
std::wstring pathStr = osPath;
593593
CoTaskMemFree(osPath);
594594
std::filesystem::path path(pathStr);
595-
return canonical(path);
595+
return { weakly_canonical(path), {} };
596596
#else
597-
if (char const* data_home_path = getenv("XDG_DATA_HOME")) {
598-
return data_home_path;
599-
}
600-
if (char const* home_path = getenv("HOME")) {
601-
return std::filesystem::path(home_path) / ".local/share";
602-
}
603-
uid_t uid = getuid();
604-
struct passwd *pw = getpwuid(uid);
605-
return std::filesystem::path(pw->pw_dir) / ".local/share";
597+
if (char const* data_home_path = getenv("XDG_DATA_HOME")) {
598+
return { data_home_path, {} };
599+
}
600+
if (char const* home_path = getenv("HOME")) {
601+
return { std::filesystem::path(home_path) / ".local/share", {} };
602+
}
603+
uid_t uid = getuid();
604+
struct passwd *pw = getpwuid(uid);
605+
return { std::filesystem::path(pw->pw_dir) / ".local/share", {} };
606606
#endif
607607
}
608608

@@ -628,7 +628,7 @@ sys_main_c::sys_main_c()
628628

629629
// Set the local system information
630630
basePath = FindBasePath();
631-
userPath = FindUserPath();
631+
std::tie(userPath, userPathReason) = FindUserPath();
632632
}
633633

634634
bool sys_main_c::Run(int argc, char** argv)

ui_api.cpp

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,9 @@
8585
** compressed = Deflate(uncompressed)
8686
** uncompressed = Inflate(compressed)
8787
** msec = GetTime()
88-
** path = GetScriptPath()
89-
** path = GetRuntimePath()
90-
** path = GetUserPath() -- may return nil if the user path could not be determined
88+
** path[, pathACP[, err]] = GetScriptPath()
89+
** path[, pathACP[, err]] = GetRuntimePath()
90+
** path[, pathACP[, err]] = GetUserPath() -- may return nil if the user path could not be determined
9191
** SetWorkDir("<path>")
9292
** path = GetWorkDir()
9393
** ssID = LaunchSubScript("<scriptText>", "<funcList>", "<subList>"[, ...])
@@ -1544,25 +1544,63 @@ static int l_GetScriptPath(lua_State* L)
15441544
{
15451545
ui_main_c* ui = GetUIPtr(L);
15461546
lua_pushstring(L, ui->scriptPath.generic_u8string().c_str());
1547-
return 1;
1547+
try
1548+
{
1549+
lua_pushstring(L, ui->scriptPath.generic_string().c_str());
1550+
return 2;
1551+
}
1552+
catch (std::exception& e)
1553+
{
1554+
lua_pushnil(L);
1555+
lua_pushstring(L, e.what());
1556+
return 3;
1557+
}
15481558
}
15491559

15501560
static int l_GetRuntimePath(lua_State* L)
15511561
{
15521562
ui_main_c* ui = GetUIPtr(L);
15531563
lua_pushstring(L, ui->sys->basePath.generic_u8string().c_str());
1554-
return 1;
1564+
try
1565+
{
1566+
lua_pushstring(L, ui->sys->basePath.generic_string().c_str());
1567+
return 2;
1568+
}
1569+
catch (std::exception& e)
1570+
{
1571+
lua_pushnil(L);
1572+
lua_pushstring(L, e.what());
1573+
return 3;
1574+
}
15551575
}
15561576

15571577
static int l_GetUserPath(lua_State* L)
15581578
{
15591579
ui_main_c* ui = GetUIPtr(L);
15601580
auto& userPath = ui->sys->userPath;
1561-
if (userPath) {
1562-
lua_pushstring(L, userPath->generic_u8string().c_str());
1563-
return 1;
1581+
if (!userPath) {
1582+
lua_pushnil(L);
1583+
lua_pushnil(L);
1584+
if (auto& reason = ui->sys->userPathReason)
1585+
{
1586+
lua_pushstring(L, reason->c_str());
1587+
return 3;
1588+
}
1589+
return 2;
1590+
}
1591+
1592+
lua_pushstring(L, userPath->generic_u8string().c_str());
1593+
try
1594+
{
1595+
lua_pushstring(L, userPath->generic_string().c_str());
1596+
return 2;
1597+
}
1598+
catch (std::exception& e)
1599+
{
1600+
lua_pushnil(L);
1601+
lua_pushstring(L, e.what());
1602+
return 3;
15641603
}
1565-
return 0;
15661604
}
15671605

15681606
static int l_MakeDir(lua_State* L)

0 commit comments

Comments
 (0)