summaryrefslogtreecommitdiff
path: root/Source/Core/Common/FileSearch.cpp
diff options
context:
space:
mode:
authorPierre Bourdon <delroth@gmail.com>2023-01-24 12:18:25 +0100
committerGitHub <noreply@github.com>2023-01-24 12:18:25 +0100
commitcaca662dbff0a2fdebe6231288f9288e54419819 (patch)
tree7b914a5a76e0db3558976f8abde43db91c92d59d /Source/Core/Common/FileSearch.cpp
parentd4d6f3db63f974885c7a96a1bf6dfc65a1640122 (diff)
parentd51e4e52364d7215a229e961e4f4457d1dfde3ca (diff)
Merge pull request #10994 from shuffle2/fs
get rid of HAS_STD_FILESYSTEM
Diffstat (limited to 'Source/Core/Common/FileSearch.cpp')
-rw-r--r--Source/Core/Common/FileSearch.cpp127
1 files changed, 39 insertions, 88 deletions
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 <algorithm>
+#include <filesystem>
#include <functional>
#include <iterator>
+#include <system_error>
#include "Common/CommonPaths.h"
+#include "Common/Logging/Log.h"
#include "Common/StringUtil.h"
#ifdef _MSC_VER
#include <Windows.h>
-#include <filesystem>
-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<std::string>* result_out,
- std::function<bool(const File::FSTEntry&)> callback)
-{
- File::FSTEntry top = File::ScanDirectoryTree(directory, recursive);
-
- const std::function<void(File::FSTEntry&)> 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<std::string> DoFileSearch(const std::vector<std::string>& directories,
- const std::vector<std::string>& exts, bool recursive)
+namespace Common
{
- std::vector<std::string> 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<std::string> 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<std::string> DoFileSearch(const std::vector<std::string>& directories,
const std::vector<std::string>& exts, bool recursive)
{
- bool accept_all = exts.empty();
+ const bool accept_all = exts.empty();
std::vector<fs::path> native_exts;
for (const auto& ext : exts)
@@ -105,39 +40,57 @@ std::vector<std::string> DoFileSearch(const std::vector<std::string>& 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<fs::path::value_type> 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<int>(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<int>(compare_len),
+ ext.c_str(), static_cast<int>(compare_len), TRUE) == CSTR_EQUAL;
+#else
+ return strncasecmp(substr_to_compare.data(), ext.c_str(), compare_len) == 0;
+#endif
});
};
std::vector<std::string> 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<std::string> 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<std::string> DoFileSearch(const std::vector<std::string>& directorie
return result;
}
-#endif
-
} // namespace Common