diff --git a/base/mem_trie.hpp b/base/mem_trie.hpp index d5394f5bf3..6bd161eed9 100644 --- a/base/mem_trie.hpp +++ b/base/mem_trie.hpp @@ -3,6 +3,7 @@ #include "base/macros.hpp" #include "base/stl_add.hpp" +#include #include #include #include @@ -32,25 +33,28 @@ public: return *this; } - // A read-only iterator. Any modification to the + // A read-only iterator wrapping a Node. Any modification to the // underlying trie is assumed to invalidate the iterator. class Iterator { public: Iterator(MemTrie::Node const & node) : m_node(node) {} + // Iterates over all possible moves from this Iterator's node + // and calls |toDo| with two arguments: + // (Char of the move, Iterator wrapping the node of the move). template - void ForEachMove(ToDo && todo) const + void ForEachMove(ToDo && toDo) const { for (auto const & move : m_node.m_moves) - todo(move.first, Iterator(*move.second)); + toDo(move.first, Iterator(*move.second)); } + // Calls |toDo| for every value in this Iterator's node. template - void ForEachInNode(ToDo && todo) const + void ForEachInNode(ToDo && toDo) const { - for (auto const & value : m_node.m_values) - todo(value); + std::for_each(m_node.m_values.begin(), m_node.m_values.end(), std::forward(toDo)); } private: @@ -71,32 +75,32 @@ public: cur->AddValue(value); } - // Traverses all key-value pairs in the trie and calls |todo| on each of them. + // Traverses all key-value pairs in the trie and calls |toDo| on each of them. template - void ForEachInTrie(ToDo && todo) const + void ForEachInTrie(ToDo && toDo) const { String prefix; - ForEachInSubtree(m_root, prefix, std::forward(todo)); + ForEachInSubtree(m_root, prefix, std::forward(toDo)); } - // Calls |todo| for each key-value pair in the node that is reachable + // Calls |toDo| for each key-value pair in the node that is reachable // by |prefix| from the trie root. Does nothing if such node does // not exist. template - void ForEachInNode(String const & prefix, ToDo && todo) const + void ForEachInNode(String const & prefix, ToDo && toDo) const { if (auto const * root = MoveTo(prefix)) - ForEachInNode(*root, prefix, std::forward(todo)); + ForEachInNode(*root, prefix, std::forward(toDo)); } - // Calls |todo| for each key-value pair in a subtree that is + // Calls |toDo| for each key-value pair in a subtree that is // reachable by |prefix| from the trie root. Does nothing if such // subtree does not exist. template - void ForEachInSubtree(String prefix, ToDo && todo) const + void ForEachInSubtree(String prefix, ToDo && toDo) const { if (auto const * root = MoveTo(prefix)) - ForEachInSubtree(*root, prefix, std::forward(todo)); + ForEachInSubtree(*root, prefix, std::forward(toDo)); } size_t GetNumNodes() const { return m_numNodes; } @@ -149,27 +153,27 @@ private: return cur; } - // Calls |todo| for each key-value pair in a |node| that is + // Calls |toDo| for each key-value pair in a |node| that is // reachable by |prefix| from the trie root. template - void ForEachInNode(Node const & node, String const & prefix, ToDo && todo) const + void ForEachInNode(Node const & node, String const & prefix, ToDo && toDo) const { for (auto const & value : node.m_values) - todo(prefix, value); + toDo(prefix, value); } - // Calls |todo| for each key-value pair in subtree where |node| is a + // Calls |toDo| for each key-value pair in subtree where |node| is a // root of the subtree. |prefix| is a path from the trie root to the // |node|. template - void ForEachInSubtree(Node const & node, String & prefix, ToDo && todo) const + void ForEachInSubtree(Node const & node, String & prefix, ToDo && toDo) const { - ForEachInNode(node, prefix, todo); + ForEachInNode(node, prefix, toDo); for (auto const & move : node.m_moves) { prefix.push_back(move.first); - ForEachInSubtree(*move.second, prefix, todo); + ForEachInSubtree(*move.second, prefix, toDo); prefix.pop_back(); } } diff --git a/base/string_utils.cpp b/base/string_utils.cpp index d1ac84b24a..f2546161fb 100644 --- a/base/string_utils.cpp +++ b/base/string_utils.cpp @@ -237,19 +237,14 @@ bool IsASCIIString(std::string const & str) bool IsASCIIDigit(UniChar c) { return c >= '0' && c <= '9'; } bool IsASCIILatin(UniChar c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); } + bool StartsWith(UniString const & s, UniString const & p) { - if (p.size() > s.size()) - return false; - for (size_t i = 0; i < p.size(); ++i) - { - if (s[i] != p[i]) - return false; - } - return true; + return StartsWith(s.begin(), s.end(), p.begin(), p.end()); } bool StartsWith(std::string const & s1, char const * s2) { return (s1.compare(0, strlen(s2), s2) == 0); } + bool EndsWith(std::string const & s1, char const * s2) { size_t const n = s1.size(); diff --git a/base/string_utils.hpp b/base/string_utils.hpp index af8670c5a4..8fc2228b40 100644 --- a/base/string_utils.hpp +++ b/base/string_utils.hpp @@ -439,6 +439,17 @@ std::string to_string_dac(double d, int dac); inline std::string to_string_with_digits_after_comma(double d, int dac) { return to_string_dac(d, dac); } //@} +template +bool StartsWith(IterT1 beg, IterT1 end, IterT2 begPrefix, IterT2 endPrefix) +{ + while (beg != end && begPrefix != endPrefix && *beg == *begPrefix) + { + ++beg; + ++begPrefix; + } + return begPrefix == endPrefix; +} + bool StartsWith(UniString const & s, UniString const & p); bool StartsWith(std::string const & s1, char const * s2); diff --git a/search/keyword_matcher.cpp b/search/keyword_matcher.cpp index 42672f5119..073a9f80b8 100644 --- a/search/keyword_matcher.cpp +++ b/search/keyword_matcher.cpp @@ -1,11 +1,10 @@ #include "search/keyword_matcher.hpp" -#include "search/utils.hpp" - #include "indexer/search_delimiters.hpp" #include "indexer/search_string_utils.hpp" #include "base/stl_add.hpp" +#include "base/string_utils.hpp" #include "std/algorithm.hpp" #include "std/sstream.hpp" @@ -69,7 +68,7 @@ KeywordMatcher::ScoreT KeywordMatcher::Score(StringT const * tokens, size_t coun bPrefixMatched = false; for (int j = 0; j < count && !bPrefixMatched; ++j) if (!isNameTokenMatched[j] && - StartsWith(tokens[j].begin(), tokens[j].end(), m_prefix.begin(), m_prefix.end())) + strings::StartsWith(tokens[j].begin(), tokens[j].end(), m_prefix.begin(), m_prefix.end())) { isNameTokenMatched[j] = bPrefixMatched = true; int8_t const tokenMatchDistance = int(m_keywords.size()) - j; diff --git a/search/processor.cpp b/search/processor.cpp index b5e7c4e577..1382b9db5c 100644 --- a/search/processor.cpp +++ b/search/processor.cpp @@ -129,7 +129,7 @@ void SendStatistics(SearchParams const & params, m2::RectD const & viewport, Res } // Removes all full-token stop words from |params|. -// Does nothing if all tokens in |params| are stop words. +// Does nothing if all tokens in |params| are non-prefix stop words. void RemoveStopWordsIfNeeded(QueryParams & params) { size_t numStopWords = 0; @@ -409,16 +409,16 @@ TLocales Processor::GetCategoryLocales() const } template -void Processor::ForEachCategoryType(StringSliceBase const & slice, ToDo && todo) const +void Processor::ForEachCategoryType(StringSliceBase const & slice, ToDo && toDo) const { - ::search::ForEachCategoryType(slice, GetCategoryLocales(), m_categories, forward(todo)); + ::search::ForEachCategoryType(slice, GetCategoryLocales(), m_categories, forward(toDo)); } template -void Processor::ForEachCategoryTypeFuzzy(StringSliceBase const & slice, ToDo && todo) const +void Processor::ForEachCategoryTypeFuzzy(StringSliceBase const & slice, ToDo && toDo) const { ::search::ForEachCategoryTypeFuzzy(slice, GetCategoryLocales(), m_categories, - forward(todo)); + forward(toDo)); } void Processor::Search(SearchParams const & params, m2::RectD const & viewport) diff --git a/search/processor.hpp b/search/processor.hpp index c32d03f16d..3ad34f7ad1 100644 --- a/search/processor.hpp +++ b/search/processor.hpp @@ -139,10 +139,10 @@ protected: TLocales GetCategoryLocales() const; template - void ForEachCategoryType(StringSliceBase const & slice, ToDo && todo) const; + void ForEachCategoryType(StringSliceBase const & slice, ToDo && toDo) const; template - void ForEachCategoryTypeFuzzy(StringSliceBase const & slice, ToDo && todo) const; + void ForEachCategoryTypeFuzzy(StringSliceBase const & slice, ToDo && toDo) const; m2::PointD GetPivotPoint() const; m2::RectD GetPivotRect() const; diff --git a/search/ranker.cpp b/search/ranker.cpp index 84b4048f2c..b2e708a162 100644 --- a/search/ranker.cpp +++ b/search/ranker.cpp @@ -8,6 +8,7 @@ #include "indexer/feature_algo.hpp" #include "base/logging.hpp" +#include "base/string_utils.hpp" #include "std/algorithm.hpp" #include "std/iterator.hpp" @@ -433,7 +434,7 @@ void Ranker::MatchForSuggestions(strings::UniString const & token, int8_t locale if ((suggest.m_prefixLength <= token.size()) && (token != s) && // do not push suggestion if it already equals to token (suggest.m_locale == locale) && // push suggestions only for needed language - StartsWith(s.begin(), s.end(), token.begin(), token.end())) + strings::StartsWith(s.begin(), s.end(), token.begin(), token.end())) { string const utf8Str = strings::ToUtf8(s); Result r(utf8Str, prologue + utf8Str + " "); diff --git a/search/utils.hpp b/search/utils.hpp index 919a18e907..717f100eb9 100644 --- a/search/utils.hpp +++ b/search/utils.hpp @@ -18,8 +18,6 @@ namespace search { -namespace -{ // my::MemTrie // todo(@m, @y). Unite with the similar function in search/feature_offset_match.hpp. template @@ -65,7 +63,6 @@ bool MatchInTrie(Trie const & trie, DFA const & dfa, ToDo && toDo) return found; } -} // namespace using TLocales = buffer_vector; @@ -113,15 +110,4 @@ void ForEachCategoryTypeFuzzy(StringSliceBase const & slice, TLocales const & lo } } } - -template -bool StartsWith(IterT1 beg, IterT1 end, IterT2 begPrefix, IterT2 endPrefix) -{ - while (beg != end && begPrefix != endPrefix && *beg == *begPrefix) - { - ++beg; - ++begPrefix; - } - return begPrefix == endPrefix; -} } // namespace search