diff options
Diffstat (limited to 'xbmc/utils/TextSearch.cpp')
-rw-r--r-- | xbmc/utils/TextSearch.cpp | 146 |
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); + } +} |