summaryrefslogtreecommitdiffstats
path: root/source/core/slang-io.cpp
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2019-04-23 17:19:20 -0400
committerGitHub <noreply@github.com>2019-04-23 17:19:20 -0400
commit9cb75371f5ea45640ae0e3998eb27bcda0a22cd9 (patch)
tree8e4c18099888d88860c54c0a23c5fe345f3fd4b7 /source/core/slang-io.cpp
parent7a71b86aadda83d16dadf809be137c7551f31464 (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.cpp127
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));