remwharead  0.6.3
Functions
search.hpp File Reference
#include <vector>
#include <string>
#include "sqlite.hpp"

Go to the source code of this file.

Functions

const vector< vector< string > > remwharead::parse_expression (string expression)
 Split expression in subexpressions. More...
 
const string remwharead::to_lowercase (const string &str)
 Convert str to lowercase. Works with unicode. More...
 
const vector< DB::entry > remwharead::search_tags (const vector< Database::entry > &entries, string expression, const bool is_re)
 Search in tags of database entries. More...
 
const vector< DB::entry > remwharead::search_all (const vector< Database::entry > &entries, string expression, const bool is_re)
 Search in full text of database entries. More...
 

Function Documentation

◆ parse_expression()

const vector< vector< string > > remwharead::parse_expression ( string  expression)

Split expression in subexpressions.

First it splits at OR or ||, then it splits the subexpressions at AND or &&. The first vector contains all tags before the first OR.

Returns
Vector of OR-vectors of AND-tags.
32  {
33  vector<vector<string>> searchlist;
34  const regex re_or("(.+?) (OR|\\|\\|) ");
35  const regex re_and("(.+?) (AND|&&) ");
36  smatch match;
37 
38  vector<string> subexpressions;
39  { // Split expression at OR.
40  while (regex_search(expression, match, re_or))
41  {
42  subexpressions.push_back(match[1].str());
43  expression = match.suffix().str();
44  }
45  subexpressions.push_back(expression);
46  }
47 
48  {
49  for (string sub : subexpressions)
50  { // Split each OR-slice at AND.
51  vector<string> terms;
52  while (regex_search(sub, match, re_and))
53  {
54  terms.push_back(to_lowercase(match[1].str()));
55  sub = match.suffix().str();
56  }
57  terms.push_back(to_lowercase(sub));
58  searchlist.push_back(terms);
59  }
60  }
61 
62  return searchlist;
63  }

◆ search_all()

const vector< Database::entry > remwharead::search_all ( const vector< Database::entry > &  entries,
string  expression,
const bool  is_re 
)

Search in full text of database entries.

Searches in tags, title, description and full text.

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

◆ search_tags()

const vector< Database::entry > remwharead::search_tags ( const vector< Database::entry > &  entries,
string  expression,
const bool  is_re 
)

Search in tags of database entries.

Only matches whole tags, Pill does not match Pillow.

Parameters
entriesVector of Database::entry to search.
expressionSearch expression.
is_reIs it a regular expression?
Returns
Vector of matching Database::entry.
75  {
76  vector<vector<string>> searchlist = parse_expression(expression);
77  vector<DB::entry> result;
78 
79  for (const vector<string> &tags_or : searchlist)
80  {
81  for (const DB::entry &entry : entries)
82  { // Add entry to result if all tags in an OR-slice match.
83  bool matched = true;
84 
85  for (const string &tag : tags_or)
86  {
87  const auto it = find_if(
88  entry.tags.begin(), entry.tags.end(),
89  [&tag, is_re](string s)
90  {
91  s = to_lowercase(s);
92  if (is_re)
93  {
94  const regex re("^" + tag + "$");
95  return regex_search(s, re);
96  }
97  else
98  {
99  return (s == tag);
100  }
101  });
102  if (it == entry.tags.end())
103  {
104  matched = false;
105  }
106  }
107  if (matched == true)
108  {
109  result.push_back(entry);
110  }
111  }
112  }
113 
114  return result;
115  }

◆ to_lowercase()

const string remwharead::to_lowercase ( const string &  str)

Convert str to lowercase. Works with unicode.

66  {
67  icu::UnicodeString uni(str.c_str());
68  string out;
69  uni.toLower().toUTF8String(out);
70  return out;
71  }