/* * Author: Patrick-Christopher Mattulat * Company: Lynar Studios * E-Mail: webmaster@lynarstudios.com * Created: 2020-08-15 * Changed: 2020-08-17 * * */ #include "File.hpp" #include "../exception/FileOperationException.hpp" #include "FilePathSeparatorMatch.hpp" #include #include #include #include #include #if defined(unix) || defined(__APPLE__) #include #include #endif #ifdef _WIN32 #include #endif ls_std::File::File(std::string _absoluteFilePath) : Class("File"), absoluteFilePath(ls_std::File::_normalizePath(std::move(_absoluteFilePath))) {} bool ls_std::File::operator==(File &_file) { return this->absoluteFilePath == _file.getAbsoluteFilePath(); } bool ls_std::File::operator!=(File &_file) { return this->absoluteFilePath != _file.getAbsoluteFilePath(); } bool ls_std::File::canExecute() { bool executable {}; struct stat _stat {}; if(stat(this->absoluteFilePath.c_str(), &_stat) == 0) { executable = (_stat.st_mode & (unsigned short) S_IEXEC) != 0; } return executable; } void ls_std::File::createNewFile() { if(!ls_std::File::_exists(this->absoluteFilePath)) { std::ofstream file {this->absoluteFilePath}; file.close(); } else { throw ls_std::FileOperationException{this->absoluteFilePath}; } } bool ls_std::File::exists() { return ls_std::File::_exists(this->absoluteFilePath); } std::string ls_std::File::getAbsoluteFilePath() { return this->absoluteFilePath; } std::string ls_std::File::getName() { std::string copy = this->absoluteFilePath; // if it's a directory, remove separator from end, if it does exist if(ls_std::File::_isDirectory(this->absoluteFilePath)) { copy.erase(std::remove_if(copy.end() - 1, copy.end(), ls_std::FilePathSeparatorMatch()), copy.end()); } // now get the file / directory name auto base = std::find_if(copy.rbegin(), copy.rend(), ls_std::FilePathSeparatorMatch()).base(); return std::string(base, copy.end()); } std::string ls_std::File::getParent() { return ls_std::File::_getParent(this->absoluteFilePath); } long ls_std::File::getSize() { std::streampos fileSize {}; if(ls_std::File::_exists(this->absoluteFilePath)) { std::ifstream fileHandler{this->absoluteFilePath, std::ios::in}; fileSize = fileHandler.tellg(); fileHandler.seekg(0, std::ios::end); fileSize = fileHandler.tellg() - fileSize; fileHandler.close(); } return fileSize; } bool ls_std::File::isDirectory() { return ls_std::File::_isDirectory(this->absoluteFilePath); } bool ls_std::File::isFile() { return ls_std::File::_isFile(this->absoluteFilePath); } time_t ls_std::File::lastModified() { return ls_std::File::_lastModified(this->absoluteFilePath); } std::list ls_std::File::list() { std::list fileList {}; if(ls_std::File::_isDirectory(this->absoluteFilePath)) { fileList = ls_std::File::_list(this->absoluteFilePath); } return fileList; } std::list ls_std::File::listFiles() { std::list fileList {}; if(ls_std::File::_isDirectory(this->absoluteFilePath)) { fileList = ls_std::File::_listFiles(this->absoluteFilePath); } return fileList; } void ls_std::File::makeDirectory() { if(ls_std::File::_mkdir(this->absoluteFilePath)) { throw ls_std::FileOperationException {this->absoluteFilePath}; } } void ls_std::File::makeDirectories() { std::vector subDirectories = ls_std::File::_splitIntoSubDirectoryNames(this->absoluteFilePath); const char separator = ls_std::FilePathSeparator::getOperatingSystemSpecificSeparator(); std::string currentHierarchy {}; for(const auto& subDirectory : subDirectories) { currentHierarchy += subDirectory; if(!ls_std::File::_exists(currentHierarchy)) { ls_std::File::_mkdir(currentHierarchy); } currentHierarchy += separator; } } void ls_std::File::remove() { if(ls_std::File::_isFile(this->absoluteFilePath)) { if(std::remove(this->absoluteFilePath.c_str())) { throw ls_std::FileOperationException{this->absoluteFilePath}; } } if(ls_std::File::_isDirectory(this->absoluteFilePath)) { if(rmdir(this->absoluteFilePath.c_str())) { throw ls_std::FileOperationException{this->absoluteFilePath}; } } } bool ls_std::File::_exists(const std::string& _path) { struct stat _stat {}; return (stat(_path.c_str(), &_stat) == 0); } std::string ls_std::File::_getParent(const std::string &_path) { std::string parent {}; std::vector subDirectoryNames = ls_std::File::_splitIntoSubDirectoryNames(_path); const char separator = ls_std::FilePathSeparator::getOperatingSystemSpecificSeparator(); subDirectoryNames.pop_back(); for(auto const& subDirectoryName : subDirectoryNames) { parent += subDirectoryName + separator; } return parent; } bool ls_std::File::_isDirectory(const std::string& _path) { bool match {}; struct stat _stat {}; if(stat(_path.c_str(), &_stat) == 0) { match = _stat.st_mode & (unsigned short) S_IFDIR; } return match; } bool ls_std::File::_isFile(const std::string& _path) { bool match {}; struct stat _stat {}; if(stat(_path.c_str(), &_stat) == 0) { match = _stat.st_mode & (unsigned short) S_IFREG; } return match; } time_t ls_std::File::_lastModified(const std::string &_path) { time_t lastModifiedTimeStamp {}; struct stat _stat {}; if(stat(_path.c_str(), &_stat) == 0) { lastModifiedTimeStamp = _stat.st_mtime; } return lastModifiedTimeStamp; } std::list ls_std::File::_list(const std::string &_path) { std::list filesInDirectory {}; #if defined(unix) || defined(__APPLE__) filesInDirectory = ls_std::File::_listUnix(_path, true); #endif #ifdef _WIN32 filesInDirectory = ls_std::File::_listWindows(_path, true); #endif return filesInDirectory; } std::list ls_std::File::_listFiles(const std::string &_path) { std::list filesInDirectory {}; #if defined(unix) || defined(__APPLE__) filesInDirectory = ls_std::File::_listUnix(_path, false); #endif #ifdef _WIN32 filesInDirectory = ls_std::File::_listWindows(_path, false); #endif return filesInDirectory; } #if defined(unix) || defined(__APPLE__) std::list ls_std::File::_listUnix(const std::string &_path, bool withDirectories) { std::list filesInDirectory {}; DIR* directory = opendir(_path.c_str()); struct dirent* directoryEntity; std::string parent = ls_std::File::_getParent(_path); std::string absolutePath {}; while((directoryEntity = readdir(directory)) != nullptr) { absolutePath = parent + directoryEntity->d_name; if(withDirectories) { filesInDirectory.emplace_back(absolutePath); } else { if(ls_std::File::_isFile(absolutePath)) { filesInDirectory.emplace_back(absolutePath); } } } return filesInDirectory; } #endif #ifdef _WIN32 std::list ls_std::File::_listWindows(const std::string &_path, bool withDirectories) { std::list filesInDirectory {}; WIN32_FIND_DATA data {}; HANDLE hFind; std::string parent = ls_std::File::_getParent(_path); std::string pattern {_path + ls_std::FilePathSeparator::getOperatingSystemSpecificSeparator() + "*"}; std::string absolutePath {}; if((hFind = FindFirstFile(pattern.c_str(), &data)) != INVALID_HANDLE_VALUE) { do { absolutePath = parent + data.cFileName; if(withDirectories) { filesInDirectory.emplace_back(absolutePath); } else { if(ls_std::File::_isFile(absolutePath)) { filesInDirectory.emplace_back(absolutePath); } } } while(FindNextFile(hFind, &data) != 0); FindClose(hFind); } return filesInDirectory; } #endif int ls_std::File::_mkdir(const std::string& _path) { int result; #ifdef _WIN32 result = mkdir(_path.c_str()); #endif #if defined(unix) || defined(__APPLE__) result = mkdir(_path.c_str(), 0777); #endif return result; } std::string ls_std::File::_normalizePath(std::string _path) { const char unixSeparator = ls_std::FilePathSeparator::getUnixFilePathSeparator(); const char windowsSeparator = ls_std::FilePathSeparator::getWindowsFilePathSeparator(); #if defined(unix) || defined(__APPLE__) std::replace(_path.begin(), _path.end(), windowsSeparator, unixSeparator); #endif #ifdef _WIN32 std::replace(_path.begin(), _path.end(), unixSeparator, windowsSeparator); #endif return _path; } std::vector ls_std::File::_splitIntoSubDirectoryNames(const std::string& _path) { std::vector subDirectoryNames {}; std::stringstream _stream {_path}; std::string subDirectoryName {}; const char separator = ls_std::FilePathSeparator::getOperatingSystemSpecificSeparator(); while(std::getline(_stream, subDirectoryName, separator)) { subDirectoryNames.push_back(subDirectoryName); } return subDirectoryNames; }