Merge pull request #1751 from linkmauve/no-recursive-readdir
Make recursive FileUtil functions take a maximum recursion
This commit is contained in:
		| @@ -118,19 +118,20 @@ void GameList::LoadInterfaceLayout() | ||||
|     item_model->sort(header->sortIndicatorSection(), header->sortIndicatorOrder()); | ||||
| } | ||||
|  | ||||
| void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, bool deep_scan) | ||||
| void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsigned int recursion) | ||||
| { | ||||
|     const auto callback = [&](unsigned* num_entries_out, | ||||
|                               const std::string& directory, | ||||
|                               const std::string& virtual_name) -> bool { | ||||
|                               const std::string& virtual_name, | ||||
|                               unsigned int recursion) -> bool { | ||||
|  | ||||
|         std::string physical_name = directory + DIR_SEP + virtual_name; | ||||
|  | ||||
|         if (stop_processing) | ||||
|             return false; // Breaks the callback loop. | ||||
|  | ||||
|         if (deep_scan && FileUtil::IsDirectory(physical_name)) { | ||||
|             AddFstEntriesToGameList(physical_name, true); | ||||
|         if (recursion > 0 && FileUtil::IsDirectory(physical_name)) { | ||||
|             AddFstEntriesToGameList(physical_name, recursion - 1); | ||||
|         } else { | ||||
|             std::unique_ptr<Loader::AppLoader> loader = Loader::GetLoader(physical_name); | ||||
|             if (!loader) | ||||
| @@ -155,7 +156,7 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, bool d | ||||
| void GameListWorker::run() | ||||
| { | ||||
|     stop_processing = false; | ||||
|     AddFstEntriesToGameList(dir_path.toStdString(), deep_scan); | ||||
|     AddFstEntriesToGameList(dir_path.toStdString(), deep_scan ? 256 : 0); | ||||
|     emit Finished(); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -181,5 +181,5 @@ private: | ||||
|     bool deep_scan; | ||||
|     std::atomic_bool stop_processing; | ||||
|  | ||||
|     void AddFstEntriesToGameList(const std::string& dir_path, bool deep_scan); | ||||
|     void AddFstEntriesToGameList(const std::string& dir_path, unsigned int recursion = 0); | ||||
| }; | ||||
|   | ||||
| @@ -434,7 +434,7 @@ bool CreateEmptyFile(const std::string &filename) | ||||
| } | ||||
|  | ||||
|  | ||||
| bool ForeachDirectoryEntry(unsigned* num_entries_out, const std::string &directory, DirectoryEntryCallable callback) | ||||
| bool ForeachDirectoryEntry(unsigned* num_entries_out, const std::string &directory, DirectoryEntryCallable callback, unsigned int recursion) | ||||
| { | ||||
|     LOG_TRACE(Common_Filesystem, "directory %s", directory.c_str()); | ||||
|  | ||||
| @@ -472,7 +472,7 @@ bool ForeachDirectoryEntry(unsigned* num_entries_out, const std::string &directo | ||||
|             continue; | ||||
|  | ||||
|         unsigned ret_entries = 0; | ||||
|         if (!callback(&ret_entries, directory, virtual_name)) { | ||||
|         if (!callback(&ret_entries, directory, virtual_name, recursion)) { | ||||
|             callback_error = true; | ||||
|             break; | ||||
|         } | ||||
| @@ -486,30 +486,34 @@ bool ForeachDirectoryEntry(unsigned* num_entries_out, const std::string &directo | ||||
|     closedir(dirp); | ||||
| #endif | ||||
|  | ||||
|     if (!callback_error) { | ||||
|     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) | ||||
|         *num_entries_out = found_entries; | ||||
|     return true; | ||||
|     } else { | ||||
|         return false; | ||||
|     } | ||||
| } | ||||
|  | ||||
| unsigned ScanDirectoryTree(const std::string &directory, FSTEntry& parent_entry) | ||||
| unsigned ScanDirectoryTree(const std::string &directory, FSTEntry& parent_entry, unsigned int recursion) | ||||
| { | ||||
|     const auto callback = [&parent_entry](unsigned* num_entries_out, | ||||
|                                           const std::string& directory, | ||||
|                                           const std::string& virtual_name) -> bool { | ||||
|                                           const std::string& virtual_name, | ||||
|                                           unsigned int recursion) -> bool { | ||||
|         FSTEntry entry; | ||||
|         entry.virtualName = virtual_name; | ||||
|         entry.physicalName = directory + DIR_SEP + virtual_name; | ||||
|  | ||||
|         if (IsDirectory(entry.physicalName)) { | ||||
|             entry.isDirectory = true; | ||||
|             // is a directory, lets go inside | ||||
|             entry.size = ScanDirectoryTree(entry.physicalName, entry); | ||||
|             // is a directory, lets go inside if we didn't recurse to often | ||||
|             if (recursion > 0) { | ||||
|                 entry.size = ScanDirectoryTree(entry.physicalName, entry, recursion - 1); | ||||
|                 *num_entries_out += (int)entry.size; | ||||
|             } else { | ||||
|                 entry.size = 0; | ||||
|             } | ||||
|         } else { // is a file | ||||
|             entry.isDirectory = false; | ||||
|             entry.size = GetSize(entry.physicalName); | ||||
| @@ -522,23 +526,27 @@ unsigned ScanDirectoryTree(const std::string &directory, FSTEntry& parent_entry) | ||||
|     }; | ||||
|  | ||||
|     unsigned num_entries; | ||||
|     return ForeachDirectoryEntry(&num_entries, directory, callback) ? num_entries : 0; | ||||
|     return ForeachDirectoryEntry(&num_entries, directory, callback, recursion) ? num_entries : 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| bool DeleteDirRecursively(const std::string &directory) | ||||
| bool DeleteDirRecursively(const std::string &directory, unsigned int recursion) | ||||
| { | ||||
|     const static auto callback = [](unsigned* num_entries_out, | ||||
|                                     const std::string& directory, | ||||
|                                     const std::string& virtual_name) -> bool { | ||||
|                                     const std::string& virtual_name, | ||||
|                                     unsigned int recursion) -> bool { | ||||
|         std::string new_path = directory + DIR_SEP_CHR + virtual_name; | ||||
|         if (IsDirectory(new_path)) | ||||
|             return DeleteDirRecursively(new_path); | ||||
|  | ||||
|         if (IsDirectory(new_path)) { | ||||
|             if (recursion == 0) | ||||
|                 return false; | ||||
|             return DeleteDirRecursively(new_path, recursion - 1); | ||||
|         } | ||||
|         return Delete(new_path); | ||||
|     }; | ||||
|  | ||||
|     if (!ForeachDirectoryEntry(nullptr, directory, callback)) | ||||
|     if (!ForeachDirectoryEntry(nullptr, directory, callback, recursion)) | ||||
|         return false; | ||||
|  | ||||
|     // Delete the outermost directory | ||||
|   | ||||
| @@ -105,11 +105,13 @@ bool CreateEmptyFile(const std::string &filename); | ||||
|  * @param num_entries_out to be assigned by the callable with the number of iterated directory entries, never null | ||||
|  * @param directory the path to the enclosing directory | ||||
|  * @param virtual_name the entry name, without any preceding directory info | ||||
|  * @param recursion Number of children directory to read before giving up | ||||
|  * @return whether handling the entry succeeded | ||||
|  */ | ||||
| using DirectoryEntryCallable = std::function<bool(unsigned* num_entries_out, | ||||
|                                                  const std::string& directory, | ||||
|                                                  const std::string& virtual_name)>; | ||||
|                                                  const std::string& virtual_name, | ||||
|                                                  unsigned int recursion)>; | ||||
|  | ||||
| /** | ||||
|  * Scans a directory, calling the callback for each file/directory contained within. | ||||
| @@ -117,20 +119,22 @@ using DirectoryEntryCallable = std::function<bool(unsigned* num_entries_out, | ||||
|  * @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 recursion Number of children directories to read before giving up | ||||
|  * @return whether scanning the directory succeeded | ||||
|  */ | ||||
| bool ForeachDirectoryEntry(unsigned* num_entries_out, const std::string &directory, DirectoryEntryCallable callback); | ||||
| bool ForeachDirectoryEntry(unsigned* num_entries_out, const std::string &directory, DirectoryEntryCallable callback, unsigned int recursion = 0); | ||||
|  | ||||
| /** | ||||
|  * Scans the directory tree, storing the results. | ||||
|  * @param directory the parent directory to start scanning from | ||||
|  * @param parent_entry FSTEntry where the filesystem tree results will be stored. | ||||
|  * @param recursion Number of children directories to read before giving up. | ||||
|  * @return the total number of files/directories found | ||||
|  */ | ||||
| unsigned ScanDirectoryTree(const std::string &directory, FSTEntry& parent_entry); | ||||
| unsigned ScanDirectoryTree(const std::string &directory, FSTEntry& parent_entry, unsigned int recursion = 0); | ||||
|  | ||||
| // deletes the given directory and anything under it. Returns true on success. | ||||
| bool DeleteDirRecursively(const std::string &directory); | ||||
| bool DeleteDirRecursively(const std::string &directory, unsigned int recursion = 256); | ||||
|  | ||||
| // Returns the current directory | ||||
| std::string GetCurrentDir(); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 bunnei
					bunnei