summaryrefslogtreecommitdiffstats
path: root/xbmc/utils/TextSearch.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/utils/TextSearch.cpp')
-rw-r--r--xbmc/utils/TextSearch.cpp146
1 files changed, 146 insertions, 0 deletions
diff --git a/xbmc/utils/TextSearch.cpp b/xbmc/utils/TextSearch.cpp
new file mode 100644
index 0000000..1ada61d
--- /dev/null
+++ b/xbmc/utils/TextSearch.cpp
@@ -0,0 +1,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);
+ }
+}