Program Listing for File FileHelper.h#
↰ Return to documentation for file (src/util/support/FileHelper.h)
// Consider using $ROSE/src/util/FileSystem.h since that one is documented and uses a proper path type and supports both
// version 2 and version 3 of std::filesystem.
// UNDER NO CIRCUMSTANCES SHOULD BOOST_FILESYSTEM_VERSION BE SET!!!
//
// The std::filesystem version is not dependent on which compiler we're using, but rather which version
// of boost is installed. Hard-coding a boost version number based on the compiler version has a couple of problems:
// 1. We don't know whether that filesystem version is available on a user's machine since ROSE supports multiple
// versions of boost (e.g., filesystem 3 is not available before boost 1.44)
// 2. It pollutes things for the user, who might not want the version we select here (e.g., most users of recent
// versions of boost will almost certainly want version 3, not the version 2 we select).
// Therefore, we should never select a filesystem version explicitly here, but rather be prepared to handle any version
// that is installed. If ROSE cannot support a particular version of std::filesystem on a particular architecture with a
// particular file then that should be documented where we state which versions of boost are supported, and possibly
// checked during configuration. [Matzke 11/17/2014]:
#include <FileSystem.h>
#include <string>
#include <filesystem>
class FileHelper {
public:
// This is initialized in src/frontend/SageIII/sage_support/sage_support.cpp, not FileHelper.C
static const std::string pathDelimiter;
static void ensureParentFolderExists(const std::string& path) {
ensureFolderExists(getParentFolder(path));
}
static void ensureFolderExists(const std::string& folder){
std::filesystem::path boostPath(folder);
create_directories(boostPath);
}
static void eraseFolder(const std::string& folder) {
std::filesystem::path boostPath(folder);
remove_all(boostPath);
}
static std::string concatenatePaths(const std::string& path1, const std::string& path2) {
if (path1.size() == 0) {
return path2;
}
if (path2.size() == 0) {
return path1;
}
return path1 + pathDelimiter + path2;
}
static std::string getParentFolder(const std::string& aPath) {
std::filesystem::path boostPath(aPath);
return boostPath.parent_path().string();
}
static std::string getFileName(const std::string& aPath) {
return Rose::FileSystem::toString(std::filesystem::path(aPath).filename());
}
static std::string makeAbsoluteNormalizedPath(const std::string& path, const std::string& workingDirectory) {
if (!isAbsolutePath(path)) {
//relative path, so prepend the working directory and then normalize
return normalizePath(concatenatePaths(workingDirectory, path));
} else {
return normalizePath(path);
}
}
static bool isAbsolutePath(const std::string& path) {
return path.compare(0, 1, pathDelimiter) == 0;
}
//Expects both paths to be absolute.
static bool areEquivalentPaths(const std::string& path1, const std::string& path2) {
//Note: Do not use std::filesystem::equivalent since the compared paths might not exist, which will cause an error.
return normalizePath(path1).compare(normalizePath(path2)) == 0;
}
static std::string getIncludedFilePath(const std::list<std::string>& prefixPaths, const std::string& includedPath) {
for (std::list<std::string>::const_iterator prefixPathPtr = prefixPaths.begin(); prefixPathPtr != prefixPaths.end(); prefixPathPtr++) {
std::string potentialPath = concatenatePaths(*prefixPathPtr, includedPath);
if (fileExists(potentialPath)) {
return potentialPath;
}
}
//The included file was not found, so return an empty string.
return "";
}
//Assumes that both arguments are absolute and normalized.
//Argument toPath can be either a folder or a file.
static std::string getRelativePath(const std::string& fromFolder, const std::string& toPath) {
return Rose::FileSystem::toString(Rose::FileSystem::makeRelative(toPath, fromFolder));
}
static bool fileExists(const std::string& fullFileName) {
return std::filesystem::exists(fullFileName);
}
static bool isNotEmptyFolder(const std::string& fullFolderName) {
return std::filesystem::exists(fullFolderName) && !std::filesystem::is_empty(fullFolderName);
}
static std::string normalizePath(const std::string& aPath) {
std::filesystem::path boostPath(aPath);
std::string normalizedPath = std::filesystem::canonical(boostPath).string();
return normalizedPath;
}
static std::string getNormalizedContainingFileName(PreprocessingInfo* preprocessingInfo) {
return normalizePath(preprocessingInfo -> get_file_info() -> get_filenameString());
}
//Either path1 includes path2 or vice versa
static std::string pickMoreGeneralPath(const std::string& path1, const std::string& path2) {
std::string textualPart1 = getTextualPart(path1);
std::string textualPart2 = getTextualPart(path2);
//The longer textual part should be more general, assert that
std::string moreGeneralPath = textualPart1.size() > textualPart2.size() ? textualPart1 : textualPart2;
ROSE_ASSERT(endsWith(moreGeneralPath, textualPart1));
ROSE_ASSERT(endsWith(moreGeneralPath, textualPart2));
return moreGeneralPath;
}
static std::string getTextualPart(const std::string& path) {
std::string normalizedPath = normalizePath(path);
//Remove all leading "../" and "./" (and they can be only leading, since the path is normalized).
size_t pos = normalizedPath.rfind(".." + pathDelimiter);
if (pos != std::string::npos) {
normalizedPath = normalizedPath.substr(pos + 3);
}
pos = normalizedPath.rfind("." + pathDelimiter);
if (pos != std::string::npos) {
normalizedPath = normalizedPath.substr(pos + 2);
}
return normalizedPath;
}
//Count how many leading "../" are in a path (after its normalization)
static int countUpsToParentFolder(const std::string& path) {
std::string normalizedPath = normalizePath(path);
std::string upPath = ".." + pathDelimiter;
int counter = 0;
size_t pos = normalizedPath.find(upPath);
while (pos != std::string::npos) {
counter++;
pos = normalizedPath.find(upPath, pos + 3);
}
return counter;
}
static bool endsWith(const std::string& str1, const std::string& str2) { //checks that str1 ends with str2
if (str2.size() > str1.size()) return false;
return str1.compare(str1.size() - str2.size(), str2.size(), str2) == 0;
}
};