diff options
| author | 2015-09-06 07:59:04 +0100 | |
|---|---|---|
| committer | 2016-05-21 16:41:02 +0100 | |
| commit | 8ab6f26c09e5b77a051fa545570ca2986c45bf4a (patch) | |
| tree | a0664d2b9bb548cbd7f78ed60b846a88c09f90f4 /src/common | |
| 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!
Diffstat (limited to 'src/common')
| -rw-r--r-- | src/common/file_util.cpp | 48 | ||||
| -rw-r--r-- | src/common/file_util.h | 12 |
2 files changed, 36 insertions, 24 deletions
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(); |