From c483756b42209d905d8fd4b4ef77f24ebe304a38 Mon Sep 17 00:00:00 2001 From: Daniel Kamil Kozar Date: Fri, 12 Nov 2021 18:16:15 +0100 Subject: [PATCH] Split directory.cpp into unix/win32 parts (#491) directory.cpp was essentially two implementations in one, separated with ifdefs. It's cleaner to just have two separate files, seeing how CMakeLists.txt for libmediation needs to check the platform it's running on and add the appropriate file implementation anyway. This commit splits this file into two and extracts common code parts to directory_priv.h. --- .clang-format | 1 + libmediation/CMakeLists.txt | 5 +- libmediation/fs/directory.cpp | 272 ---------------------- libmediation/fs/directory_priv.h | 55 +++++ libmediation/fs/osdep/directory_unix.cpp | 116 +++++++++ libmediation/fs/osdep/directory_win32.cpp | 131 +++++++++++ 6 files changed, 305 insertions(+), 275 deletions(-) delete mode 100644 libmediation/fs/directory.cpp create mode 100644 libmediation/fs/directory_priv.h create mode 100644 libmediation/fs/osdep/directory_unix.cpp create mode 100644 libmediation/fs/osdep/directory_win32.cpp diff --git a/.clang-format b/.clang-format index 70d59a3..790e200 100644 --- a/.clang-format +++ b/.clang-format @@ -6,3 +6,4 @@ BreakBeforeBraces: Allman AllowShortIfStatementsOnASingleLine: false IndentCaseLabels: false ColumnLimit: 120 +IncludeBlocks: Preserve diff --git a/libmediation/CMakeLists.txt b/libmediation/CMakeLists.txt index faec8b9..6f40921 100644 --- a/libmediation/CMakeLists.txt +++ b/libmediation/CMakeLists.txt @@ -2,17 +2,16 @@ cmake_minimum_required (VERSION 3.1) project(mediation) add_library(mediation STATIC - fs/directory.cpp types/types.cpp system/terminatablethread.cpp ) IF(WIN32) target_compile_definitions(mediation PRIVATE "-DUNICODE") - target_sources(mediation PRIVATE fs/osdep/file_win32.cpp) + target_sources(mediation PRIVATE fs/osdep/file_win32.cpp fs/osdep/directory_win32.cpp) ELSE() target_compile_definitions(mediation PRIVATE "-D_FILE_OFFSET_BITS=64") - target_sources(mediation PRIVATE fs/osdep/file_unix.cpp) + target_sources(mediation PRIVATE fs/osdep/file_unix.cpp fs/osdep/directory_unix.cpp) ENDIF() set(CMAKE_INCLUDE_CURRENT_DIR ON) diff --git a/libmediation/fs/directory.cpp b/libmediation/fs/directory.cpp deleted file mode 100644 index e0f0fef..0000000 --- a/libmediation/fs/directory.cpp +++ /dev/null @@ -1,272 +0,0 @@ - -#include "directory.h" - -#include -#include -#include - -#include - -#include "file.h" - -#ifdef _WIN32 -#include -#else -#include -#include -#include -#include -#include -#include -#endif - -using namespace std; - -char getDirSeparator() -{ -#ifdef _WIN32 - return '\\'; -#else - return '/'; -#endif -} - -string extractFileDir(const string& fileName) -{ - size_t index = fileName.find_last_of('/'); - if (index != string::npos) - return fileName.substr(0, index + 1); -#ifdef _WIN32 - index = fileName.find_last_of('\\'); - if (index != string::npos) - return fileName.substr(0, index + 1); -#endif - - return ""; -} - -bool fileExists(const string& fileName) -{ -#ifdef _WIN32 - File f; - return f.open(fileName.c_str(), File::ofRead | File::ofOpenExisting); -#else - struct stat buf; - return stat(fileName.c_str(), &buf) == 0; -#endif -} - -uint64_t getFileSize(const std::string& fileName) -{ -#ifdef _WIN32 - File f; - if (f.open(fileName.c_str(), File::ofRead | File::ofOpenExisting)) - { - uint64_t rv; - return f.size(&rv) ? rv : 0; - } - else - { - return 0; - } -#else - struct stat fileStat; - auto res = stat(fileName.c_str(), &fileStat) == 0; - return res ? static_cast(fileStat.st_size) : 0; -#endif -} - -bool createDir(const std::string& dirName, bool createParentDirs) -{ - if (dirName.empty()) - return false; - - if (createParentDirs) - { - for (string::size_type separatorPos = dirName.find_first_not_of(getDirSeparator()), dirEnd = string::npos; - separatorPos != string::npos; - dirEnd = separatorPos, separatorPos = dirName.find_first_not_of(getDirSeparator(), separatorPos)) - { - separatorPos = dirName.find(getDirSeparator(), separatorPos); - if (dirEnd != string::npos) - { - string parentDir = dirName.substr(0, dirEnd); -#if __linux__ == 1 || (defined(__APPLE__) && defined(__MACH__)) - if (mkdir(parentDir.c_str(), S_IREAD | S_IWRITE | S_IEXEC) == -1) - { - if (errno != EEXIST) - return false; - } -#elif defined(_WIN32) - if (parentDir.size() == 0 || parentDir[parentDir.size() - 1] == ':' || parentDir == string("\\\\.") || - parentDir == string("\\\\.\\") || // UNC patch prefix - (strStartWith(parentDir, "\\\\.\\") && parentDir[parentDir.size() - 1] == '}')) // UNC patch prefix - continue; - if (CreateDirectory(toWide(parentDir).data(), 0) == 0) - { - if (GetLastError() != ERROR_ALREADY_EXISTS) - return false; - } -#endif - } - } - } - -#if __linux__ == 1 || (defined(__APPLE__) && defined(__MACH__)) - return mkdir(dirName.c_str(), S_IREAD | S_IWRITE | S_IEXEC) == 0; -#elif defined(_WIN32) - return CreateDirectory(toWide(dirName).data(), 0) != 0; -#endif -} - -bool deleteFile(const string& fileName) -{ -#if __linux__ == 1 || (defined(__APPLE__) && defined(__MACH__)) - return unlink(fileName.c_str()) == 0; -#else - if (DeleteFile(toWide(fileName).data())) - { - return true; - } - else - { - DWORD err = GetLastError(); - return false; - } - - return DeleteFile(toWide(fileName).data()) != 0; -#endif -} - -//----------------------------------------------------------------------------- -#if defined(_WIN32) -/** windows implementation */ -//----------------------------------------------------------------------------- -#include - -bool findFiles(const string& path, const string& fileMask, vector* fileList, bool savePaths) -{ - WIN32_FIND_DATA fileData; // Data structure describes the file found - HANDLE hSearch; // Search handle returned by FindFirstFile - - auto searchStr = toWide(path + '/' + fileMask); - hSearch = FindFirstFile(searchStr.data(), &fileData); - if (hSearch == INVALID_HANDLE_VALUE) - return false; - - do - { - if (!(fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) - { - auto fileName = toUtf8(fileData.cFileName); - fileList->push_back(savePaths ? (path + '/' + fileName) : fileName); - } - } while (FindNextFile(hSearch, &fileData)); - - FindClose(hSearch); - - return true; -} - -bool findDirs(const string& path, vector* dirsList) -{ - WIN32_FIND_DATA fileData; // Data structure describes the file found - HANDLE hSearch; // Search handle returned by FindFirstFile - - auto searchStr = toWide(path + "*"); - hSearch = FindFirstFile(searchStr.data(), &fileData); - if (hSearch == INVALID_HANDLE_VALUE) - return false; - - do - { - if (!(fileData.dwFileAttributes ^ FILE_ATTRIBUTE_DIRECTORY)) - { - auto dirName = toUtf8(fileData.cFileName); - - if ("." != dirName && ".." != dirName) - dirsList->push_back(path + dirName + "/"); - } - - } while (FindNextFile(hSearch, &fileData)); - - FindClose(hSearch); - - return true; -} -#elif __linux__ == 1 || (defined(__APPLE__) && defined(__MACH__)) -#include - -bool findFiles(const string& path, const string& fileMask, vector* fileList, bool savePaths) -{ - dirent** namelist; - - int n = scandir(path.c_str(), &namelist, 0, 0); // alphasort); - - if (n < 0) - { - return false; - } - else - { - while (n--) - { - if (namelist[n]->d_type == DT_REG) - { - string fileName(namelist[n]->d_name); - - if (0 == fnmatch(fileMask.c_str(), fileName.c_str(), 0)) - fileList->push_back(savePaths ? path + fileName : fileName); - } - free(namelist[n]); - } - free(namelist); - } - - return true; -} - -bool findDirs(const string& path, vector* dirsList) -{ - dirent** namelist; - - int n = scandir(path.c_str(), &namelist, 0, 0); // alphasort); - - if (n < 0) - { - return false; - } - else - { - while (n--) - { - if (namelist[n]->d_type == DT_DIR) - { - string dirName(namelist[n]->d_name); - - // we save only normal ones - if ("." != dirName && ".." != dirName) - dirsList->push_back(path + dirName + "/"); - } - free(namelist[n]); - } - free(namelist); - } - - return true; -} -#endif -//----------------------------------------------------------------------------- - -bool findFilesRecursive(const string& path, const string& mask, vector* const fileList) -{ - // finding files - findFiles(path, mask, fileList, true); - - vector dirList; - findDirs(path, &dirList); - - for (unsigned int d_idx = 0; d_idx != dirList.size(); d_idx++) findFilesRecursive(dirList[d_idx], mask, fileList); - - return true; -} diff --git a/libmediation/fs/directory_priv.h b/libmediation/fs/directory_priv.h new file mode 100644 index 0000000..984f567 --- /dev/null +++ b/libmediation/fs/directory_priv.h @@ -0,0 +1,55 @@ +#ifndef libmediation_directory_priv_h +#define libmediation_directory_priv_h + +#include +#include + +template +void recurseDirectorySearch(F&& findFilesFn, D&& findDirsFn, const std::string& path, const std::string& mask, + std::vector* const fileList) +{ + // finding files + findFilesFn(path, mask, fileList, true); + + std::vector dirList; + findDirsFn(path, &dirList); + + for (auto&& dir : dirList) + { + recurseDirectorySearch(findFilesFn, findDirsFn, dir, mask, fileList); + } +} + +template +bool preCreateDir(SkipParentDirFn&& skipParentFn, CreateParentDirFn&& createParentFn, char dirSeparator, + const std::string& dirName, bool createParentDirs) +{ + if (dirName.empty()) + return false; + + if (createParentDirs) + { + for (auto separatorPos = dirName.find_first_not_of(dirSeparator), dirEnd = std::string::npos; + separatorPos != std::string::npos; + dirEnd = separatorPos, separatorPos = dirName.find_first_not_of(dirSeparator, separatorPos)) + { + separatorPos = dirName.find(dirSeparator, separatorPos); + if (dirEnd != std::string::npos) + { + auto parentDir = dirName.substr(0, dirEnd); + if (skipParentFn(parentDir)) + { + continue; + } + if (!createParentFn(parentDir)) + { + return false; + } + } + } + } + + return true; +} + +#endif diff --git a/libmediation/fs/osdep/directory_unix.cpp b/libmediation/fs/osdep/directory_unix.cpp new file mode 100644 index 0000000..7a3daac --- /dev/null +++ b/libmediation/fs/osdep/directory_unix.cpp @@ -0,0 +1,116 @@ +#include "../directory.h" +#include "../directory_priv.h" + +#include +#include +#include +#include +#include + +using namespace std; + +char getDirSeparator() { return '/'; } + +string extractFileDir(const string& fileName) +{ + size_t index = fileName.find_last_of('/'); + if (index != string::npos) + return fileName.substr(0, index + 1); + return ""; +} + +bool fileExists(const string& fileName) +{ + struct stat buf; + return stat(fileName.c_str(), &buf) == 0; +} + +uint64_t getFileSize(const std::string& fileName) +{ + struct stat fileStat; + auto res = stat(fileName.c_str(), &fileStat) == 0; + return res ? static_cast(fileStat.st_size) : 0; +} + +bool createDir(const std::string& dirName, bool createParentDirs) +{ + auto ok = preCreateDir([](auto) { return false; }, + [](auto&& parentDir) { + if (mkdir(parentDir.c_str(), S_IREAD | S_IWRITE | S_IEXEC) == -1) + { + if (errno != EEXIST) + return false; + } + return true; + }, + getDirSeparator(), dirName, createParentDirs); + + return ok ? mkdir(dirName.c_str(), S_IREAD | S_IWRITE | S_IEXEC) == 0 : false; +} + +bool deleteFile(const string& fileName) { return unlink(fileName.c_str()) == 0; } + +bool findFiles(const string& path, const string& fileMask, vector* fileList, bool savePaths) +{ + dirent** namelist; + + int n = scandir(path.c_str(), &namelist, 0, 0); // alphasort); + + if (n < 0) + { + return false; + } + else + { + while (n--) + { + if (namelist[n]->d_type == DT_REG) + { + string fileName(namelist[n]->d_name); + + if (0 == fnmatch(fileMask.c_str(), fileName.c_str(), 0)) + fileList->push_back(savePaths ? path + fileName : fileName); + } + free(namelist[n]); + } + free(namelist); + } + + return true; +} + +bool findDirs(const string& path, vector* dirsList) +{ + dirent** namelist; + + int n = scandir(path.c_str(), &namelist, 0, 0); // alphasort); + + if (n < 0) + { + return false; + } + else + { + while (n--) + { + if (namelist[n]->d_type == DT_DIR) + { + string dirName(namelist[n]->d_name); + + // we save only normal ones + if ("." != dirName && ".." != dirName) + dirsList->push_back(path + dirName + "/"); + } + free(namelist[n]); + } + free(namelist); + } + + return true; +} + +bool findFilesRecursive(const string& path, const string& mask, vector* const fileList) +{ + recurseDirectorySearch(findFiles, findDirs, path, mask, fileList); + return true; +} diff --git a/libmediation/fs/osdep/directory_win32.cpp b/libmediation/fs/osdep/directory_win32.cpp new file mode 100644 index 0000000..b8b2986 --- /dev/null +++ b/libmediation/fs/osdep/directory_win32.cpp @@ -0,0 +1,131 @@ +#include + +#include "../directory.h" +#include "../directory_priv.h" + +#include "../file.h" + +using namespace std; + +char getDirSeparator() { return '\\'; } + +string extractFileDir(const string& fileName) +{ + size_t index = fileName.find_last_of('\\'); + if (index != string::npos) + return fileName.substr(0, index + 1); + + return ""; +} + +bool fileExists(const string& fileName) +{ + File f; + return f.open(fileName.c_str(), File::ofRead | File::ofOpenExisting); +} + +uint64_t getFileSize(const std::string& fileName) +{ + File f; + if (f.open(fileName.c_str(), File::ofRead | File::ofOpenExisting)) + { + uint64_t rv; + return f.size(&rv) ? rv : 0; + } + else + { + return 0; + } +} + +bool createDir(const std::string& dirName, bool createParentDirs) +{ + bool ok = preCreateDir( + [](auto&& parentDir) { + return parentDir.empty() || parentDir[parentDir.size() - 1] == ':' || parentDir == "\\\\." || + parentDir == "\\\\.\\" || // UNC patch prefix + (strStartWith(parentDir, "\\\\.\\") && parentDir[parentDir.size() - 1] == '}'); // UNC patch prefix + }, + [](auto&& parentDir) { + if (CreateDirectory(toWide(parentDir).data(), 0) == 0) + { + if (GetLastError() != ERROR_ALREADY_EXISTS) + return false; + } + return true; + }, + getDirSeparator(), dirName, createParentDirs); + return ok ? CreateDirectory(toWide(dirName).data(), 0) != 0 : false; +} + +bool deleteFile(const string& fileName) +{ + if (DeleteFile(toWide(fileName).data())) + { + return true; + } + else + { + DWORD err = GetLastError(); + return false; + } + + return DeleteFile(toWide(fileName).data()) != 0; +} + +bool findFiles(const string& path, const string& fileMask, vector* fileList, bool savePaths) +{ + WIN32_FIND_DATA fileData; // Data structure describes the file found + HANDLE hSearch; // Search handle returned by FindFirstFile + + auto searchStr = toWide(path + '/' + fileMask); + hSearch = FindFirstFile(searchStr.data(), &fileData); + if (hSearch == INVALID_HANDLE_VALUE) + return false; + + do + { + if (!(fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + { + auto fileName = toUtf8(fileData.cFileName); + fileList->push_back(savePaths ? (path + '/' + fileName) : fileName); + } + } while (FindNextFile(hSearch, &fileData)); + + FindClose(hSearch); + + return true; +} + +bool findDirs(const string& path, vector* dirsList) +{ + WIN32_FIND_DATA fileData; // Data structure describes the file found + HANDLE hSearch; // Search handle returned by FindFirstFile + + auto searchStr = toWide(path + "*"); + hSearch = FindFirstFile(searchStr.data(), &fileData); + if (hSearch == INVALID_HANDLE_VALUE) + return false; + + do + { + if (!(fileData.dwFileAttributes ^ FILE_ATTRIBUTE_DIRECTORY)) + { + auto dirName = toUtf8(fileData.cFileName); + + if ("." != dirName && ".." != dirName) + dirsList->push_back(path + dirName + "/"); + } + + } while (FindNextFile(hSearch, &fileData)); + + FindClose(hSearch); + + return true; +} + +bool findFilesRecursive(const string& path, const string& mask, vector* const fileList) +{ + recurseDirectorySearch(findFiles, findDirs, path, mask, fileList); + return true; +}