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
145
146
|
/*
* Copyright (C) 2005-2018 Team Kodi
* This file is part of Kodi - https://kodi.tv
*
* SPDX-License-Identifier: GPL-2.0-or-later
* See LICENSES/README.md for more information.
*/
#include "TextSearch.h"
#include "StringUtils.h"
CTextSearch::CTextSearch(const std::string &strSearchTerms, bool bCaseSensitive /* = false */, TextSearchDefault defaultSearchMode /* = SEARCH_DEFAULT_OR */)
{
m_bCaseSensitive = bCaseSensitive;
ExtractSearchTerms(strSearchTerms, defaultSearchMode);
}
bool CTextSearch::IsValid(void) const
{
return m_AND.size() > 0 || m_OR.size() > 0 || m_NOT.size() > 0;
}
bool CTextSearch::Search(const std::string &strHaystack) const
{
if (strHaystack.empty() || !IsValid())
return false;
std::string strSearch(strHaystack);
if (!m_bCaseSensitive)
StringUtils::ToLower(strSearch);
/* check whether any of the NOT terms matches and return false if there's a match */
for (unsigned int iNotPtr = 0; iNotPtr < m_NOT.size(); iNotPtr++)
{
if (strSearch.find(m_NOT.at(iNotPtr)) != std::string::npos)
return false;
}
/* check whether at least one of the OR terms matches and return false if there's no match found */
bool bFound(m_OR.empty());
for (unsigned int iOrPtr = 0; iOrPtr < m_OR.size(); iOrPtr++)
{
if (strSearch.find(m_OR.at(iOrPtr)) != std::string::npos)
{
bFound = true;
break;
}
}
if (!bFound)
return false;
/* check whether all of the AND terms match and return false if one of them wasn't found */
for (unsigned int iAndPtr = 0; iAndPtr < m_AND.size(); iAndPtr++)
{
if (strSearch.find(m_AND[iAndPtr]) == std::string::npos)
return false;
}
/* all ok, return true */
return true;
}
void CTextSearch::GetAndCutNextTerm(std::string &strSearchTerm, std::string &strNextTerm)
{
std::string strFindNext(" ");
if (StringUtils::EndsWith(strSearchTerm, "\""))
{
strSearchTerm.erase(0, 1);
strFindNext = "\"";
}
size_t iNextPos = strSearchTerm.find(strFindNext);
if (iNextPos != std::string::npos)
{
strNextTerm = strSearchTerm.substr(0, iNextPos);
strSearchTerm.erase(0, iNextPos + 1);
}
else
{
strNextTerm = strSearchTerm;
strSearchTerm.clear();
}
}
void CTextSearch::ExtractSearchTerms(const std::string &strSearchTerm, TextSearchDefault defaultSearchMode)
{
std::string strParsedSearchTerm(strSearchTerm);
StringUtils::Trim(strParsedSearchTerm);
if (!m_bCaseSensitive)
StringUtils::ToLower(strParsedSearchTerm);
bool bNextAND(defaultSearchMode == SEARCH_DEFAULT_AND);
bool bNextOR(defaultSearchMode == SEARCH_DEFAULT_OR);
bool bNextNOT(defaultSearchMode == SEARCH_DEFAULT_NOT);
while (strParsedSearchTerm.length() > 0)
{
StringUtils::TrimLeft(strParsedSearchTerm);
if (StringUtils::StartsWith(strParsedSearchTerm, "!") || StringUtils::StartsWithNoCase(strParsedSearchTerm, "not"))
{
std::string strDummy;
GetAndCutNextTerm(strParsedSearchTerm, strDummy);
bNextNOT = true;
}
else if (StringUtils::StartsWith(strParsedSearchTerm, "+") || StringUtils::StartsWithNoCase(strParsedSearchTerm, "and"))
{
std::string strDummy;
GetAndCutNextTerm(strParsedSearchTerm, strDummy);
bNextAND = true;
}
else if (StringUtils::StartsWith(strParsedSearchTerm, "|") || StringUtils::StartsWithNoCase(strParsedSearchTerm, "or"))
{
std::string strDummy;
GetAndCutNextTerm(strParsedSearchTerm, strDummy);
bNextOR = true;
}
else
{
std::string strTerm;
GetAndCutNextTerm(strParsedSearchTerm, strTerm);
if (strTerm.length() > 0)
{
if (bNextAND)
m_AND.push_back(strTerm);
else if (bNextOR)
m_OR.push_back(strTerm);
else if (bNextNOT)
m_NOT.push_back(strTerm);
}
else
{
break;
}
bNextAND = (defaultSearchMode == SEARCH_DEFAULT_AND);
bNextOR = (defaultSearchMode == SEARCH_DEFAULT_OR);
bNextNOT = (defaultSearchMode == SEARCH_DEFAULT_NOT);
}
StringUtils::TrimLeft(strParsedSearchTerm);
}
}
|