mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	Common: Make recursive FileUtil functions take a maximum recursion
Fixes #1115. Also improves the performances of DiskArchive’s directory implementation a lot, simply by not going through the entire tree instead of just listing the first level files. Thanks to JayRoxFox for rebasing this on current master!
This commit is contained in:
		
							parent
							
								
									51ee2d2eb1
								
							
						
					
					
						commit
						8ab6f26c09
					
				
					 4 changed files with 43 additions and 30 deletions
				
			
		|  | @ -118,19 +118,20 @@ void GameList::LoadInterfaceLayout() | ||||||
|     item_model->sort(header->sortIndicatorSection(), header->sortIndicatorOrder()); |     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 auto callback = [&](unsigned* num_entries_out, | ||||||
|                               const std::string& directory, |                               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; |         std::string physical_name = directory + DIR_SEP + virtual_name; | ||||||
| 
 | 
 | ||||||
|         if (stop_processing) |         if (stop_processing) | ||||||
|             return false; // Breaks the callback loop.
 |             return false; // Breaks the callback loop.
 | ||||||
| 
 | 
 | ||||||
|         if (deep_scan && FileUtil::IsDirectory(physical_name)) { |         if (recursion > 0 && FileUtil::IsDirectory(physical_name)) { | ||||||
|             AddFstEntriesToGameList(physical_name, true); |             AddFstEntriesToGameList(physical_name, recursion - 1); | ||||||
|         } else { |         } else { | ||||||
|             std::string filename_filename, filename_extension; |             std::string filename_filename, filename_extension; | ||||||
|             Common::SplitPath(physical_name, nullptr, &filename_filename, &filename_extension); |             Common::SplitPath(physical_name, nullptr, &filename_filename, &filename_extension); | ||||||
|  | @ -169,7 +170,7 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, bool d | ||||||
| void GameListWorker::run() | void GameListWorker::run() | ||||||
| { | { | ||||||
|     stop_processing = false; |     stop_processing = false; | ||||||
|     AddFstEntriesToGameList(dir_path.toStdString(), deep_scan); |     AddFstEntriesToGameList(dir_path.toStdString(), deep_scan ? 256 : 0); | ||||||
|     emit Finished(); |     emit Finished(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -212,5 +212,5 @@ private: | ||||||
|     bool deep_scan; |     bool deep_scan; | ||||||
|     std::atomic_bool stop_processing; |     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()); |     LOG_TRACE(Common_Filesystem, "directory %s", directory.c_str()); | ||||||
| 
 | 
 | ||||||
|  | @ -472,7 +472,7 @@ bool ForeachDirectoryEntry(unsigned* num_entries_out, const std::string &directo | ||||||
|             continue; |             continue; | ||||||
| 
 | 
 | ||||||
|         unsigned ret_entries = 0; |         unsigned ret_entries = 0; | ||||||
|         if (!callback(&ret_entries, directory, virtual_name)) { |         if (!callback(&ret_entries, directory, virtual_name, recursion)) { | ||||||
|             callback_error = true; |             callback_error = true; | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|  | @ -486,30 +486,34 @@ bool ForeachDirectoryEntry(unsigned* num_entries_out, const std::string &directo | ||||||
|     closedir(dirp); |     closedir(dirp); | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|     if (!callback_error) { |     if (callback_error) | ||||||
|         // 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; |         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; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 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 auto callback = [&parent_entry](unsigned* num_entries_out, | ||||||
|                                           const std::string& directory, |                                           const std::string& directory, | ||||||
|                                           const std::string& virtual_name) -> bool { |                                           const std::string& virtual_name, | ||||||
|  |                                           unsigned int recursion) -> bool { | ||||||
|         FSTEntry entry; |         FSTEntry entry; | ||||||
|         entry.virtualName = virtual_name; |         entry.virtualName = virtual_name; | ||||||
|         entry.physicalName = directory + DIR_SEP + virtual_name; |         entry.physicalName = directory + DIR_SEP + virtual_name; | ||||||
| 
 | 
 | ||||||
|         if (IsDirectory(entry.physicalName)) { |         if (IsDirectory(entry.physicalName)) { | ||||||
|             entry.isDirectory = true; |             entry.isDirectory = true; | ||||||
|             // is a directory, lets go inside
 |             // is a directory, lets go inside if we didn't recurse to often
 | ||||||
|             entry.size = ScanDirectoryTree(entry.physicalName, entry); |             if (recursion > 0) { | ||||||
|             *num_entries_out += (int)entry.size; |                 entry.size = ScanDirectoryTree(entry.physicalName, entry, recursion - 1); | ||||||
|  |                 *num_entries_out += (int)entry.size; | ||||||
|  |             } else { | ||||||
|  |                 entry.size = 0; | ||||||
|  |             } | ||||||
|         } else { // is a file
 |         } else { // is a file
 | ||||||
|             entry.isDirectory = false; |             entry.isDirectory = false; | ||||||
|             entry.size = GetSize(entry.physicalName); |             entry.size = GetSize(entry.physicalName); | ||||||
|  | @ -522,23 +526,27 @@ unsigned ScanDirectoryTree(const std::string &directory, FSTEntry& parent_entry) | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     unsigned num_entries; |     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 static auto callback = [](unsigned* num_entries_out, | ||||||
|                                     const std::string& directory, |                                     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; |         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); |         return Delete(new_path); | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     if (!ForeachDirectoryEntry(nullptr, directory, callback)) |     if (!ForeachDirectoryEntry(nullptr, directory, callback, recursion)) | ||||||
|         return false; |         return false; | ||||||
| 
 | 
 | ||||||
|     // Delete the outermost directory
 |     // 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 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 directory the path to the enclosing directory | ||||||
|  * @param virtual_name the entry name, without any preceding directory info |  * @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 |  * @return whether handling the entry succeeded | ||||||
|  */ |  */ | ||||||
| using DirectoryEntryCallable = std::function<bool(unsigned* num_entries_out, | using DirectoryEntryCallable = std::function<bool(unsigned* num_entries_out, | ||||||
|                                                  const std::string& directory, |                                                  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. |  * 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 num_entries_out assigned by the function with the number of iterated directory entries, can be null | ||||||
|  * @param directory the directory to scan |  * @param directory the directory to scan | ||||||
|  * @param callback The callback which will be called for each entry |  * @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 |  * @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. |  * Scans the directory tree, storing the results. | ||||||
|  * @param directory the parent directory to start scanning from |  * @param directory the parent directory to start scanning from | ||||||
|  * @param parent_entry FSTEntry where the filesystem tree results will be stored. |  * @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 |  * @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.
 | // 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
 | // Returns the current directory
 | ||||||
| std::string GetCurrentDir(); | std::string GetCurrentDir(); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue