diff --git a/lib/path.cpp b/lib/path.cpp index 0b8e5b423..97d05d4d3 100644 --- a/lib/path.cpp +++ b/lib/path.cpp @@ -25,6 +25,9 @@ #include #include #include +#ifndef _WIN32 +#include +#endif /** Is the filesystem case insensitive? */ static bool caseInsensitiveFilesystem() @@ -183,6 +186,35 @@ std::string Path::getFilenameExtensionInLowerCase(const std::string &path) return extension; } +const std::string Path::getCurrentPath() +{ + char currentPath[4096]; + + if (getcwd(currentPath, 4096) != 0) + return std::string(currentPath); + + return emptyString; +} + +bool Path::isAbsolute(const std::string& path) +{ + const std::string& nativePath = toNativeSeparators(path); + +#ifdef _WIN32 + if (path.length() < 2) + return false; + + // On Windows, 'C:\foo\bar' is an absolute path, while 'C:foo\bar' is not + if (nativePath.compare(0, 2, "\\\\") == 0 || (std::isalpha(nativePath[0]) != 0 && nativePath.compare(1, 2, ":\\") == 0)) + return true; +#else + if (!nativePath.empty() && nativePath[0] == '/') + return true; +#endif + + return false; +} + std::string Path::getRelativePath(const std::string& absolutePath, const std::vector& basePaths) { for (std::vector::const_iterator i = basePaths.begin(); i != basePaths.end(); ++i) { diff --git a/lib/path.h b/lib/path.h index 50f218b65..cc6ea5107 100644 --- a/lib/path.h +++ b/lib/path.h @@ -96,6 +96,19 @@ public: */ static std::string getFilenameExtensionInLowerCase(const std::string &path); + /** + * @brief Returns the absolute path of current working directory + * @return absolute path of current working directory + */ + static const std::string getCurrentPath(); + + /** + * @brief Check if given path is absolute + * @param path Path to check + * @return true if given path is absolute + */ + static bool isAbsolute(const std::string& path); + /** * @brief Create a relative path from an absolute one, if absolute path is inside the basePaths. * @param absolutePath Path to be made relative. diff --git a/test/testpath.cpp b/test/testpath.cpp index 874d7fcf5..c28c63ec5 100644 --- a/test/testpath.cpp +++ b/test/testpath.cpp @@ -30,6 +30,8 @@ private: void run() { TEST_CASE(simplify_path); TEST_CASE(accept_file); + TEST_CASE(getCurrentPath); + TEST_CASE(isAbsolute); TEST_CASE(getRelative); TEST_CASE(is_c); TEST_CASE(is_cpp); @@ -110,6 +112,28 @@ private: ASSERT_EQUALS(false, Path::acceptFile("index.hpp")); } + void getCurrentPath() const { + ASSERT_EQUALS(true, Path::isAbsolute(Path::getCurrentPath())); + } + + void isAbsolute() const { +#ifdef _WIN32 + ASSERT_EQUALS(true, Path::isAbsolute("C:\\foo\\bar")); + ASSERT_EQUALS(true, Path::isAbsolute("C:/foo/bar")); + ASSERT_EQUALS(true, Path::isAbsolute("\\\\foo\\bar")); + ASSERT_EQUALS(false, Path::isAbsolute("foo\\bar")); + ASSERT_EQUALS(false, Path::isAbsolute("foo/bar")); + ASSERT_EQUALS(false, Path::isAbsolute("foo.cpp")); + ASSERT_EQUALS(false, Path::isAbsolute("C:foo.cpp")); + ASSERT_EQUALS(false, Path::isAbsolute("C:foo\\bar.cpp")); +#else + ASSERT_EQUALS(true, Path::isAbsolute("/foo/bar")); + ASSERT_EQUALS(true, Path::isAbsolute("/")); + ASSERT_EQUALS(false, Path::isAbsolute("foo/bar")); + ASSERT_EQUALS(false, Path::isAbsolute("foo.cpp")); +#endif + } + void getRelative() const { std::vector basePaths; basePaths.push_back(""); // Don't crash with empty paths