diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2019-04-23 17:19:20 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-04-23 17:19:20 -0400 |
| commit | 9cb75371f5ea45640ae0e3998eb27bcda0a22cd9 (patch) | |
| tree | 8e4c18099888d88860c54c0a23c5fe345f3fd4b7 /source/core/slang-io.cpp | |
| parent | 7a71b86aadda83d16dadf809be137c7551f31464 (diff) | |
Feature/premake build (#951)
* * Remove Makefile
* Document how to create build using premake5
* Added support for finding the executable path
* If binDir not set on command line use the executable path
* Fix getting exe path on linux.
* Removed CalcExecutablePath from Path:: interface, made implementation internal.
* Documentation improvements.
* Fixes based on review
* Fix some typos
* Removed unused/needed global
Diffstat (limited to 'source/core/slang-io.cpp')
| -rw-r--r-- | source/core/slang-io.cpp | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/source/core/slang-io.cpp b/source/core/slang-io.cpp index cf099aa04..6d2320cd0 100644 --- a/source/core/slang-io.cpp +++ b/source/core/slang-io.cpp @@ -9,6 +9,18 @@ #ifdef _WIN32 # include <direct.h> + +# define WIN32_LEAN_AND_MEAN +# define VC_EXTRALEAN +# include <Windows.h> +#endif + +#if defined(__linux__) || defined(__CYGWIN__) +# include <unistd.h> +#endif + +#if SLANG_APPLE_FAMILY +# include <mach-o/dyld.h> #endif #include <limits.h> /* PATH_MAX */ @@ -316,6 +328,121 @@ namespace Slang #endif } + /// Gets the path to the executable that was invoked that led to the current threads execution + /// If run from a shared library/dll will be the path of the executable that loaded said library + /// @param outPath Pointer to buffer to hold the path. + /// @param ioPathSize Size of the buffer to hold the path (including zero terminator). + /// @return SLANG_OK on success, SLANG_E_BUFFER_TOO_SMALL if buffer is too small. If ioPathSize is changed it will be the required size + static SlangResult _calcExectuablePath(char* outPath, size_t* ioSize) + { + SLANG_ASSERT(ioSize); + const size_t bufferSize = *ioSize; + SLANG_ASSERT(bufferSize > 0); + +#if SLANG_WINDOWS_FAMILY + // https://docs.microsoft.com/en-us/windows/desktop/api/libloaderapi/nf-libloaderapi-getmodulefilenamea + + DWORD res = ::GetModuleFileNameA(::GetModuleHandle(nullptr), outPath, DWORD(bufferSize)); + // If it fits it's the size not including terminator. So must be less than bufferSize + if (res < bufferSize) + { + return SLANG_OK; + } + return SLANG_E_BUFFER_TOO_SMALL; +#elif SLANG_LINUX_FAMILY + +# if defined(__linux__) || defined(__CYGWIN__) + // https://linux.die.net/man/2/readlink + // Mark last byte with 0, so can check overrun + ssize_t resSize = ::readlink("/proc/self/exe", outPath, bufferSize); + if (resSize < 0) + { + return SLANG_FAIL; + } + if (resSize >= bufferSize) + { + return SLANG_E_BUFFER_TOO_SMALL; + } + // Zero terminate + outPath[resSize - 1] = 0; + return SLANG_OK; +# else + String text = Slang::File::ReadAllText("/proc/self/maps"); + UInt startIndex = text.IndexOf('/'); + if (startIndex == UInt(-1)) + { + return SLANG_FAIL; + } + UInt endIndex = text.IndexOf("\n", startIndex); + endIndex = (endIndex == UInt(-1)) ? text.Length() : endIndex; + + auto path = text.SubString(startIndex, endIndex - startIndex); + + if (path.getLength() < bufferSize) + { + ::memcpy(outPath, path.begin(), path.getLength()); + outPath[path.getLength()] = 0; + return SLANG_OK; + } + + *ioSize = path.getLength() + 1; + return SLANG_E_BUFFER_TOO_SMALL; +# endif + +#elif SLANG_APPLE_FAMILY + // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/dyld.3.html + uint32_t size = uint32_t(*ioSize); + switch (_NSGetExecutablePath(outPath, &size)) + { + case 0: return SLANG_OK; + case -1: + { + *ioSize = size; + return SLANG_E_BUFFER_TOO_SMALL; + } + default: break; + } + return SLANG_FAIL; +#else + return SLANG_E_NOT_IMPLEMENTED; +#endif + } + + static String _getExecutablePath() + { + List<char> buffer; + // Guess an initial buffer size + buffer.SetSize(1024); + + while (true) + { + const size_t size = buffer.Count(); + size_t bufferSize = size; + SlangResult res = _calcExectuablePath(buffer.Buffer(), &bufferSize); + + if (SLANG_SUCCEEDED(res)) + { + return String(buffer.Buffer()); + } + + if (res != SLANG_E_BUFFER_TOO_SMALL) + { + // Couldn't determine the executable string + return String(); + } + + // If bufferSize changed it should be the exact fit size, else we just make the buffer bigger by a guess (50% bigger) + bufferSize = (bufferSize > size) ? bufferSize : (bufferSize + bufferSize / 2); + buffer.SetSize(bufferSize); + } + } + + /* static */String Path::GetExecutablePath() + { + static String executablePath = _getExecutablePath(); + return executablePath; + } + Slang::String File::ReadAllText(const Slang::String & fileName) { StreamReader reader(new FileStream(fileName, FileMode::Open, FileAccess::Read, FileShare::ReadWrite)); |
