Program Listing for File FileSystem.h

Program Listing for File FileSystem.h#

Return to documentation for file (src/util/FileSystem.h)

#ifndef ROSE_FileSystem_H
#define ROSE_FileSystem_H

#include <filesystem>
#include <regex>
#include <fstream>
#include <streambuf>
#include <string>
#include <vector>
#include <iterator>
#include "rosedll.h"
#include "mlog.h"

namespace Rose {

namespace FileSystem {

extern const char *tempNamePattern;

typedef std::filesystem::path Path;

typedef std::filesystem::directory_iterator DirectoryIterator;

typedef std::filesystem::recursive_directory_iterator RecursiveDirectoryIterator;

ROSE_UTIL_API bool isExisting(const Path &path);

ROSE_UTIL_API bool isFile(const Path &path);

ROSE_UTIL_API bool isDirectory(const Path &path);

ROSE_UTIL_API bool isSymbolicLink(const Path &path);

ROSE_UTIL_API bool isNotSymbolicLink(const Path &path);

class ROSE_UTIL_API baseNameMatches {
    const std::regex &re_;
public:
    baseNameMatches(const std::regex &re): re_(re) {}
    bool operator()(const Path &path);
};

ROSE_UTIL_API Path createTemporaryDirectory();

ROSE_UTIL_API Path makeNormal(const Path&);

ROSE_UTIL_API Path makeRelative(const Path &path, const Path &root = std::filesystem::current_path());

ROSE_UTIL_API Path makeAbsolute(const Path &path, const Path &root = std::filesystem::current_path());

template<class Select>
std::vector<Path> findNames(const Path &root, Select select) {
    std::vector<Path> matching;
    if (isDirectory(root)) {
        for (DirectoryIterator iter(root); iter!=DirectoryIterator(); ++iter) {
            if (select(iter->path()))
                matching.push_back(iter->path());
        }
    }
    std::sort(matching.begin(), matching.end());
    return matching;
}

ROSE_UTIL_API std::vector<Path> findNames(const Path &root);
template<class Select, class Descend>
std::vector<Path> findNamesRecursively(const Path &root, Select select, Descend descend) {
    std::vector<Path> matching;
    RecursiveDirectoryIterator end;
    for (RecursiveDirectoryIterator dentry(root); dentry!=end; ++dentry) {
        if (select(dentry->path()))
            matching.push_back(dentry->path());
        if (!descend(dentry->path()))
            dentry.disable_recursion_pending();
    }
    std::sort(matching.begin(), matching.end());
    return matching;
}

template<class Select>
std::vector<Path> findNamesRecursively(const Path &root, Select select) {
    return findNamesRecursively(root, select, isDirectory);
}

ROSE_UTIL_API std::vector<Path> findNamesRecursively(const Path &root);
ROSE_UTIL_API void copyFile(const Path &sourceFileName, const Path &destinationFileName);

ROSE_UTIL_API void copyFiles(const std::vector<Path> &files, const Path &root, const Path &destinationDirectory);

template<class Select, class Descend>
void copyFilesRecursively(const Path &root, const Path &destination, Select select, Descend descend) {
    std::vector<Path> files = findNamesRecursively(root, select, descend);
    files.erase(files.begin(), std::remove_if(files.begin(), files.end(), isFile)); // keep only isFile names
    copyFiles(files, root, destination);
}

ROSE_UTIL_API std::vector<Path> findRoseFilesRecursively(const Path &root);

ROSE_UTIL_API std::string toString(const Path&);

template<class Container>
Container readFile(const std::filesystem::path &fileName,
                   std::ios_base::openmode openMode = std::ios_base::in | std::ios_base::binary) {
    using streamIterator = std::istreambuf_iterator<char>;
    std::ifstream stream(fileName.c_str(), openMode);
    if (!stream.good())
        MLOG_ERROR_CXX("UTIL") << "unable to open file " << fileName.string();
    Container container;
    std::copy(streamIterator(stream), streamIterator(), std::back_inserter(container));
    if (stream.fail())
        MLOG_ERROR_CXX("UTIL") << "unable to read from file " << fileName.string();
    return container;
}

template<class Container>
void writeFile(const std::filesystem::path &fileName, const Container &data,
               std::ios_base::openmode openMode = std::ios_base::out | std::ios_base::binary) {
    std::ofstream stream(fileName.c_str(),openMode);
    if (!stream.good())
        MLOG_ERROR_CXX("UTIL") << "unable to open file " << fileName.string();
    std::ostream_iterator<char> streamIterator(stream);
    std::copy(data.begin(), data.end(), streamIterator);
    stream.close();
    if (stream.fail())
        MLOG_ERROR_CXX("UTIL") << "unable to write to file " << fileName.string();
}

} // namespace
} // namespace

#endif