Compare commits

...

1 Commits

Author SHA1 Message Date
Lioncash
70b02ed164 file_util: Make ForeachDirectoryEntry() use directory iterators
Simplifies the implementing code so that we don't need to explicitly
handle platform-specifics.
2020-12-09 19:14:24 -05:00
5 changed files with 56 additions and 84 deletions

View File

@@ -218,9 +218,9 @@ bool CreateEmptyFile(const std::string& filename) {
return true;
}
bool ForeachDirectoryEntry(u64* num_entries_out, const std::string& directory,
DirectoryEntryCallable callback) {
LOG_TRACE(Common_Filesystem, "directory {}", directory);
bool ForeachDirectoryEntry(u64* num_entries_out, const fs::path& directory,
const DirectoryEntryCallable& callback) {
LOG_TRACE(Common_Filesystem, "directory {}", directory.string());
// How many files + directories we found
u64 found_entries = 0;
@@ -228,52 +228,31 @@ bool ForeachDirectoryEntry(u64* num_entries_out, const std::string& directory,
// Save the status of callback function
bool callback_error = false;
#ifdef _WIN32
// Find the first file in the directory.
WIN32_FIND_DATAW ffd;
HANDLE handle_find = FindFirstFileW(Common::UTF8ToUTF16W(directory + "\\*").c_str(), &ffd);
if (handle_find == INVALID_HANDLE_VALUE) {
FindClose(handle_find);
return false;
}
// windows loop
do {
const std::string virtual_name = std::filesystem::path(ffd.cFileName).string();
#else
DIR* dirp = opendir(directory.c_str());
if (!dirp)
return false;
// non windows loop
while (struct dirent* result = readdir(dirp)) {
const std::string virtual_name(result->d_name);
#endif
if (virtual_name == "." || virtual_name == "..")
continue;
std::error_code ec;
for (const auto& entry : fs::directory_iterator(directory, ec)) {
u64 ret_entries = 0;
if (!callback(&ret_entries, directory, virtual_name)) {
if (!callback(&ret_entries, directory, entry.path().filename())) {
callback_error = true;
break;
}
found_entries += ret_entries;
#ifdef _WIN32
} while (FindNextFileW(handle_find, &ffd) != 0);
FindClose(handle_find);
#else
}
closedir(dirp);
#endif
if (callback_error)
if (ec) {
LOG_ERROR(Common_Filesystem, "Unable to completely enumerate directory {}: {}",
directory.string(), ec.message());
return false;
}
if (callback_error) {
return false;
}
// num_entries_out is allowed to be specified nullptr, in which case we shouldn't try to set it
if (num_entries_out != nullptr)
if (num_entries_out != nullptr) {
*num_entries_out = found_entries;
}
return true;
}

View File

@@ -84,20 +84,23 @@ bool CreateEmptyFile(const std::string& filename);
* @param virtual_name the entry name, without any preceding directory info
* @return whether handling the entry succeeded
*/
using DirectoryEntryCallable = std::function<bool(
u64* num_entries_out, const std::string& directory, const std::string& virtual_name)>;
using DirectoryEntryCallable =
std::function<bool(u64* num_entries_out, const std::filesystem::path& directory,
const std::filesystem::path& virtual_name)>;
/**
* Scans a directory, calling the callback for each file/directory contained within.
* If the callback returns failure, scanning halts and this function returns failure as well
* @param num_entries_out assigned by the function with the number of iterated directory entries,
* can be null
* @param directory the directory to scan
* @param callback The callback which will be called for each entry
*
* @param num_entries_out Assigned by the function with the number of iterated directory entries,
* can be null
* @param directory The directory to scan
* @param callback The callback which will be called for each entry
*
* @return whether scanning the directory succeeded
*/
bool ForeachDirectoryEntry(u64* num_entries_out, const std::string& directory,
DirectoryEntryCallable callback);
bool ForeachDirectoryEntry(u64* num_entries_out, const std::filesystem::path& directory,
const DirectoryEntryCallable& callback);
// Deletes the given path and anything under it. Returns true on success.
bool DeleteDirRecursively(const std::filesystem::path& path);

View File

@@ -4,6 +4,7 @@
#include <algorithm>
#include <cstddef>
#include <filesystem>
#include <iterator>
#include <utility>
#include "common/assert.h"
@@ -15,6 +16,7 @@
namespace FileSys {
namespace FS = Common::FS;
namespace stdfs = std::filesystem;
static std::string ModeFlagsToString(Mode mode) {
std::string mode_str;
@@ -313,10 +315,10 @@ std::vector<VirtualFile> RealVfsDirectory::IterateEntries<RealVfsFile, VfsFile>(
std::vector<VirtualFile> out;
FS::ForeachDirectoryEntry(
nullptr, path,
[&out, this](u64* entries_out, const std::string& directory, const std::string& filename) {
const std::string full_path = directory + DIR_SEP + filename;
[&out, this](u64*, const stdfs::path& directory, const stdfs::path& filename) {
const auto full_path = directory / filename;
if (!FS::IsDirectory(full_path)) {
out.emplace_back(base.OpenFile(full_path, perms));
out.emplace_back(base.OpenFile(full_path.string(), perms));
}
return true;
});
@@ -333,10 +335,10 @@ std::vector<VirtualDir> RealVfsDirectory::IterateEntries<RealVfsDirectory, VfsDi
std::vector<VirtualDir> out;
FS::ForeachDirectoryEntry(
nullptr, path,
[&out, this](u64* entries_out, const std::string& directory, const std::string& filename) {
const std::string full_path = directory + DIR_SEP + filename;
[&out, this](u64*, const stdfs::path& directory, const stdfs::path& filename) {
const auto full_path = directory / filename;
if (FS::IsDirectory(full_path)) {
out.emplace_back(base.OpenDirectory(full_path, perms));
out.emplace_back(base.OpenDirectory(full_path.string(), perms));
}
return true;
});
@@ -461,10 +463,9 @@ std::map<std::string, VfsEntryType, std::less<>> RealVfsDirectory::GetEntries()
std::map<std::string, VfsEntryType, std::less<>> out;
FS::ForeachDirectoryEntry(
nullptr, path,
[&out](u64* entries_out, const std::string& directory, const std::string& filename) {
const std::string full_path = directory + DIR_SEP + filename;
out.emplace(filename,
nullptr, path, [&out](u64*, const stdfs::path& directory, const stdfs::path& filename) {
const auto full_path = directory / filename;
out.emplace(filename.string(),
FS::IsDirectory(full_path) ? VfsEntryType::Directory : VfsEntryType::File);
return true;
});

View File

@@ -10,6 +10,7 @@
#include "yuzu/configuration/input_profiles.h"
namespace FS = Common::FS;
namespace stdfs = std::filesystem;
namespace {
@@ -18,40 +19,27 @@ bool ProfileExistsInFilesystem(std::string_view profile_name) {
FS::GetUserPath(FS::UserPath::ConfigDir), profile_name));
}
bool IsINI(std::string_view filename) {
const std::size_t index = filename.rfind('.');
if (index == std::string::npos) {
return false;
}
return filename.substr(index) == ".ini";
bool IsINI(const stdfs::path& filename) {
return filename.extension() == ".ini";
}
std::string GetNameWithoutExtension(const std::string& filename) {
const std::size_t index = filename.rfind('.');
if (index == std::string::npos) {
return filename;
}
return filename.substr(0, index);
stdfs::path GetNameWithoutExtension(stdfs::path filename) {
return filename.replace_extension();
}
} // namespace
} // Anonymous namespace
InputProfiles::InputProfiles() {
const std::string input_profile_loc =
fmt::format("{}input", FS::GetUserPath(FS::UserPath::ConfigDir));
FS::ForeachDirectoryEntry(
nullptr, input_profile_loc,
[this](u64* entries_out, const std::string& directory, const std::string& filename) {
if (IsINI(filename) && IsProfileNameValid(GetNameWithoutExtension(filename))) {
nullptr, input_profile_loc, [this](u64*, const stdfs::path&, const stdfs::path& filename) {
const auto name_without_ext = GetNameWithoutExtension(filename).string();
if (IsINI(filename) && IsProfileNameValid(name_without_ext)) {
map_profiles.insert_or_assign(
GetNameWithoutExtension(filename),
std::make_unique<Config>(GetNameWithoutExtension(filename),
Config::ConfigType::InputProfile));
name_without_ext,
std::make_unique<Config>(name_without_ext, Config::ConfigType::InputProfile));
}
return true;
});

View File

@@ -283,17 +283,18 @@ void GameListWorker::AddTitlesToGameList(GameListDir* parent_dir) {
void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_path,
unsigned int recursion, GameListDir* parent_dir) {
auto& system = Core::System::GetInstance();
namespace stdfs = std::filesystem;
auto& system = Core::System::GetInstance();
const auto callback = [this, target, recursion, parent_dir,
&system](u64* num_entries_out, const std::string& directory,
const std::string& virtual_name) -> bool {
&system](u64*, const stdfs::path& directory,
const stdfs::path& virtual_name) -> bool {
if (stop_processing) {
// Breaks the callback loop.
return false;
}
const std::string physical_name = directory + DIR_SEP + virtual_name;
const auto physical_name = (directory / virtual_name).string();
const bool is_dir = Common::FS::IsDirectory(physical_name);
if (!is_dir &&
(HasSupportedFileExtension(physical_name) || IsExtractedNCAMain(physical_name))) {