-
Notifications
You must be signed in to change notification settings - Fork 0
/
SearchEngine.cpp
144 lines (118 loc) · 3.68 KB
/
SearchEngine.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#include <main.h>
#include <SearchEngine.h>
std::list<fs::path> indexResults;
std::mutex indexMutex;
void SearchEngine::IndexDirectory(const fs::path& directory)
{
if(!fs::exists(directory)) {
LOGI("Can't index dir");
return;
}
std::async(std::launch::async, [directory]() {
std::lock_guard<std::mutex> lock(indexMutex);
indexResults.clear();
try {
for (const auto& entry : fs::recursive_directory_iterator(directory, fs::directory_options::skip_permission_denied)) {
LOGI("Indexing path: " + entry.path().string());
indexResults.push_back(entry.path());
}
} catch (const std::exception& e) {
LOGI("Error during indexing: " + std::string(e.what()));
}
LOGI("Indexing completed");
});
}
bool SearchEngine::FindOne(const std::string& keys)
{
auto it = std::find_if(indexResults.begin(), indexResults.end(),
[&keys](const fs::path& path) {
return strstr(path.string().c_str(), keys.c_str());
});
if (it != indexResults.end()) {
LOGI("File found: " + it->string());
return true;
} else {
LOGI("File not found");
return false;
}
}
std::list<fs::path> SearchEngine::SearchByKeywords(const std::string& keyword)
{
std::list<fs::path> results{};
// filter invalid chars
if (!keyword.empty()) {
for (char c : keyword) {
if (c == '\0' || c == '\\') {
return SearchByKeywords("");
}
}
}
for (const auto& path : indexResults) {
if (!fs::exists(path)) {
LOGE("Path does not exist: " + path.string());
break;
}
std::string pathStr;
try {
pathStr = path.string();
} catch (const std::exception& e) {
LOGE("Error converting path to string: " + std::string(e.what()));
continue;
}
if (pathStr.find(keyword) != std::string::npos) {
LOGI("Found match: " + pathStr);
results.push_back(path);
}
}
if (results.empty()) {
LOGI("No matches found for keyword: " + keyword);
return SearchByKeywords("");
}
return results;
}
std::mutex resultsMutex;
void SearchInChunk(const std::list<fs::path>::iterator& start, const std::list<fs::path>::iterator& end,
const std::regex& pattern, std::list<fs::path>& results) {
for (auto it = start; it != end; ++it) {
if (std::regex_search(it->string(), pattern)) {
std::lock_guard<std::mutex> lock(resultsMutex); // Protect the results list
LOGI("Found match: " + it->string());
results.push_back(*it);
}
}
}
std::list<fs::path> SearchEngine::SearchByRegex(const std::string& regexPattern) {
std::list<fs::path> results;
try {
std::regex pattern(regexPattern);
int numThreads = std::thread::hardware_concurrency();
if (numThreads == 0) {
numThreads = 4;
}
auto totalPaths = indexResults.size();
auto chunkSize = totalPaths / numThreads;
std::vector<std::thread> threads;
auto it = indexResults.begin();
for (int i = 0; i < numThreads - 1; ++i) {
auto chunkEnd = std::next(it, chunkSize);
threads.emplace_back(SearchInChunk, it, chunkEnd, std::cref(pattern), std::ref(results));
it = chunkEnd;
}
threads.emplace_back(SearchInChunk, it, indexResults.end(), std::cref(pattern), std::ref(results));
for (auto& t : threads) {
if (t.joinable()) {
t.join();
}
}
if (results.empty()) {
LOGI("No matches found for regex: " + regexPattern);
}
} catch (const std::regex_error& e) {
LOGI("Invalid regex pattern: " + regexPattern + ", Error: " + e.what());
} catch (const std::exception& e) {
LOGI("Exception during search: " + std::string(e.what()));
} catch (const std::logic_error& e) {
LOGI("Exception logic error: " + std::string(e.what()));
}
return results;
}