2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
9 #include "TextSearch.h"
11 #include "StringUtils.h"
13 CTextSearch::CTextSearch(const std::string
&strSearchTerms
, bool bCaseSensitive
/* = false */, TextSearchDefault defaultSearchMode
/* = SEARCH_DEFAULT_OR */)
15 m_bCaseSensitive
= bCaseSensitive
;
16 ExtractSearchTerms(strSearchTerms
, defaultSearchMode
);
19 bool CTextSearch::IsValid(void) const
21 return m_AND
.size() > 0 || m_OR
.size() > 0 || m_NOT
.size() > 0;
24 bool CTextSearch::Search(const std::string
&strHaystack
) const
26 if (strHaystack
.empty() || !IsValid())
29 std::string
strSearch(strHaystack
);
30 if (!m_bCaseSensitive
)
31 StringUtils::ToLower(strSearch
);
33 /* check whether any of the NOT terms matches and return false if there's a match */
34 for (unsigned int iNotPtr
= 0; iNotPtr
< m_NOT
.size(); iNotPtr
++)
36 if (strSearch
.find(m_NOT
.at(iNotPtr
)) != std::string::npos
)
40 /* check whether at least one of the OR terms matches and return false if there's no match found */
41 bool bFound(m_OR
.empty());
42 for (unsigned int iOrPtr
= 0; iOrPtr
< m_OR
.size(); iOrPtr
++)
44 if (strSearch
.find(m_OR
.at(iOrPtr
)) != std::string::npos
)
53 /* check whether all of the AND terms match and return false if one of them wasn't found */
54 for (unsigned int iAndPtr
= 0; iAndPtr
< m_AND
.size(); iAndPtr
++)
56 if (strSearch
.find(m_AND
[iAndPtr
]) == std::string::npos
)
60 /* all ok, return true */
64 void CTextSearch::GetAndCutNextTerm(std::string
&strSearchTerm
, std::string
&strNextTerm
)
66 std::string
strFindNext(" ");
68 if (StringUtils::EndsWith(strSearchTerm
, "\""))
70 strSearchTerm
.erase(0, 1);
74 size_t iNextPos
= strSearchTerm
.find(strFindNext
);
75 if (iNextPos
!= std::string::npos
)
77 strNextTerm
= strSearchTerm
.substr(0, iNextPos
);
78 strSearchTerm
.erase(0, iNextPos
+ 1);
82 strNextTerm
= strSearchTerm
;
83 strSearchTerm
.clear();
87 void CTextSearch::ExtractSearchTerms(const std::string
&strSearchTerm
, TextSearchDefault defaultSearchMode
)
89 std::string
strParsedSearchTerm(strSearchTerm
);
90 StringUtils::Trim(strParsedSearchTerm
);
92 if (!m_bCaseSensitive
)
93 StringUtils::ToLower(strParsedSearchTerm
);
95 bool bNextAND(defaultSearchMode
== SEARCH_DEFAULT_AND
);
96 bool bNextOR(defaultSearchMode
== SEARCH_DEFAULT_OR
);
97 bool bNextNOT(defaultSearchMode
== SEARCH_DEFAULT_NOT
);
99 while (strParsedSearchTerm
.length() > 0)
101 StringUtils::TrimLeft(strParsedSearchTerm
);
103 if (StringUtils::StartsWith(strParsedSearchTerm
, "!") || StringUtils::StartsWithNoCase(strParsedSearchTerm
, "not"))
105 std::string strDummy
;
106 GetAndCutNextTerm(strParsedSearchTerm
, strDummy
);
109 else if (StringUtils::StartsWith(strParsedSearchTerm
, "+") || StringUtils::StartsWithNoCase(strParsedSearchTerm
, "and"))
111 std::string strDummy
;
112 GetAndCutNextTerm(strParsedSearchTerm
, strDummy
);
115 else if (StringUtils::StartsWith(strParsedSearchTerm
, "|") || StringUtils::StartsWithNoCase(strParsedSearchTerm
, "or"))
117 std::string strDummy
;
118 GetAndCutNextTerm(strParsedSearchTerm
, strDummy
);
124 GetAndCutNextTerm(strParsedSearchTerm
, strTerm
);
125 if (strTerm
.length() > 0)
128 m_AND
.push_back(strTerm
);
130 m_OR
.push_back(strTerm
);
132 m_NOT
.push_back(strTerm
);
139 bNextAND
= (defaultSearchMode
== SEARCH_DEFAULT_AND
);
140 bNextOR
= (defaultSearchMode
== SEARCH_DEFAULT_OR
);
141 bNextNOT
= (defaultSearchMode
== SEARCH_DEFAULT_NOT
);
144 StringUtils::TrimLeft(strParsedSearchTerm
);