summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBert Belder <bertbelder@gmail.com>2018-08-26 01:37:15 +0200
committerBert Belder <bertbelder@gmail.com>2018-08-26 18:27:23 +0200
commit26707446fc83a6f6c7152153db43db4152698f58 (patch)
tree184a4765b5d5d15046a96c49e0db6800729bcf16
parentddddd50540847a34697380a6f1fc4336d3f20c83 (diff)
libdeno: add file utilities Dirname() and ExePath()
-rw-r--r--libdeno/file_util.cc59
-rw-r--r--libdeno/file_util.h2
-rw-r--r--libdeno/file_util_test.cc29
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);
+}