diff options
author | Bert Belder <bertbelder@gmail.com> | 2018-08-26 01:37:15 +0200 |
---|---|---|
committer | Bert Belder <bertbelder@gmail.com> | 2018-08-26 18:27:23 +0200 |
commit | 26707446fc83a6f6c7152153db43db4152698f58 (patch) | |
tree | 184a4765b5d5d15046a96c49e0db6800729bcf16 | |
parent | ddddd50540847a34697380a6f1fc4336d3f20c83 (diff) |
libdeno: add file utilities Dirname() and ExePath()
-rw-r--r-- | libdeno/file_util.cc | 59 | ||||
-rw-r--r-- | libdeno/file_util.h | 2 | ||||
-rw-r--r-- | libdeno/file_util_test.cc | 29 |
3 files changed, 88 insertions, 2 deletions
diff --git a/libdeno/file_util.cc b/libdeno/file_util.cc index a0cae5f58..8df0dafea 100644 --- a/libdeno/file_util.cc +++ b/libdeno/file_util.cc @@ -1,10 +1,21 @@ // Copyright 2018 the Deno authors. All rights reserved. MIT license. #include <inttypes.h> +#include <limits.h> +#include <stdint.h> #include <stdio.h> +#include <stdlib.h> #include <fstream> #include <iterator> #include <string> +#ifdef __APPLE__ +#include <mach-o/dyld.h> +#endif + +#ifdef _WIN32 +#include <windows.h> +#endif + #include "file_util.h" namespace deno { @@ -28,4 +39,52 @@ std::string Basename(std::string const& filename) { return filename; } +// Returns the directory component from a filename. The returned path always +// ends with a slash. This function does not understand Windows drive letters. +std::string Dirname(std::string const& filename) { + for (auto it = filename.rbegin(); it != filename.rend(); ++it) { + char ch = *it; + if (ch == '\\' || ch == '/') { + return std::string(filename.begin(), it.base()); + } + } + return std::string("./"); +} + +// Returns the full path the currently running executable. +// This implementation is very basic. Caveats: +// * OS X: fails if buffer is too small, does not retry with a bigger buffer. +// * Windows: ANSI only, no unicode. Fails if path is longer than 260 chars. +bool ExePath(std::string* path) { +#ifdef _WIN32 + // Windows only. + char exe_buf[MAX_PATH]; + DWORD len = GetModuleFileNameA(NULL, exe_buf, sizeof exe_buf); + if (len == 0 || len == sizeof exe_buf) { + return false; + } +#else +#ifdef __APPLE__ + // OS X only. + char link_buf[PATH_MAX * 2]; // Exe may be longer than MAX_PATH, says Apple. + uint32_t len = sizeof link_buf; + if (_NSGetExecutablePath(link_buf, &len) < 0) { + return false; + } +#else + // Linux only. + static const char* link_buf = "/proc/self/exe"; +#endif + // Linux and OS X. + char exe_buf[PATH_MAX]; + char* r = realpath(link_buf, exe_buf); + if (r == NULL) { + return false; + } +#endif + // All platforms. + path->assign(exe_buf); + return true; +} + } // namespace deno diff --git a/libdeno/file_util.h b/libdeno/file_util.h index c8c0e5759..63ecef907 100644 --- a/libdeno/file_util.h +++ b/libdeno/file_util.h @@ -7,6 +7,8 @@ namespace deno { bool ReadFileToString(const char* fn, std::string* contents); std::string Basename(std::string const& filename); +std::string Dirname(std::string const& filename); +bool ExePath(std::string* path); } // namespace deno #endif // FILE_UTIL_H_ diff --git a/libdeno/file_util_test.cc b/libdeno/file_util_test.cc index 3f01c8115..a7b6727e1 100644 --- a/libdeno/file_util_test.cc +++ b/libdeno/file_util_test.cc @@ -11,11 +11,36 @@ TEST(FileUtilTest, ReadFileToStringFileNotExist) { TEST(FileUtilTest, Basename) { EXPECT_EQ("foo.txt", deno::Basename("foo.txt")); EXPECT_EQ("foo.txt", deno::Basename("/foo.txt")); + EXPECT_EQ("", deno::Basename("/foo/")); + EXPECT_EQ("", deno::Basename("foo/")); EXPECT_EQ("", deno::Basename("/")); EXPECT_EQ("foo.txt", deno::Basename(".\\foo.txt")); EXPECT_EQ("foo.txt", deno::Basename("/home/ryan/foo.txt")); EXPECT_EQ("foo.txt", deno::Basename("C:\\home\\ryan\\foo.txt")); } -// TODO(ry) success unit test. Needs a tempfile or fixture. -// TEST(FileUtilTest, ReadFileToStringSuccess) { } +TEST(FileUtilTest, Dirname) { + EXPECT_EQ("home/dank/", deno::Dirname("home/dank/memes.gif")); + EXPECT_EQ("/home/dank/", deno::Dirname("/home/dank/memes.gif")); + EXPECT_EQ("/home/dank/", deno::Dirname("/home/dank/")); + EXPECT_EQ("home/dank/", deno::Dirname("home/dank/memes.gif")); + EXPECT_EQ("/", deno::Dirname("/")); + EXPECT_EQ(".\\", deno::Dirname(".\\memes.gif")); + EXPECT_EQ("c:\\", deno::Dirname("c:\\stuff")); + EXPECT_EQ("./", deno::Dirname("nothing")); + EXPECT_EQ("./", deno::Dirname("")); +} + +TEST(FileUtilTest, ExePath) { + std::string exe_path; + EXPECT_TRUE(deno::ExePath(&exe_path)); + // Path is absolute. + EXPECT_TRUE(exe_path.find("/") == 0 || exe_path.find(":\\") == 1); + // FIlename is the name of the test binary. + std::string exe_filename = deno::Basename(exe_path); + EXPECT_EQ(exe_filename.find("test_cc"), 0); + // Path exists (also tests ReadFileToString). + std::string contents; + EXPECT_TRUE(deno::ReadFileToString(exe_path.c_str(), &contents)); + EXPECT_NE(contents.find("Inception :)"), std::string::npos); +} |