diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp index a286b93412..2446074fbb 100644 --- a/src/common/file_util.cpp +++ b/src/common/file_util.cpp @@ -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; } diff --git a/src/common/file_util.h b/src/common/file_util.h index cf006cc9dd..f94340eeb9 100644 --- a/src/common/file_util.h +++ b/src/common/file_util.h @@ -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; +using DirectoryEntryCallable = + std::function; /** * 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); diff --git a/src/core/file_sys/vfs_real.cpp b/src/core/file_sys/vfs_real.cpp index 3b70f7755b..3be43ce30c 100644 --- a/src/core/file_sys/vfs_real.cpp +++ b/src/core/file_sys/vfs_real.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #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 RealVfsDirectory::IterateEntries( std::vector 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 RealVfsDirectory::IterateEntries 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> RealVfsDirectory::GetEntries() std::map> 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; }); diff --git a/src/yuzu/configuration/input_profiles.cpp b/src/yuzu/configuration/input_profiles.cpp index e87aededb3..89845ea570 100644 --- a/src/yuzu/configuration/input_profiles.cpp +++ b/src/yuzu/configuration/input_profiles.cpp @@ -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(GetNameWithoutExtension(filename), - Config::ConfigType::InputProfile)); + name_without_ext, + std::make_unique(name_without_ext, Config::ConfigType::InputProfile)); } return true; }); diff --git a/src/yuzu/game_list_worker.cpp b/src/yuzu/game_list_worker.cpp index 23643aea22..4b665f4ae8 100644 --- a/src/yuzu/game_list_worker.cpp +++ b/src/yuzu/game_list_worker.cpp @@ -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))) {