remwharead  0.8.0
Public Member Functions | List of all members
remwharead::Search Class Reference

Search in database entries. More...

#include <remwharead/search.hpp>

Public Member Functions

 Search (const list< Database::entry > &entries)
 Defines the entries to search. More...
 
const list< Database::entrysearch_tags (string expression, const bool is_re) const
 Search in tags of database entries. More...
 
const list< Database::entrysearch_all (string expression, const bool is_re) const
 Search in full text of database entries. More...
 
const list< Database::entrysearch_all_threaded (string expression, const bool is_re) const
 Spawn threads of search_all(), if it seems sensible. More...
 

Detailed Description

Search in database entries.

Since
0.7.0

Constructor & Destructor Documentation

◆ Search()

remwharead::Search::Search ( const list< Database::entry > &  entries)
explicit

Defines the entries to search.

Since
0.7.0
39  :_entries(entries)
40  {}

Member Function Documentation

◆ search_all()

const list< DB::entry > remwharead::Search::search_all ( string  expression,
const bool  is_re 
) const

Search in full text of database entries.

Searches in tags, title, description and full text.

Parameters
expressionSearch expression.
is_reIs it a regular expression?
Returns
List of matching Database::entry.
Since
0.7.0
128  {
129  vector<vector<string>> searchlist = parse_expression(expression);
130  list<DB::entry> result = search_tags(expression, is_re);
131 
132  for (const vector<string> &terms_or : searchlist)
133  {
134  for (const DB::entry &entry : _entries)
135  {
136  // Add entry to result if all terms in an OR-slice match title,
137  // description or full text.
138  bool matched_title = true;
139  bool matched_description = true;
140  bool matched_fulltext = true;
141 
142  const auto it = find(result.begin(), result.end(), entry);
143  if (it != result.end())
144  { // Skip if already in result list.
145  continue;
146  }
147 
148  for (const string &term : terms_or)
149  {
150  const string title = to_lowercase(entry.title);
151  const string description = to_lowercase(entry.description);
152  const string fulltext = to_lowercase(entry.fulltext);
153 
154  // Set matched_* to false if term is not found.
155  if (is_re)
156  {
157  const regex re(term);
158 
159  if(!regex_search(title, re))
160  {
161  matched_title = false;
162  }
163 
164  if(!regex_search(description, re))
165  {
166  matched_description = false;
167  }
168 
169  if(!regex_search(fulltext, re))
170  {
171  matched_fulltext = false;
172  }
173  }
174  else
175  {
176  if (title.find(term) == string::npos)
177  {
178  matched_title = false;
179  }
180 
181  if (description.find(term) == string::npos)
182  {
183  matched_description = false;
184  }
185 
186  if (fulltext.find(term) == string::npos)
187  {
188  matched_fulltext = false;
189  }
190  }
191  }
192  if (matched_title == true
193  || matched_description == true
194  || matched_fulltext == true)
195  {
196  result.push_back(entry);
197  }
198  }
199  }
200 
201  return result;
202  }
struct remwharead::Database::entry entry
Describes a database entry.
const list< Database::entry > search_tags(string expression, const bool is_re) const
Search in tags of database entries.
Definition: search.cpp:82

◆ search_all_threaded()

const list< Database::entry > remwharead::Search::search_all_threaded ( string  expression,
const bool  is_re 
) const

Spawn threads of search_all(), if it seems sensible.

Figure out if threads could be useful and spawn a sensible amount of them.

Parameters
expressionSearch expression.
is_reIs it a regular expression?
Returns
List of matching Database::entry.
Since
0.7.2
206  {
207  list<Database::entry> entries = _entries;
208 
209  const size_t len = entries.size();
210  constexpr size_t min_len = 100;
211  constexpr size_t min_per_thread = 50;
212  const size_t n_threads = thread::hardware_concurrency() / 3 + 1;
213  size_t cut_at = len;
214  if (len > min_len)
215  { // If there are over `min_len` entries, use `n_threads` threads.
216  cut_at = len / n_threads;
217 
218  // But don't use less than `min_per_thread` entries per thread.
219  if (cut_at < min_per_thread)
220  {
221  cut_at = min_per_thread;
222  }
223  }
224 
225  list<list<Database::entry>> segments;
226 
227  // Use threads if list is big.
228  while (entries.size() > cut_at)
229  {
230  list<Database::entry> segment;
231 
232  auto it = entries.begin();
233  std::advance(it, cut_at);
234 
235  // Move the first `cut_at` entries into `segments`.
236  segment.splice(segment.begin(), entries, entries.begin(), it);
237  segments.push_back(move(segment));
238  }
239  // Move rest of `entries` into `segments`.
240  segments.push_back(move(entries));
241 
242  list<thread> threads;
243  for (auto &segment : segments)
244  {
245  thread t(
246  [&]
247  {
248  Search search(segment);
249  // Replace `segment` with `result`.
250  segment = search.search_all(expression, is_re);
251  });
252  threads.push_back(move(t));
253  }
254 
255  for (thread &t : threads)
256  {
257  t.join();
258  // Move each of `segments` into `entries`.
259  entries.splice(entries.end(), segments.front());
260  segments.pop_front();
261  }
262 
263  return entries;
264  }
Search(const list< Database::entry > &entries)
Defines the entries to search.
Definition: search.cpp:38

◆ search_tags()

const list< DB::entry > remwharead::Search::search_tags ( string  expression,
const bool  is_re 
) const

Search in tags of database entries.

Only matches whole tags, Pill does not match Pillow.

Parameters
expressionSearch expression.
is_reIs it a regular expression?
Returns
List of matching Database::entry.
Since
0.7.0
84  {
85  vector<vector<string>> searchlist = parse_expression(expression);
86  list<DB::entry> result;
87 
88  for (const vector<string> &tags_or : searchlist)
89  {
90  for (const DB::entry &entry : _entries)
91  { // Add entry to result if all tags in an OR-slice match.
92  bool matched = true;
93 
94  for (const string &tag : tags_or)
95  {
96  const auto it = find_if(
97  entry.tags.begin(), entry.tags.end(),
98  [&, is_re](string s)
99  {
100  s = to_lowercase(s);
101  if (is_re)
102  {
103  const regex re("^" + tag + "$");
104  return regex_search(s, re);
105  }
106  else
107  {
108  return (s == tag);
109  }
110  });
111  if (it == entry.tags.end())
112  {
113  matched = false;
114  }
115  }
116  if (matched == true)
117  {
118  result.push_back(entry);
119  }
120  }
121  }
122 
123  return result;
124  }
struct remwharead::Database::entry entry
Describes a database entry.

The documentation for this class was generated from the following files: