diff --git a/include/bx/filepath.h b/include/bx/filepath.h index 7fdd57f..6f26a5c 100644 --- a/include/bx/filepath.h +++ b/include/bx/filepath.h @@ -23,9 +23,10 @@ namespace bx /// Special OS directories: enum Enum { - Current, //!< Current directory. - Temp, //!< Temporary directory. - Home, //!< User's home directory. + Current, //!< Current directory. + Executable, //!< Executable file path. + Home, //!< User's home directory. + Temp, //!< Temporary directory. Count }; diff --git a/src/filepath.cpp b/src/filepath.cpp index 4432736..87d355a 100644 --- a/src/filepath.cpp +++ b/src/filepath.cpp @@ -16,7 +16,8 @@ #endif // !BX_CRT_NONE #if BX_PLATFORM_WINDOWS -extern "C" __declspec(dllimport) unsigned long __stdcall GetTempPathA(unsigned long _max, char* _ptr); +extern "C" __declspec(dllimport) unsigned long __stdcall GetModuleFileNameA(void* _module, char* _outFilePath, unsigned long _size); +extern "C" __declspec(dllimport) unsigned long __stdcall GetTempPathA(unsigned long _max, char* _outFilePath); #endif // BX_PLATFORM_WINDOWS namespace bx @@ -180,7 +181,7 @@ namespace bx return ::_getcwd(_buffer, (int32_t)_size); #else return ::getcwd(_buffer, _size); -#endif // BX_COMPILER_ +#endif // BX_PLATFORM_* } static bool getCurrentPath(char* _out, uint32_t* _inOutSize) @@ -195,6 +196,29 @@ namespace bx return false; } + static bool getExecutablePath(char* _out, uint32_t* _inOutSize) + { +#if BX_PLATFORM_WINDOWS + uint32_t len = ::GetModuleFileNameA(NULL, _out, *_inOutSize); + bool result = len != 0 && len < *_inOutSize; + *_inOutSize = len; + return result; +#elif BX_PLATFORM_LINUX + char tmp[64]; + snprintf(tmp, sizeof(tmp), "/proc/%d/exe", getpid() ); + ssize_t result = readlink(tmp, _out, *_inOutSize); + + if (-1 < result) + { + *_inOutSize = uint32_t(result); + return true; + } +#elif BX_PLATFORM_OSX +#endif // BX_PLATFORM_* + + return false; + } + static bool getHomePath(char* _out, uint32_t* _inOutSize) { return false @@ -287,28 +311,22 @@ namespace bx void FilePath::set(Dir::Enum _dir) { + bool ok = false; char tmp[kMaxFilePath]; uint32_t len = BX_COUNTOF(tmp); switch (_dir) { - case Dir::Current: - getCurrentPath(tmp, &len); - break; + case Dir::Current: ok = getCurrentPath(tmp, &len); break; + case Dir::Executable: ok = getExecutablePath(tmp, &len); break; + case Dir::Home: ok = getHomePath(tmp, &len); break; + case Dir::Temp: ok = getTempPath(tmp, &len); break; - case Dir::Temp: - getTempPath(tmp, &len); - break; - - case Dir::Home: - getHomePath(tmp, &len); - break; - - default: - len = 0; - break; + default: break; } + len = ok ? len : 0; + set(StringView(tmp, len) ); } diff --git a/tests/filepath_test.cpp b/tests/filepath_test.cpp index 24e1c7d..7df7659 100644 --- a/tests/filepath_test.cpp +++ b/tests/filepath_test.cpp @@ -133,3 +133,30 @@ TEST_CASE("FilePath temp", "[filepath]") REQUIRE(bx::removeAll(tmp, &err) ); REQUIRE(err.isOk() ); } + +TEST_CASE("FilePath special", "[filepath]") +{ + { + bx::FilePath tmp(bx::Dir::Current); + bx::StringView sv(tmp); + DBG("%S", &sv); + } + + { + bx::FilePath tmp(bx::Dir::Executable); + bx::StringView sv(tmp); + DBG("%S", &sv); + } + + { + bx::FilePath tmp(bx::Dir::Home); + bx::StringView sv(tmp); + DBG("%S", &sv); + } + + { + bx::FilePath tmp(bx::Dir::Temp); + bx::StringView sv(tmp); + DBG("%S", &sv); + } +}