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/file_util.cpp | |
| 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/file_util.cpp')
| -rw-r--r-- | src/common/file_util.cpp | 48 |
1 files changed, 28 insertions, 20 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 |