Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1032)

Unified Diff: base/files/file_enumerator_win.cc

Issue 2892173003: Add recursive pattern matching for subfolders in file_enumerator. (Closed)
Patch Set: Add recursive pattern matching for subfolders in file_enumerator Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « base/files/file_enumerator_unittest.cc ('k') | chrome_elf/BUILD.gn » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/files/file_enumerator_win.cc
diff --git a/base/files/file_enumerator_win.cc b/base/files/file_enumerator_win.cc
index e629cc203e5e8892ca52fbf7d0b55987aa6324fa..826e293bed810a86ab14706edbba8b33dfd9997f 100644
--- a/base/files/file_enumerator_win.cc
+++ b/base/files/file_enumerator_win.cc
@@ -4,6 +4,7 @@
#include "base/files/file_enumerator.h"
+#include <shlwapi.h>
#include <stdint.h>
#include <string.h>
@@ -12,6 +13,25 @@
namespace base {
+namespace {
+
+FilePath BuildSearchFilter(FileEnumerator::FolderSearchPolicy policy,
+ const FilePath& root_path,
+ const FilePath::StringType& pattern) {
+ // MATCH_ONLY policy filters incoming files by pattern on OS side. ALL policy
+ // collects all files and filters them manually.
+ switch (policy) {
+ case FileEnumerator::FolderSearchPolicy::MATCH_ONLY:
+ return root_path.Append(pattern);
+ case FileEnumerator::FolderSearchPolicy::ALL:
+ return root_path.Append(L"*");
+ }
+ NOTREACHED();
+ return {};
+}
+
+} // namespace
+
// FileEnumerator::FileInfo ----------------------------------------------------
FileEnumerator::FileInfo::FileInfo() {
@@ -44,25 +64,31 @@ base::Time FileEnumerator::FileInfo::GetLastModifiedTime() const {
FileEnumerator::FileEnumerator(const FilePath& root_path,
bool recursive,
int file_type)
- : has_find_data_(false),
- find_handle_(INVALID_HANDLE_VALUE),
- recursive_(recursive),
- file_type_(file_type) {
- // INCLUDE_DOT_DOT must not be specified if recursive.
- DCHECK(!(recursive && (INCLUDE_DOT_DOT & file_type_)));
- memset(&find_data_, 0, sizeof(find_data_));
- pending_paths_.push(root_path);
-}
+ : FileEnumerator(root_path,
+ recursive,
+ file_type,
+ FilePath::StringType(),
+ FolderSearchPolicy::MATCH_ONLY) {}
FileEnumerator::FileEnumerator(const FilePath& root_path,
bool recursive,
int file_type,
const FilePath::StringType& pattern)
- : has_find_data_(false),
- find_handle_(INVALID_HANDLE_VALUE),
- recursive_(recursive),
+ : FileEnumerator(root_path,
+ recursive,
+ file_type,
+ pattern,
+ FolderSearchPolicy::MATCH_ONLY) {}
+
+FileEnumerator::FileEnumerator(const FilePath& root_path,
+ bool recursive,
+ int file_type,
+ const FilePath::StringType& pattern,
+ FolderSearchPolicy folder_search_policy)
+ : recursive_(recursive),
file_type_(file_type),
- pattern_(pattern) {
+ pattern_(!pattern.empty() ? pattern : L"*"),
+ folder_search_policy_(folder_search_policy) {
// INCLUDE_DOT_DOT must not be specified if recursive.
DCHECK(!(recursive && (INCLUDE_DOT_DOT & file_type_)));
memset(&find_data_, 0, sizeof(find_data_));
@@ -94,21 +120,12 @@ FilePath FileEnumerator::Next() {
pending_paths_.pop();
// Start a new find operation.
- FilePath src = root_path_;
-
- if (pattern_.empty())
- src = src.Append(L"*"); // No pattern = match everything.
- else
- src = src.Append(pattern_);
-
- // Use a "large fetch" which should speed up large enumerations (we seldom
- // abort in the middle).
+ const FilePath src =
+ BuildSearchFilter(folder_search_policy_, root_path_, pattern_);
find_handle_ = FindFirstFileEx(src.value().c_str(),
FindExInfoBasic, // Omit short name.
- &find_data_,
- FindExSearchNameMatch,
- NULL,
- FIND_FIRST_EX_LARGE_FETCH);
+ &find_data_, FindExSearchNameMatch,
+ nullptr, FIND_FIRST_EX_LARGE_FETCH);
has_find_data_ = true;
} else {
// Search for the next file/directory.
@@ -121,41 +138,58 @@ FilePath FileEnumerator::Next() {
if (INVALID_HANDLE_VALUE == find_handle_) {
has_find_data_ = false;
- // This is reached when we have finished a directory and are advancing to
- // the next one in the queue. We applied the pattern (if any) to the files
- // in the root search directory, but for those directories which were
- // matched, we want to enumerate all files inside them. This will happen
- // when the handle is empty.
- pattern_ = FilePath::StringType();
+ // MATCH_ONLY policy clears pattern for matched subfolders. ALL policy
+ // applies pattern for all subfolders.
+ if (folder_search_policy_ == FolderSearchPolicy::MATCH_ONLY) {
+ // This is reached when we have finished a directory and are advancing
+ // to the next one in the queue. We applied the pattern (if any) to the
+ // files in the root search directory, but for those directories which
+ // were matched, we want to enumerate all files inside them. This will
+ // happen when the handle is empty.
+ pattern_ = L"*";
+ }
continue;
}
- FilePath cur_file(find_data_.cFileName);
- if (ShouldSkip(cur_file))
+ const FilePath filename(find_data_.cFileName);
+ if (ShouldSkip(filename))
continue;
- // Construct the absolute filename.
- cur_file = root_path_.Append(find_data_.cFileName);
-
- if (find_data_.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
- if (recursive_) {
- // If |cur_file| is a directory, and we are doing recursive searching,
- // add it to pending_paths_ so we scan it after we finish scanning this
- // directory. However, don't do recursion through reparse points or we
- // may end up with an infinite cycle.
- DWORD attributes = GetFileAttributes(cur_file.value().c_str());
- if (!(attributes & FILE_ATTRIBUTE_REPARSE_POINT))
- pending_paths_.push(cur_file);
- }
- if (file_type_ & FileEnumerator::DIRECTORIES)
- return cur_file;
- } else if (file_type_ & FileEnumerator::FILES) {
- return cur_file;
+ const bool is_dir =
+ (find_data_.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
+ const FilePath abs_path = root_path_.Append(filename);
+
+ // Check if directory should be processed recursive.
+ if (is_dir && recursive_) {
+ // If |cur_file| is a directory, and we are doing recursive searching,
+ // add it to pending_paths_ so we scan it after we finish scanning this
+ // directory. However, don't do recursion through reparse points or we
+ // may end up with an infinite cycle.
+ DWORD attributes = GetFileAttributes(abs_path.value().c_str());
+ if (!(attributes & FILE_ATTRIBUTE_REPARSE_POINT))
+ pending_paths_.push(abs_path);
}
- }
+ if (IsTypeMatched(is_dir) && IsPatternMatched(filename))
+ return abs_path;
+ }
return FilePath();
}
+bool FileEnumerator::IsPatternMatched(const FilePath& src) const {
+ switch (folder_search_policy_) {
+ case FolderSearchPolicy::MATCH_ONLY:
+ // MATCH_ONLY policy filters by pattern on search request, so all found
+ // files already fits to pattern.
+ return true;
+ case FolderSearchPolicy::ALL:
+ // ALL policy enumerates all files, we need to check pattern match
+ // manually.
+ return PathMatchSpec(src.value().c_str(), pattern_.c_str()) == TRUE;
+ }
+ NOTREACHED();
+ return false;
+}
+
} // namespace base
« no previous file with comments | « base/files/file_enumerator_unittest.cc ('k') | chrome_elf/BUILD.gn » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698