diff options
| author | 2015-09-06 07:59:04 +0100 | |
|---|---|---|
| committer | 2016-05-21 16:41:02 +0100 | |
| commit | 8ab6f26c09e5b77a051fa545570ca2986c45bf4a (patch) | |
| tree | a0664d2b9bb548cbd7f78ed60b846a88c09f90f4 | |
| parent | Appveyor: Restore working directory after test_script (#1835) (diff) | |
| download | yuzu-8ab6f26c09e5b77a051fa545570ca2986c45bf4a.tar.gz yuzu-8ab6f26c09e5b77a051fa545570ca2986c45bf4a.tar.xz yuzu-8ab6f26c09e5b77a051fa545570ca2986c45bf4a.zip | |
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!
| -rw-r--r-- | src/citra_qt/game_list.cpp | 11 | ||||
| -rw-r--r-- | src/citra_qt/game_list_p.h | 2 | ||||
| -rw-r--r-- | src/common/file_util.cpp | 48 | ||||
| -rw-r--r-- | src/common/file_util.h | 12 |
4 files changed, 43 insertions, 30 deletions
diff --git a/src/citra_qt/game_list.cpp b/src/citra_qt/game_list.cpp index d4ac9c96e..adbcf24e8 100644 --- a/src/citra_qt/game_list.cpp +++ b/src/citra_qt/game_list.cpp | |||
| @@ -118,19 +118,20 @@ void GameList::LoadInterfaceLayout() | |||
| 118 | item_model->sort(header->sortIndicatorSection(), header->sortIndicatorOrder()); | 118 | item_model->sort(header->sortIndicatorSection(), header->sortIndicatorOrder()); |
| 119 | } | 119 | } |
| 120 | 120 | ||
| 121 | void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, bool deep_scan) | 121 | void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsigned int recursion) |
| 122 | { | 122 | { |
| 123 | const auto callback = [&](unsigned* num_entries_out, | 123 | const auto callback = [&](unsigned* num_entries_out, |
| 124 | const std::string& directory, | 124 | const std::string& directory, |
| 125 | const std::string& virtual_name) -> bool { | 125 | const std::string& virtual_name, |
| 126 | unsigned int recursion) -> bool { | ||
| 126 | 127 | ||
| 127 | std::string physical_name = directory + DIR_SEP + virtual_name; | 128 | std::string physical_name = directory + DIR_SEP + virtual_name; |
| 128 | 129 | ||
| 129 | if (stop_processing) | 130 | if (stop_processing) |
| 130 | return false; // Breaks the callback loop. | 131 | return false; // Breaks the callback loop. |
| 131 | 132 | ||
| 132 | if (deep_scan && FileUtil::IsDirectory(physical_name)) { | 133 | if (recursion > 0 && FileUtil::IsDirectory(physical_name)) { |
| 133 | AddFstEntriesToGameList(physical_name, true); | 134 | AddFstEntriesToGameList(physical_name, recursion - 1); |
| 134 | } else { | 135 | } else { |
| 135 | std::string filename_filename, filename_extension; | 136 | std::string filename_filename, filename_extension; |
| 136 | Common::SplitPath(physical_name, nullptr, &filename_filename, &filename_extension); | 137 | Common::SplitPath(physical_name, nullptr, &filename_filename, &filename_extension); |
| @@ -169,7 +170,7 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, bool d | |||
| 169 | void GameListWorker::run() | 170 | void GameListWorker::run() |
| 170 | { | 171 | { |
| 171 | stop_processing = false; | 172 | stop_processing = false; |
| 172 | AddFstEntriesToGameList(dir_path.toStdString(), deep_scan); | 173 | AddFstEntriesToGameList(dir_path.toStdString(), deep_scan ? 256 : 0); |
| 173 | emit Finished(); | 174 | emit Finished(); |
| 174 | } | 175 | } |
| 175 | 176 | ||
diff --git a/src/citra_qt/game_list_p.h b/src/citra_qt/game_list_p.h index 284f5da81..2d6b8aae0 100644 --- a/src/citra_qt/game_list_p.h +++ b/src/citra_qt/game_list_p.h | |||
| @@ -212,5 +212,5 @@ private: | |||
| 212 | bool deep_scan; | 212 | bool deep_scan; |
| 213 | std::atomic_bool stop_processing; | 213 | std::atomic_bool stop_processing; |
| 214 | 214 | ||
| 215 | void AddFstEntriesToGameList(const std::string& dir_path, bool deep_scan); | 215 | void AddFstEntriesToGameList(const std::string& dir_path, unsigned int recursion = 0); |
| 216 | }; | 216 | }; |
diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp index 6e2867658..17af7c385 100644 --- a/src/common/file_util.cpp +++ b/src/common/file_util.cpp | |||
| @@ -434,7 +434,7 @@ bool CreateEmptyFile(const std::string &filename) | |||
| 434 | } | 434 | } |
| 435 | 435 | ||
| 436 | 436 | ||
| 437 | bool ForeachDirectoryEntry(unsigned* num_entries_out, const std::string &directory, DirectoryEntryCallable callback) | 437 | bool ForeachDirectoryEntry(unsigned* num_entries_out, const std::string &directory, DirectoryEntryCallable callback, unsigned int recursion) |
| 438 | { | 438 | { |
| 439 | LOG_TRACE(Common_Filesystem, "directory %s", directory.c_str()); | 439 | LOG_TRACE(Common_Filesystem, "directory %s", directory.c_str()); |
| 440 | 440 | ||
| @@ -472,7 +472,7 @@ bool ForeachDirectoryEntry(unsigned* num_entries_out, const std::string &directo | |||
| 472 | continue; | 472 | continue; |
| 473 | 473 | ||
| 474 | unsigned ret_entries = 0; | 474 | unsigned ret_entries = 0; |
| 475 | if (!callback(&ret_entries, directory, virtual_name)) { | 475 | if (!callback(&ret_entries, directory, virtual_name, recursion)) { |
| 476 | callback_error = true; | 476 | callback_error = true; |
| 477 | break; | 477 | break; |
| 478 | } | 478 | } |
| @@ -486,30 +486,34 @@ bool ForeachDirectoryEntry(unsigned* num_entries_out, const std::string &directo | |||
| 486 | closedir(dirp); | 486 | closedir(dirp); |
| 487 | #endif | 487 | #endif |
| 488 | 488 | ||
| 489 | if (!callback_error) { | 489 | if (callback_error) |
| 490 | // num_entries_out is allowed to be specified nullptr, in which case we shouldn't try to set it | ||
| 491 | if (num_entries_out != nullptr) | ||
| 492 | *num_entries_out = found_entries; | ||
| 493 | return true; | ||
| 494 | } else { | ||
| 495 | return false; | 490 | return false; |
| 496 | } | 491 | |
| 492 | // num_entries_out is allowed to be specified nullptr, in which case we shouldn't try to set it | ||
| 493 | if (num_entries_out != nullptr) | ||
| 494 | *num_entries_out = found_entries; | ||
| 495 | return true; | ||
| 497 | } | 496 | } |
| 498 | 497 | ||
| 499 | unsigned ScanDirectoryTree(const std::string &directory, FSTEntry& parent_entry) | 498 | unsigned ScanDirectoryTree(const std::string &directory, FSTEntry& parent_entry, unsigned int recursion) |
| 500 | { | 499 | { |
| 501 | const auto callback = [&parent_entry](unsigned* num_entries_out, | 500 | const auto callback = [&parent_entry](unsigned* num_entries_out, |
| 502 | const std::string& directory, | 501 | const std::string& directory, |
| 503 | const std::string& virtual_name) -> bool { | 502 | const std::string& virtual_name, |
| 503 | unsigned int recursion) -> bool { | ||
| 504 | FSTEntry entry; | 504 | FSTEntry entry; |
| 505 | entry.virtualName = virtual_name; | 505 | entry.virtualName = virtual_name; |
| 506 | entry.physicalName = directory + DIR_SEP + virtual_name; | 506 | entry.physicalName = directory + DIR_SEP + virtual_name; |
| 507 | 507 | ||
| 508 | if (IsDirectory(entry.physicalName)) { | 508 | if (IsDirectory(entry.physicalName)) { |
| 509 | entry.isDirectory = true; | 509 | entry.isDirectory = true; |
| 510 | // is a directory, lets go inside | 510 | // is a directory, lets go inside if we didn't recurse to often |
| 511 | entry.size = ScanDirectoryTree(entry.physicalName, entry); | 511 | if (recursion > 0) { |
| 512 | *num_entries_out += (int)entry.size; | 512 | entry.size = ScanDirectoryTree(entry.physicalName, entry, recursion - 1); |
| 513 | *num_entries_out += (int)entry.size; | ||
| 514 | } else { | ||
| 515 | entry.size = 0; | ||
| 516 | } | ||
| 513 | } else { // is a file | 517 | } else { // is a file |
| 514 | entry.isDirectory = false; | 518 | entry.isDirectory = false; |
| 515 | entry.size = GetSize(entry.physicalName); | 519 | entry.size = GetSize(entry.physicalName); |
| @@ -522,23 +526,27 @@ unsigned ScanDirectoryTree(const std::string &directory, FSTEntry& parent_entry) | |||
| 522 | }; | 526 | }; |
| 523 | 527 | ||
| 524 | unsigned num_entries; | 528 | unsigned num_entries; |
| 525 | return ForeachDirectoryEntry(&num_entries, directory, callback) ? num_entries : 0; | 529 | return ForeachDirectoryEntry(&num_entries, directory, callback, recursion) ? num_entries : 0; |
| 526 | } | 530 | } |
| 527 | 531 | ||
| 528 | 532 | ||
| 529 | bool DeleteDirRecursively(const std::string &directory) | 533 | bool DeleteDirRecursively(const std::string &directory, unsigned int recursion) |
| 530 | { | 534 | { |
| 531 | const static auto callback = [](unsigned* num_entries_out, | 535 | const static auto callback = [](unsigned* num_entries_out, |
| 532 | const std::string& directory, | 536 | const std::string& directory, |
| 533 | const std::string& virtual_name) -> bool { | 537 | const std::string& virtual_name, |
| 538 | unsigned int recursion) -> bool { | ||
| 534 | std::string new_path = directory + DIR_SEP_CHR + virtual_name; | 539 | std::string new_path = directory + DIR_SEP_CHR + virtual_name; |
| 535 | if (IsDirectory(new_path)) | ||
| 536 | return DeleteDirRecursively(new_path); | ||
| 537 | 540 | ||
| 541 | if (IsDirectory(new_path)) { | ||
| 542 | if (recursion == 0) | ||
| 543 | return false; | ||
| 544 | return DeleteDirRecursively(new_path, recursion - 1); | ||
| 545 | } | ||
| 538 | return Delete(new_path); | 546 | return Delete(new_path); |
| 539 | }; | 547 | }; |
| 540 | 548 | ||
| 541 | if (!ForeachDirectoryEntry(nullptr, directory, callback)) | 549 | if (!ForeachDirectoryEntry(nullptr, directory, callback, recursion)) |
| 542 | return false; | 550 | return false; |
| 543 | 551 | ||
| 544 | // Delete the outermost directory | 552 | // Delete the outermost directory |
diff --git a/src/common/file_util.h b/src/common/file_util.h index c6a8694ce..32ae2dc57 100644 --- a/src/common/file_util.h +++ b/src/common/file_util.h | |||
| @@ -105,11 +105,13 @@ bool CreateEmptyFile(const std::string &filename); | |||
| 105 | * @param num_entries_out to be assigned by the callable with the number of iterated directory entries, never null | 105 | * @param num_entries_out to be assigned by the callable with the number of iterated directory entries, never null |
| 106 | * @param directory the path to the enclosing directory | 106 | * @param directory the path to the enclosing directory |
| 107 | * @param virtual_name the entry name, without any preceding directory info | 107 | * @param virtual_name the entry name, without any preceding directory info |
| 108 | * @param recursion Number of children directory to read before giving up | ||
| 108 | * @return whether handling the entry succeeded | 109 | * @return whether handling the entry succeeded |
| 109 | */ | 110 | */ |
| 110 | using DirectoryEntryCallable = std::function<bool(unsigned* num_entries_out, | 111 | using DirectoryEntryCallable = std::function<bool(unsigned* num_entries_out, |
| 111 | const std::string& directory, | 112 | const std::string& directory, |
| 112 | const std::string& virtual_name)>; | 113 | const std::string& virtual_name, |
| 114 | unsigned int recursion)>; | ||
| 113 | 115 | ||
| 114 | /** | 116 | /** |
| 115 | * Scans a directory, calling the callback for each file/directory contained within. | 117 | * 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, | |||
| 117 | * @param num_entries_out assigned by the function with the number of iterated directory entries, can be null | 119 | * @param num_entries_out assigned by the function with the number of iterated directory entries, can be null |
| 118 | * @param directory the directory to scan | 120 | * @param directory the directory to scan |
| 119 | * @param callback The callback which will be called for each entry | 121 | * @param callback The callback which will be called for each entry |
| 122 | * @param recursion Number of children directories to read before giving up | ||
| 120 | * @return whether scanning the directory succeeded | 123 | * @return whether scanning the directory succeeded |
| 121 | */ | 124 | */ |
| 122 | bool ForeachDirectoryEntry(unsigned* num_entries_out, const std::string &directory, DirectoryEntryCallable callback); | 125 | bool ForeachDirectoryEntry(unsigned* num_entries_out, const std::string &directory, DirectoryEntryCallable callback, unsigned int recursion = 0); |
| 123 | 126 | ||
| 124 | /** | 127 | /** |
| 125 | * Scans the directory tree, storing the results. | 128 | * Scans the directory tree, storing the results. |
| 126 | * @param directory the parent directory to start scanning from | 129 | * @param directory the parent directory to start scanning from |
| 127 | * @param parent_entry FSTEntry where the filesystem tree results will be stored. | 130 | * @param parent_entry FSTEntry where the filesystem tree results will be stored. |
| 131 | * @param recursion Number of children directories to read before giving up. | ||
| 128 | * @return the total number of files/directories found | 132 | * @return the total number of files/directories found |
| 129 | */ | 133 | */ |
| 130 | unsigned ScanDirectoryTree(const std::string &directory, FSTEntry& parent_entry); | 134 | unsigned ScanDirectoryTree(const std::string &directory, FSTEntry& parent_entry, unsigned int recursion = 0); |
| 131 | 135 | ||
| 132 | // deletes the given directory and anything under it. Returns true on success. | 136 | // deletes the given directory and anything under it. Returns true on success. |
| 133 | bool DeleteDirRecursively(const std::string &directory); | 137 | bool DeleteDirRecursively(const std::string &directory, unsigned int recursion = 256); |
| 134 | 138 | ||
| 135 | // Returns the current directory | 139 | // Returns the current directory |
| 136 | std::string GetCurrentDir(); | 140 | std::string GetCurrentDir(); |