| // Copyright 2023 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/ash/extensions/file_manager/search_by_pattern.h" |
| |
| #include <ctype.h> |
| |
| #include "base/files/file_enumerator.h" |
| #include "base/strings/strcat.h" |
| #include "base/strings/string_util.h" |
| #include "chrome/browser/ash/fileapi/recent_disk_source.h" |
| |
| namespace extensions { |
| |
| std::string CreateFnmatchQuery(const std::string& query) { |
| std::vector<std::string> query_pieces = {"*"}; |
| size_t sequence_start = 0; |
| for (size_t i = 0; i < query.size(); ++i) { |
| if (isalpha(query[i])) { |
| if (sequence_start != i) { |
| query_pieces.push_back( |
| query.substr(sequence_start, i - sequence_start)); |
| } |
| std::string piece("["); |
| piece.resize(4); |
| piece[1] = tolower(query[i]); |
| piece[2] = toupper(query[i]); |
| piece[3] = ']'; |
| query_pieces.push_back(std::move(piece)); |
| sequence_start = i + 1; |
| } |
| } |
| if (sequence_start != query.size()) { |
| query_pieces.push_back(query.substr(sequence_start)); |
| } |
| if (query_pieces.size() > 1) { |
| query_pieces.push_back("*"); |
| } |
| |
| return base::StrCat(query_pieces); |
| } |
| |
| std::vector<std::pair<base::FilePath, bool>> SearchByPattern( |
| const base::FilePath& root, |
| const std::string& query, |
| const base::Time& min_timestamp, |
| ash::RecentSource::FileType file_type, |
| size_t max_results) { |
| std::vector<std::pair<base::FilePath, bool>> prefix_matches; |
| std::vector<std::pair<base::FilePath, bool>> other_matches; |
| |
| base::FileEnumerator enumerator( |
| root, true, |
| base::FileEnumerator::DIRECTORIES | base::FileEnumerator::FILES, |
| CreateFnmatchQuery(query), base::FileEnumerator::FolderSearchPolicy::ALL); |
| |
| for (base::FilePath path = enumerator.Next(); !path.empty(); |
| path = enumerator.Next()) { |
| if (enumerator.GetInfo().GetLastModifiedTime() < min_timestamp) { |
| continue; |
| } |
| if (!ash::RecentDiskSource::MatchesFileType(path, file_type)) { |
| continue; |
| } |
| if (base::StartsWith(path.BaseName().value(), query, |
| base::CompareCase::INSENSITIVE_ASCII)) { |
| prefix_matches.emplace_back(path, enumerator.GetInfo().IsDirectory()); |
| if (max_results && prefix_matches.size() == max_results) { |
| return prefix_matches; |
| } |
| continue; |
| } |
| if (!max_results || |
| prefix_matches.size() + other_matches.size() < max_results) { |
| other_matches.emplace_back(path, enumerator.GetInfo().IsDirectory()); |
| } |
| } |
| prefix_matches.insert( |
| prefix_matches.end(), other_matches.begin(), |
| other_matches.begin() + |
| std::min(max_results - prefix_matches.size(), other_matches.size())); |
| |
| return prefix_matches; |
| } |
| |
| } // namespace extensions |