#include "utility/file/FilePath.h" #include #include "utility/logging/logging.h" FilePath::FilePath() : m_exists(false) , m_checkedExists(false) { } FilePath::FilePath(const char* filePath) : m_path(filePath) , m_exists(false) , m_checkedExists(false) { } FilePath::FilePath(const std::string& filePath) : m_path(filePath) , m_exists(false) , m_checkedExists(false) { } FilePath::FilePath(const boost::filesystem::path& filePath) : m_path(filePath) , m_exists(false) , m_checkedExists(false) { } boost::filesystem::path FilePath::path() const { return m_path; } bool FilePath::empty() const { return m_path.empty(); } bool FilePath::exists() const { if (!m_checkedExists) { m_exists = boost::filesystem::exists(m_path); m_checkedExists = true; } return m_exists; } bool FilePath::isDirectory() const { return boost::filesystem::is_directory(m_path); } bool FilePath::isAbsolute() const { return m_path.is_absolute(); } FilePath FilePath::parentDirectory() const { return m_path.parent_path(); } FilePath FilePath::absolute() const { return boost::filesystem::absolute(m_path); } FilePath FilePath::canonical() const { if (!exists()) { return FilePath(m_path); } boost::filesystem::path abs_p = boost::filesystem::absolute(m_path); boost::filesystem::path result; for (boost::filesystem::path::iterator it = abs_p.begin(); it != abs_p.end(); ++it) { if (*it == "..") { // /a/b/.. is not necessarily /a if b is a symbolic link if (boost::filesystem::is_symlink(result)) result /= *it; // /a/b/../.. is not /a/b/.. under most circumstances // We can end up with ..s in our result because of symbolic links else if (result.filename() == "..") result /= *it; // Otherwise it should be safe to resolve the parent else result = result.parent_path(); } else if (*it == ".") { // Ignore } else { // Just cat other path entries result /= *it; } } return result; } FilePath FilePath::expandEnvironmentVariables() const { std::string text = str(); static std::regex env("\\$\\{([^}]+)\\}|%([0-9A-Za-z\\/]*)%"); std::smatch match; while (std::regex_search(text, match, env)) { const char * s = getenv(match[1].str().c_str()); if (s == nullptr) { LOG_ERROR(match[1].str() + " is no a environment variable"); return FilePath(); } text.replace( match.position(0), match.length(0), s); } return FilePath(text); } FilePath FilePath::relativeTo(const FilePath& other) const { boost::filesystem::path a = this->canonical().m_path; boost::filesystem::path b = other.canonical().m_path; if (a.root_path() != b.root_path()) { return str(); } boost::filesystem::path::const_iterator itA = a.begin(); boost::filesystem::path::const_iterator itB = b.begin(); while (*itA == *itB && itA != a.end() && itB != b.end()) { itA++; itB++; } boost::filesystem::path r; if (itB != b.end()) { itB++; for (; itB != b.end(); itB++) { r /= ".."; } } for (; itA != a.end(); itA++) { r /= *itA; } return r; } FilePath FilePath::concat(const FilePath& other) const { return boost::filesystem::path(m_path) / other.m_path; } std::string FilePath::str() const { return m_path.generic_string(); } std::string FilePath::fileName() const { return m_path.filename().generic_string(); } std::string FilePath::extension() const { return m_path.extension().generic_string(); } FilePath FilePath::withoutExtension() const { return FilePath(boost::filesystem::path(m_path).replace_extension()); } FilePath FilePath::replaceExtension(const std::string& extension) const { return FilePath(boost::filesystem::path(m_path).replace_extension(extension)); } bool FilePath::hasExtension(const std::vector& extensions) const { std::string e = extension(); for (std::string ext : extensions) { if (e == ext) { return true; } } return false; } bool FilePath::operator==(const FilePath& other) const { if (exists() && other.exists()) { return boost::filesystem::equivalent(m_path, other.m_path); } return m_path.compare(other.m_path) == 0; } bool FilePath::operator!=(const FilePath& other) const { return !(*this == other); } bool FilePath::operator<(const FilePath& other) const { return m_path.compare(other.m_path) < 0; }