From d51e4e52364d7215a229e961e4f4457d1dfde3ca Mon Sep 17 00:00:00 2001 From: Shawn Hoffman Date: Fri, 19 Aug 2022 19:50:36 -0700 Subject: get rid of HAS_STD_FILESYSTEM just use std::filesystem --- Source/Core/Common/FileSearch.cpp | 127 ++++++++++++-------------------------- 1 file changed, 39 insertions(+), 88 deletions(-) (limited to 'Source/Core/Common/FileSearch.cpp') diff --git a/Source/Core/Common/FileSearch.cpp b/Source/Core/Common/FileSearch.cpp index 0da6c4fc13..d022414efc 100644 --- a/Source/Core/Common/FileSearch.cpp +++ b/Source/Core/Common/FileSearch.cpp @@ -4,17 +4,17 @@ #include "Common/FileSearch.h" #include +#include #include #include +#include #include "Common/CommonPaths.h" +#include "Common/Logging/Log.h" #include "Common/StringUtil.h" #ifdef _MSC_VER #include -#include -namespace fs = std::filesystem; -#define HAS_STD_FILESYSTEM #else #ifdef ANDROID #include "jni/AndroidCommon/AndroidCommon.h" @@ -25,79 +25,14 @@ namespace fs = std::filesystem; #include "Common/FileUtil.h" #endif -namespace Common -{ -#ifndef HAS_STD_FILESYSTEM - -static void FileSearchWithTest(const std::string& directory, bool recursive, - std::vector* result_out, - std::function callback) -{ - File::FSTEntry top = File::ScanDirectoryTree(directory, recursive); - - const std::function DoEntry = [&](File::FSTEntry& entry) { - if (callback(entry)) - result_out->push_back(entry.physicalName); - for (auto& child : entry.children) - DoEntry(child); - }; - - for (auto& child : top.children) - DoEntry(child); -} +namespace fs = std::filesystem; -std::vector DoFileSearch(const std::vector& directories, - const std::vector& exts, bool recursive) +namespace Common { - std::vector result; - - bool accept_all = exts.empty(); - const auto callback = [&exts, accept_all](const File::FSTEntry& entry) { - if (accept_all) - return true; - if (entry.isDirectory) - return false; - return std::any_of(exts.begin(), exts.end(), [&](const std::string& ext) { - const std::string& name = entry.virtualName; - return name.length() >= ext.length() && - strcasecmp(name.c_str() + name.length() - ext.length(), ext.c_str()) == 0; - }); - }; - - for (const std::string& directory : directories) - { -#ifdef ANDROID - // While File::ScanDirectoryTree (which is called in FileSearchWithTest) does handle Android - // content correctly, having a specialized implementation of DoFileSearch for Android content - // provides a much needed performance boost. Also, this specialized implementation will be - // required if we in the future replace the use of File::ScanDirectoryTree with std::filesystem. - if (IsPathAndroidContent(directory)) - { - const std::vector partial_result = - DoFileSearchAndroidContent(directory, exts, recursive); - - result.insert(result.end(), std::make_move_iterator(partial_result.begin()), - std::make_move_iterator(partial_result.end())); - } - else -#endif - { - FileSearchWithTest(directory, recursive, &result, callback); - } - } - - // remove duplicates - std::sort(result.begin(), result.end()); - result.erase(std::unique(result.begin(), result.end()), result.end()); - return result; -} - -#else - std::vector DoFileSearch(const std::vector& directories, const std::vector& exts, bool recursive) { - bool accept_all = exts.empty(); + const bool accept_all = exts.empty(); std::vector native_exts; for (const auto& ext : exts) @@ -105,39 +40,57 @@ std::vector DoFileSearch(const std::vector& directorie // N.B. This avoids doing any copies auto ext_matches = [&native_exts](const fs::path& path) { - const auto& native_path = path.native(); + const std::basic_string_view native_path = path.native(); return std::any_of(native_exts.cbegin(), native_exts.cend(), [&native_path](const auto& ext) { - // TODO provide cross-platform compat for the comparison function, once more platforms - // support std::filesystem - int compare_len = static_cast(ext.native().length()); - return native_path.length() >= compare_len && - CompareStringOrdinal(&native_path.c_str()[native_path.length() - compare_len], - compare_len, ext.c_str(), compare_len, TRUE) == CSTR_EQUAL; + const auto compare_len = ext.native().length(); + if (native_path.length() < compare_len) + return false; + const auto substr_to_compare = native_path.substr(native_path.length() - compare_len); +#ifdef _WIN32 + return CompareStringOrdinal(substr_to_compare.data(), static_cast(compare_len), + ext.c_str(), static_cast(compare_len), TRUE) == CSTR_EQUAL; +#else + return strncasecmp(substr_to_compare.data(), ext.c_str(), compare_len) == 0; +#endif }); }; std::vector result; auto add_filtered = [&](const fs::directory_entry& entry) { auto& path = entry.path(); - if (accept_all || (ext_matches(path) && !fs::is_directory(path))) + if (accept_all || (!entry.is_directory() && ext_matches(path))) result.emplace_back(PathToString(path)); }; for (const auto& directory : directories) { - fs::path directory_path = StringToPath(directory); - if (fs::is_directory(directory_path)) // Can't create iterators for non-existant directories +#ifdef ANDROID + if (IsPathAndroidContent(directory)) + { + const std::vector partial_result = + DoFileSearchAndroidContent(directory, exts, recursive); + + result.insert(result.end(), std::make_move_iterator(partial_result.begin()), + std::make_move_iterator(partial_result.end())); + } + else +#endif { + fs::path directory_path = StringToPath(directory); + std::error_code error; if (recursive) { - // TODO use fs::directory_options::follow_directory_symlink ? - for (auto& entry : fs::recursive_directory_iterator(std::move(directory_path))) - add_filtered(entry); + for (auto it = fs::recursive_directory_iterator(std::move(directory_path), error); + it != fs::recursive_directory_iterator(); it.increment(error)) + add_filtered(*it); } else { - for (auto& entry : fs::directory_iterator(std::move(directory_path))) - add_filtered(entry); + for (auto it = fs::directory_iterator(std::move(directory_path), error); + it != fs::directory_iterator(); it.increment(error)) + add_filtered(*it); } + if (error) + ERROR_LOG_FMT(COMMON, "{} error on {}: {}", __func__, directory, error.message()); } } @@ -160,6 +113,4 @@ std::vector DoFileSearch(const std::vector& directorie return result; } -#endif - } // namespace Common -- cgit v1.2.3