Chromium Code Reviews| Index: components/query_parser/query_parser.cc |
| diff --git a/components/query_parser/query_parser.cc b/components/query_parser/query_parser.cc |
| index 96c73c2de5e9f719366cc98952b669c350ce54b5..dc8471e76a1c6ed6b634f8293a8fb06a8f1a45a5 100644 |
| --- a/components/query_parser/query_parser.cc |
| +++ b/components/query_parser/query_parser.cc |
| @@ -71,6 +71,7 @@ class QueryNodeWord : public QueryNode { |
| const base::string16& word() const { return word_; } |
| + bool literal() const { return literal_; }; |
| void set_literal(bool literal) { literal_ = literal; } |
| // QueryNode: |
| @@ -142,6 +143,44 @@ void QueryNodeWord::AppendWords(std::vector<base::string16>* words) const { |
| words->push_back(word_); |
| } |
| +// A QueryNodePrefixWord is a single word in the query that can always be used |
| +// in a prefix search. By comparison, short words as QueryNodeWord are only |
| +// checked for exact matches. |
| +class QueryNodePrefixWord : public QueryNodeWord { |
|
Kibeom Kim (inactive)
2014/11/03 18:41:32
It looks like this class is identical to QueryNode
sky
2014/11/03 21:44:05
Why bother with a template and not a field, always
Kibeom Kim (inactive)
2014/11/04 01:28:19
Done.
Since the class is local to this file and n
|
| + public: |
| + explicit QueryNodePrefixWord(const base::string16& word); |
| + ~QueryNodePrefixWord() override; |
| + |
| + // QueryNodeWord: |
| + int AppendToSQLiteQuery(base::string16* query) const override; |
| + bool Matches(const base::string16& word, bool exact) const override; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(QueryNodePrefixWord); |
| +}; |
| + |
| +QueryNodePrefixWord::QueryNodePrefixWord(const base::string16& word) |
| + : QueryNodeWord(word) {} |
| + |
| +QueryNodePrefixWord::~QueryNodePrefixWord() {} |
| + |
| +int QueryNodePrefixWord::AppendToSQLiteQuery(base::string16* query) const { |
| + query->append(this->word()); |
| + |
| + // Use prefix search if we're not literal and long enough. |
| + if (!this->literal()) |
| + *query += L'*'; |
| + return 1; |
| +} |
| + |
| +bool QueryNodePrefixWord::Matches(const base::string16& word, |
| + bool exact) const { |
| + if (exact) |
| + return word == this->word(); |
| + return word.size() >= this->word().size() && |
| + (this->word().compare( |
| + 0, this->word().size(), word, 0, this->word().size()) == 0); |
| +} |
| + |
| // A QueryNodeList has a collection of QueryNodes which are deleted in the end. |
| class QueryNodeList : public QueryNode { |
| public: |
| @@ -327,25 +366,28 @@ bool QueryParser::IsWordLongEnoughForPrefixSearch(const base::string16& word) { |
| } |
| int QueryParser::ParseQuery(const base::string16& query, |
| + bool always_prefix_search, |
| base::string16* sqlite_query) { |
| QueryNodeList root; |
| - if (!ParseQueryImpl(query, &root)) |
| + if (!ParseQueryImpl(query, always_prefix_search, &root)) |
| return 0; |
| return root.AppendToSQLiteQuery(sqlite_query); |
| } |
| void QueryParser::ParseQueryWords(const base::string16& query, |
| + bool always_prefix_search, |
| std::vector<base::string16>* words) { |
| QueryNodeList root; |
| - if (!ParseQueryImpl(query, &root)) |
| + if (!ParseQueryImpl(query, always_prefix_search, &root)) |
| return; |
| root.AppendWords(words); |
| } |
| void QueryParser::ParseQueryNodes(const base::string16& query, |
| + bool always_prefix_search, |
| QueryNodeStarVector* nodes) { |
| QueryNodeList root; |
| - if (ParseQueryImpl(base::i18n::ToLower(query), &root)) |
| + if (ParseQueryImpl(base::i18n::ToLower(query), always_prefix_search, &root)) |
| nodes->swap(*root.children()); |
| } |
| @@ -393,6 +435,7 @@ bool QueryParser::DoesQueryMatch(const QueryWordVector& query_words, |
| } |
| bool QueryParser::ParseQueryImpl(const base::string16& query, |
| + bool always_prefix_search, |
| QueryNodeList* root) { |
| base::i18n::BreakIterator iter(query, base::i18n::BreakIterator::BREAK_WORD); |
| // TODO(evanm): support a locale here |
| @@ -410,7 +453,9 @@ bool QueryParser::ParseQueryImpl(const base::string16& query, |
| // is not necessarily a word, but could also be a sequence of punctuation |
| // or whitespace. |
| if (iter.IsWord()) { |
| - QueryNodeWord* word_node = new QueryNodeWord(iter.GetString()); |
| + QueryNodeWord* word_node = (always_prefix_search) |
| + ? new QueryNodePrefixWord(iter.GetString()) |
| + : new QueryNodeWord(iter.GetString()); |
| if (in_quotes) |
| word_node->set_literal(true); |
| query_stack.back()->AddChild(word_node); |