summaryrefslogtreecommitdiff
path: root/src/common/file_util.cpp
diff options
context:
space:
mode:
authorGravatar Emmanuel Gil Peyrot2015-09-06 07:59:04 +0100
committerGravatar Emmanuel Gil Peyrot2016-05-21 16:41:02 +0100
commit8ab6f26c09e5b77a051fa545570ca2986c45bf4a (patch)
treea0664d2b9bb548cbd7f78ed60b846a88c09f90f4 /src/common/file_util.cpp
parentAppveyor: Restore working directory after test_script (#1835) (diff)
downloadyuzu-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.cpp48
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
437bool ForeachDirectoryEntry(unsigned* num_entries_out, const std::string &directory, DirectoryEntryCallable callback) 437bool 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
499unsigned ScanDirectoryTree(const std::string &directory, FSTEntry& parent_entry) 498unsigned 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
529bool DeleteDirRecursively(const std::string &directory) 533bool 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