| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/query_parser/query_parser.h" | 5 #include "components/query_parser/query_parser.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
| 10 #include "base/i18n/break_iterator.h" | 10 #include "base/i18n/break_iterator.h" |
| (...skipping 28 matching lines...) Expand all Loading... |
| 39 i != matches->end(); ) { | 39 i != matches->end(); ) { |
| 40 if (SnippetIntersects(mp, *i)) { | 40 if (SnippetIntersects(mp, *i)) { |
| 41 mp.second = std::max(mp.second, i->second); | 41 mp.second = std::max(mp.second, i->second); |
| 42 i = matches->erase(i); | 42 i = matches->erase(i); |
| 43 } else { | 43 } else { |
| 44 return; | 44 return; |
| 45 } | 45 } |
| 46 } | 46 } |
| 47 } | 47 } |
| 48 | 48 |
| 49 // Sorts the match positions in |matches| by their first index, then coalesces | |
| 50 // any match positions that intersect each other. | |
| 51 void CoalseAndSortMatchPositions(Snippet::MatchPositions* matches) { | |
| 52 std::sort(matches->begin(), matches->end(), &CompareMatchPosition); | |
| 53 // WARNING: we don't use iterator here as CoalesceMatchesFrom may remove | |
| 54 // from matches. | |
| 55 for (size_t i = 0; i < matches->size(); ++i) | |
| 56 CoalesceMatchesFrom(i, matches); | |
| 57 } | |
| 58 | |
| 59 // Returns true if the character is considered a quote. | 49 // Returns true if the character is considered a quote. |
| 60 bool IsQueryQuote(wchar_t ch) { | 50 bool IsQueryQuote(wchar_t ch) { |
| 61 return ch == '"' || | 51 return ch == '"' || |
| 62 ch == 0xab || // left pointing double angle bracket | 52 ch == 0xab || // left pointing double angle bracket |
| 63 ch == 0xbb || // right pointing double angle bracket | 53 ch == 0xbb || // right pointing double angle bracket |
| 64 ch == 0x201c || // left double quotation mark | 54 ch == 0x201c || // left double quotation mark |
| 65 ch == 0x201d || // right double quotation mark | 55 ch == 0x201d || // right double quotation mark |
| 66 ch == 0x201e; // double low-9 quotation mark | 56 ch == 0x201e; // double low-9 quotation mark |
| 67 } | 57 } |
| 68 | 58 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 81 | 71 |
| 82 const base::string16& word() const { return word_; } | 72 const base::string16& word() const { return word_; } |
| 83 | 73 |
| 84 void set_literal(bool literal) { literal_ = literal; } | 74 void set_literal(bool literal) { literal_ = literal; } |
| 85 | 75 |
| 86 // QueryNode: | 76 // QueryNode: |
| 87 virtual int AppendToSQLiteQuery(base::string16* query) const OVERRIDE; | 77 virtual int AppendToSQLiteQuery(base::string16* query) const OVERRIDE; |
| 88 virtual bool IsWord() const OVERRIDE; | 78 virtual bool IsWord() const OVERRIDE; |
| 89 virtual bool Matches(const base::string16& word, bool exact) const OVERRIDE; | 79 virtual bool Matches(const base::string16& word, bool exact) const OVERRIDE; |
| 90 virtual bool HasMatchIn( | 80 virtual bool HasMatchIn( |
| 91 const std::vector<QueryWord>& words, | 81 const QueryWordVector& words, |
| 92 Snippet::MatchPositions* match_positions) const OVERRIDE; | 82 Snippet::MatchPositions* match_positions) const OVERRIDE; |
| 93 virtual bool HasMatchIn( | 83 virtual bool HasMatchIn( |
| 94 const std::vector<QueryWord>& words) const OVERRIDE; | 84 const QueryWordVector& words) const OVERRIDE; |
| 95 virtual void AppendWords(std::vector<base::string16>* words) const OVERRIDE; | 85 virtual void AppendWords(std::vector<base::string16>* words) const OVERRIDE; |
| 96 | 86 |
| 97 private: | 87 private: |
| 98 base::string16 word_; | 88 base::string16 word_; |
| 99 bool literal_; | 89 bool literal_; |
| 100 | 90 |
| 101 DISALLOW_COPY_AND_ASSIGN(QueryNodeWord); | 91 DISALLOW_COPY_AND_ASSIGN(QueryNodeWord); |
| 102 }; | 92 }; |
| 103 | 93 |
| 104 QueryNodeWord::QueryNodeWord(const base::string16& word) | 94 QueryNodeWord::QueryNodeWord(const base::string16& word) |
| (...skipping 15 matching lines...) Expand all Loading... |
| 120 return true; | 110 return true; |
| 121 } | 111 } |
| 122 | 112 |
| 123 bool QueryNodeWord::Matches(const base::string16& word, bool exact) const { | 113 bool QueryNodeWord::Matches(const base::string16& word, bool exact) const { |
| 124 if (exact || !QueryParser::IsWordLongEnoughForPrefixSearch(word_)) | 114 if (exact || !QueryParser::IsWordLongEnoughForPrefixSearch(word_)) |
| 125 return word == word_; | 115 return word == word_; |
| 126 return word.size() >= word_.size() && | 116 return word.size() >= word_.size() && |
| 127 (word_.compare(0, word_.size(), word, 0, word_.size()) == 0); | 117 (word_.compare(0, word_.size(), word, 0, word_.size()) == 0); |
| 128 } | 118 } |
| 129 | 119 |
| 130 bool QueryNodeWord::HasMatchIn(const std::vector<QueryWord>& words, | 120 bool QueryNodeWord::HasMatchIn(const QueryWordVector& words, |
| 131 Snippet::MatchPositions* match_positions) const { | 121 Snippet::MatchPositions* match_positions) const { |
| 132 bool matched = false; | 122 bool matched = false; |
| 133 for (size_t i = 0; i < words.size(); ++i) { | 123 for (size_t i = 0; i < words.size(); ++i) { |
| 134 if (Matches(words[i].word, false)) { | 124 if (Matches(words[i].word, false)) { |
| 135 size_t match_start = words[i].position; | 125 size_t match_start = words[i].position; |
| 136 match_positions->push_back( | 126 match_positions->push_back( |
| 137 Snippet::MatchPosition(match_start, | 127 Snippet::MatchPosition(match_start, |
| 138 match_start + static_cast<int>(word_.size()))); | 128 match_start + static_cast<int>(word_.size()))); |
| 139 matched = true; | 129 matched = true; |
| 140 } | 130 } |
| 141 } | 131 } |
| 142 return matched; | 132 return matched; |
| 143 } | 133 } |
| 144 | 134 |
| 145 bool QueryNodeWord::HasMatchIn(const std::vector<QueryWord>& words) const { | 135 bool QueryNodeWord::HasMatchIn(const QueryWordVector& words) const { |
| 146 for (size_t i = 0; i < words.size(); ++i) { | 136 for (size_t i = 0; i < words.size(); ++i) { |
| 147 if (Matches(words[i].word, false)) | 137 if (Matches(words[i].word, false)) |
| 148 return true; | 138 return true; |
| 149 } | 139 } |
| 150 return false; | 140 return false; |
| 151 } | 141 } |
| 152 | 142 |
| 153 void QueryNodeWord::AppendWords(std::vector<base::string16>* words) const { | 143 void QueryNodeWord::AppendWords(std::vector<base::string16>* words) const { |
| 154 words->push_back(word_); | 144 words->push_back(word_); |
| 155 } | 145 } |
| 156 | 146 |
| 157 // A QueryNodeList has a collection of QueryNodes which are deleted in the end. | 147 // A QueryNodeList has a collection of QueryNodes which are deleted in the end. |
| 158 class QueryNodeList : public QueryNode { | 148 class QueryNodeList : public QueryNode { |
| 159 public: | 149 public: |
| 160 typedef std::vector<QueryNode*> QueryNodeVector; | |
| 161 | |
| 162 QueryNodeList(); | 150 QueryNodeList(); |
| 163 virtual ~QueryNodeList(); | 151 virtual ~QueryNodeList(); |
| 164 | 152 |
| 165 QueryNodeVector* children() { return &children_; } | 153 QueryNodeStarVector* children() { return &children_; } |
| 166 | 154 |
| 167 void AddChild(QueryNode* node); | 155 void AddChild(QueryNode* node); |
| 168 | 156 |
| 169 // Remove empty subnodes left over from other parsing. | 157 // Remove empty subnodes left over from other parsing. |
| 170 void RemoveEmptySubnodes(); | 158 void RemoveEmptySubnodes(); |
| 171 | 159 |
| 172 // QueryNode: | 160 // QueryNode: |
| 173 virtual int AppendToSQLiteQuery(base::string16* query) const OVERRIDE; | 161 virtual int AppendToSQLiteQuery(base::string16* query) const OVERRIDE; |
| 174 virtual bool IsWord() const OVERRIDE; | 162 virtual bool IsWord() const OVERRIDE; |
| 175 virtual bool Matches(const base::string16& word, bool exact) const OVERRIDE; | 163 virtual bool Matches(const base::string16& word, bool exact) const OVERRIDE; |
| 176 virtual bool HasMatchIn( | 164 virtual bool HasMatchIn( |
| 177 const std::vector<QueryWord>& words, | 165 const QueryWordVector& words, |
| 178 Snippet::MatchPositions* match_positions) const OVERRIDE; | 166 Snippet::MatchPositions* match_positions) const OVERRIDE; |
| 179 virtual bool HasMatchIn( | 167 virtual bool HasMatchIn(const QueryWordVector& words) const OVERRIDE; |
| 180 const std::vector<QueryWord>& words) const OVERRIDE; | |
| 181 virtual void AppendWords(std::vector<base::string16>* words) const OVERRIDE; | 168 virtual void AppendWords(std::vector<base::string16>* words) const OVERRIDE; |
| 182 | 169 |
| 183 protected: | 170 protected: |
| 184 int AppendChildrenToString(base::string16* query) const; | 171 int AppendChildrenToString(base::string16* query) const; |
| 185 | 172 |
| 186 QueryNodeVector children_; | 173 QueryNodeStarVector children_; |
| 187 | 174 |
| 188 private: | 175 private: |
| 189 DISALLOW_COPY_AND_ASSIGN(QueryNodeList); | 176 DISALLOW_COPY_AND_ASSIGN(QueryNodeList); |
| 190 }; | 177 }; |
| 191 | 178 |
| 192 QueryNodeList::QueryNodeList() {} | 179 QueryNodeList::QueryNodeList() {} |
| 193 | 180 |
| 194 QueryNodeList::~QueryNodeList() { | 181 QueryNodeList::~QueryNodeList() { |
| 195 STLDeleteElements(&children_); | 182 STLDeleteElements(&children_); |
| 196 } | 183 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 220 | 207 |
| 221 bool QueryNodeList::IsWord() const { | 208 bool QueryNodeList::IsWord() const { |
| 222 return false; | 209 return false; |
| 223 } | 210 } |
| 224 | 211 |
| 225 bool QueryNodeList::Matches(const base::string16& word, bool exact) const { | 212 bool QueryNodeList::Matches(const base::string16& word, bool exact) const { |
| 226 NOTREACHED(); | 213 NOTREACHED(); |
| 227 return false; | 214 return false; |
| 228 } | 215 } |
| 229 | 216 |
| 230 bool QueryNodeList::HasMatchIn(const std::vector<QueryWord>& words, | 217 bool QueryNodeList::HasMatchIn(const QueryWordVector& words, |
| 231 Snippet::MatchPositions* match_positions) const { | 218 Snippet::MatchPositions* match_positions) const { |
| 232 NOTREACHED(); | 219 NOTREACHED(); |
| 233 return false; | 220 return false; |
| 234 } | 221 } |
| 235 | 222 |
| 236 bool QueryNodeList::HasMatchIn(const std::vector<QueryWord>& words) const { | 223 bool QueryNodeList::HasMatchIn(const QueryWordVector& words) const { |
| 237 NOTREACHED(); | 224 NOTREACHED(); |
| 238 return false; | 225 return false; |
| 239 } | 226 } |
| 240 | 227 |
| 241 void QueryNodeList::AppendWords(std::vector<base::string16>* words) const { | 228 void QueryNodeList::AppendWords(std::vector<base::string16>* words) const { |
| 242 for (size_t i = 0; i < children_.size(); ++i) | 229 for (size_t i = 0; i < children_.size(); ++i) |
| 243 children_[i]->AppendWords(words); | 230 children_[i]->AppendWords(words); |
| 244 } | 231 } |
| 245 | 232 |
| 246 int QueryNodeList::AppendChildrenToString(base::string16* query) const { | 233 int QueryNodeList::AppendChildrenToString(base::string16* query) const { |
| 247 int num_words = 0; | 234 int num_words = 0; |
| 248 for (QueryNodeVector::const_iterator node = children_.begin(); | 235 for (QueryNodeStarVector::const_iterator node = children_.begin(); |
| 249 node != children_.end(); ++node) { | 236 node != children_.end(); ++node) { |
| 250 if (node != children_.begin()) | 237 if (node != children_.begin()) |
| 251 query->push_back(L' '); | 238 query->push_back(L' '); |
| 252 num_words += (*node)->AppendToSQLiteQuery(query); | 239 num_words += (*node)->AppendToSQLiteQuery(query); |
| 253 } | 240 } |
| 254 return num_words; | 241 return num_words; |
| 255 } | 242 } |
| 256 | 243 |
| 257 // A QueryNodePhrase is a phrase query ("quoted"). | 244 // A QueryNodePhrase is a phrase query ("quoted"). |
| 258 class QueryNodePhrase : public QueryNodeList { | 245 class QueryNodePhrase : public QueryNodeList { |
| 259 public: | 246 public: |
| 260 QueryNodePhrase(); | 247 QueryNodePhrase(); |
| 261 virtual ~QueryNodePhrase(); | 248 virtual ~QueryNodePhrase(); |
| 262 | 249 |
| 263 // QueryNodeList: | 250 // QueryNodeList: |
| 264 virtual int AppendToSQLiteQuery(base::string16* query) const OVERRIDE; | 251 virtual int AppendToSQLiteQuery(base::string16* query) const OVERRIDE; |
| 265 virtual bool HasMatchIn( | 252 virtual bool HasMatchIn( |
| 266 const std::vector<QueryWord>& words, | 253 const QueryWordVector& words, |
| 267 Snippet::MatchPositions* match_positions) const OVERRIDE; | 254 Snippet::MatchPositions* match_positions) const OVERRIDE; |
| 268 virtual bool HasMatchIn( | 255 virtual bool HasMatchIn(const QueryWordVector& words) const OVERRIDE; |
| 269 const std::vector<QueryWord>& words) const OVERRIDE; | |
| 270 | 256 |
| 271 private: | 257 private: |
| 272 bool MatchesAll(const std::vector<QueryWord>& words, | 258 bool MatchesAll(const QueryWordVector& words, |
| 273 const QueryWord** first_word, | 259 const QueryWord** first_word, |
| 274 const QueryWord** last_word) const; | 260 const QueryWord** last_word) const; |
| 275 DISALLOW_COPY_AND_ASSIGN(QueryNodePhrase); | 261 DISALLOW_COPY_AND_ASSIGN(QueryNodePhrase); |
| 276 }; | 262 }; |
| 277 | 263 |
| 278 QueryNodePhrase::QueryNodePhrase() {} | 264 QueryNodePhrase::QueryNodePhrase() {} |
| 279 | 265 |
| 280 QueryNodePhrase::~QueryNodePhrase() {} | 266 QueryNodePhrase::~QueryNodePhrase() {} |
| 281 | 267 |
| 282 int QueryNodePhrase::AppendToSQLiteQuery(base::string16* query) const { | 268 int QueryNodePhrase::AppendToSQLiteQuery(base::string16* query) const { |
| 283 query->push_back(L'"'); | 269 query->push_back(L'"'); |
| 284 int num_words = AppendChildrenToString(query); | 270 int num_words = AppendChildrenToString(query); |
| 285 query->push_back(L'"'); | 271 query->push_back(L'"'); |
| 286 return num_words; | 272 return num_words; |
| 287 } | 273 } |
| 288 | 274 |
| 289 bool QueryNodePhrase::MatchesAll(const std::vector<QueryWord>& words, | 275 bool QueryNodePhrase::MatchesAll(const QueryWordVector& words, |
| 290 const QueryWord** first_word, | 276 const QueryWord** first_word, |
| 291 const QueryWord** last_word) const { | 277 const QueryWord** last_word) const { |
| 292 if (words.size() < children_.size()) | 278 if (words.size() < children_.size()) |
| 293 return false; | 279 return false; |
| 294 | 280 |
| 295 for (size_t i = 0, max = words.size() - children_.size() + 1; i < max; ++i) { | 281 for (size_t i = 0, max = words.size() - children_.size() + 1; i < max; ++i) { |
| 296 bool matched_all = true; | 282 bool matched_all = true; |
| 297 for (size_t j = 0; j < children_.size(); ++j) { | 283 for (size_t j = 0; j < children_.size(); ++j) { |
| 298 if (!children_[j]->Matches(words[i + j].word, true)) { | 284 if (!children_[j]->Matches(words[i + j].word, true)) { |
| 299 matched_all = false; | 285 matched_all = false; |
| 300 break; | 286 break; |
| 301 } | 287 } |
| 302 } | 288 } |
| 303 if (matched_all) { | 289 if (matched_all) { |
| 304 *first_word = &words[i]; | 290 *first_word = &words[i]; |
| 305 *last_word = &words[i + children_.size() - 1]; | 291 *last_word = &words[i + children_.size() - 1]; |
| 306 return true; | 292 return true; |
| 307 } | 293 } |
| 308 } | 294 } |
| 309 return false; | 295 return false; |
| 310 } | 296 } |
| 311 | 297 |
| 312 bool QueryNodePhrase::HasMatchIn( | 298 bool QueryNodePhrase::HasMatchIn( |
| 313 const std::vector<QueryWord>& words, | 299 const QueryWordVector& words, |
| 314 Snippet::MatchPositions* match_positions) const { | 300 Snippet::MatchPositions* match_positions) const { |
| 315 const QueryWord* first_word; | 301 const QueryWord* first_word; |
| 316 const QueryWord* last_word; | 302 const QueryWord* last_word; |
| 317 | 303 |
| 318 if (MatchesAll(words, &first_word, &last_word)) { | 304 if (MatchesAll(words, &first_word, &last_word)) { |
| 319 match_positions->push_back( | 305 match_positions->push_back( |
| 320 Snippet::MatchPosition(first_word->position, | 306 Snippet::MatchPosition(first_word->position, |
| 321 last_word->position + last_word->word.length())); | 307 last_word->position + last_word->word.length())); |
| 322 return true; | 308 return true; |
| 323 } | 309 } |
| 324 return false; | 310 return false; |
| 325 } | 311 } |
| 326 | 312 |
| 327 bool QueryNodePhrase::HasMatchIn(const std::vector<QueryWord>& words) const { | 313 bool QueryNodePhrase::HasMatchIn(const QueryWordVector& words) const { |
| 328 const QueryWord* first_word; | 314 const QueryWord* first_word; |
| 329 const QueryWord* last_word; | 315 const QueryWord* last_word; |
| 330 return MatchesAll(words, &first_word, &last_word); | 316 return MatchesAll(words, &first_word, &last_word); |
| 331 } | 317 } |
| 332 | 318 |
| 333 QueryParser::QueryParser() {} | 319 QueryParser::QueryParser() {} |
| 334 | 320 |
| 335 // static | 321 // static |
| 336 bool QueryParser::IsWordLongEnoughForPrefixSearch(const base::string16& word) { | 322 bool QueryParser::IsWordLongEnoughForPrefixSearch(const base::string16& word) { |
| 337 DCHECK(!word.empty()); | 323 DCHECK(!word.empty()); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 354 | 340 |
| 355 void QueryParser::ParseQueryWords(const base::string16& query, | 341 void QueryParser::ParseQueryWords(const base::string16& query, |
| 356 std::vector<base::string16>* words) { | 342 std::vector<base::string16>* words) { |
| 357 QueryNodeList root; | 343 QueryNodeList root; |
| 358 if (!ParseQueryImpl(query, &root)) | 344 if (!ParseQueryImpl(query, &root)) |
| 359 return; | 345 return; |
| 360 root.AppendWords(words); | 346 root.AppendWords(words); |
| 361 } | 347 } |
| 362 | 348 |
| 363 void QueryParser::ParseQueryNodes(const base::string16& query, | 349 void QueryParser::ParseQueryNodes(const base::string16& query, |
| 364 std::vector<QueryNode*>* nodes) { | 350 QueryNodeStarVector* nodes) { |
| 365 QueryNodeList root; | 351 QueryNodeList root; |
| 366 if (ParseQueryImpl(base::i18n::ToLower(query), &root)) | 352 if (ParseQueryImpl(base::i18n::ToLower(query), &root)) |
| 367 nodes->swap(*root.children()); | 353 nodes->swap(*root.children()); |
| 368 } | 354 } |
| 369 | 355 |
| 370 bool QueryParser::DoesQueryMatch(const base::string16& text, | 356 bool QueryParser::DoesQueryMatch(const base::string16& text, |
| 371 const std::vector<QueryNode*>& query_nodes, | 357 const QueryNodeStarVector& query_nodes, |
| 372 Snippet::MatchPositions* match_positions) { | 358 Snippet::MatchPositions* match_positions) { |
| 373 if (query_nodes.empty()) | 359 if (query_nodes.empty()) |
| 374 return false; | 360 return false; |
| 375 | 361 |
| 376 std::vector<QueryWord> query_words; | 362 QueryWordVector query_words; |
| 377 base::string16 lower_text = base::i18n::ToLower(text); | 363 base::string16 lower_text = base::i18n::ToLower(text); |
| 378 ExtractQueryWords(lower_text, &query_words); | 364 ExtractQueryWords(lower_text, &query_words); |
| 379 | 365 |
| 380 if (query_words.empty()) | 366 if (query_words.empty()) |
| 381 return false; | 367 return false; |
| 382 | 368 |
| 383 Snippet::MatchPositions matches; | 369 Snippet::MatchPositions matches; |
| 384 for (size_t i = 0; i < query_nodes.size(); ++i) { | 370 for (size_t i = 0; i < query_nodes.size(); ++i) { |
| 385 if (!query_nodes[i]->HasMatchIn(query_words, &matches)) | 371 if (!query_nodes[i]->HasMatchIn(query_words, &matches)) |
| 386 return false; | 372 return false; |
| 387 } | 373 } |
| 388 if (lower_text.length() != text.length()) { | 374 if (lower_text.length() != text.length()) { |
| 389 // The lower case string differs from the original string. The matches are | 375 // The lower case string differs from the original string. The matches are |
| 390 // meaningless. | 376 // meaningless. |
| 391 // TODO(sky): we need a better way to align the positions so that we don't | 377 // TODO(sky): we need a better way to align the positions so that we don't |
| 392 // completely punt here. | 378 // completely punt here. |
| 393 match_positions->clear(); | 379 match_positions->clear(); |
| 394 } else { | 380 } else { |
| 395 CoalseAndSortMatchPositions(&matches); | 381 SortAndCoalesceMatchPositions(&matches); |
| 396 match_positions->swap(matches); | 382 match_positions->swap(matches); |
| 397 } | 383 } |
| 398 return true; | 384 return true; |
| 399 } | 385 } |
| 400 | 386 |
| 401 bool QueryParser::DoesQueryMatch(const std::vector<QueryWord>& query_words, | 387 bool QueryParser::DoesQueryMatch(const QueryWordVector& query_words, |
| 402 const std::vector<QueryNode*>& query_nodes) { | 388 const QueryNodeStarVector& query_nodes) { |
| 403 if (query_nodes.empty() || query_words.empty()) | 389 if (query_nodes.empty() || query_words.empty()) |
| 404 return false; | 390 return false; |
| 405 | 391 |
| 406 for (size_t i = 0; i < query_nodes.size(); ++i) { | 392 for (size_t i = 0; i < query_nodes.size(); ++i) { |
| 407 if (!query_nodes[i]->HasMatchIn(query_words)) | 393 if (!query_nodes[i]->HasMatchIn(query_words)) |
| 408 return false; | 394 return false; |
| 409 } | 395 } |
| 410 return true; | 396 return true; |
| 411 } | 397 } |
| 412 | 398 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 445 } | 431 } |
| 446 } | 432 } |
| 447 } | 433 } |
| 448 } | 434 } |
| 449 | 435 |
| 450 root->RemoveEmptySubnodes(); | 436 root->RemoveEmptySubnodes(); |
| 451 return true; | 437 return true; |
| 452 } | 438 } |
| 453 | 439 |
| 454 void QueryParser::ExtractQueryWords(const base::string16& text, | 440 void QueryParser::ExtractQueryWords(const base::string16& text, |
| 455 std::vector<QueryWord>* words) { | 441 QueryWordVector* words) { |
| 456 base::i18n::BreakIterator iter(text, base::i18n::BreakIterator::BREAK_WORD); | 442 base::i18n::BreakIterator iter(text, base::i18n::BreakIterator::BREAK_WORD); |
| 457 // TODO(evanm): support a locale here | 443 // TODO(evanm): support a locale here |
| 458 if (!iter.Init()) | 444 if (!iter.Init()) |
| 459 return; | 445 return; |
| 460 | 446 |
| 461 while (iter.Advance()) { | 447 while (iter.Advance()) { |
| 462 // Just found a span between 'prev' (inclusive) and 'pos' (exclusive). It | 448 // Just found a span between 'prev' (inclusive) and 'pos' (exclusive). It |
| 463 // is not necessarily a word, but could also be a sequence of punctuation | 449 // is not necessarily a word, but could also be a sequence of punctuation |
| 464 // or whitespace. | 450 // or whitespace. |
| 465 if (iter.IsWord()) { | 451 if (iter.IsWord()) { |
| 466 base::string16 word = iter.GetString(); | 452 base::string16 word = iter.GetString(); |
| 467 if (!word.empty()) { | 453 if (!word.empty()) { |
| 468 words->push_back(QueryWord()); | 454 words->push_back(QueryWord()); |
| 469 words->back().word = word; | 455 words->back().word = word; |
| 470 words->back().position = iter.prev(); | 456 words->back().position = iter.prev(); |
| 471 } | 457 } |
| 472 } | 458 } |
| 473 } | 459 } |
| 474 } | 460 } |
| 475 | 461 |
| 462 // static |
| 463 void QueryParser::SortAndCoalesceMatchPositions( |
| 464 Snippet::MatchPositions* matches) { |
| 465 std::sort(matches->begin(), matches->end(), &CompareMatchPosition); |
| 466 // WARNING: we don't use iterator here as CoalesceMatchesFrom may remove |
| 467 // from matches. |
| 468 for (size_t i = 0; i < matches->size(); ++i) |
| 469 CoalesceMatchesFrom(i, matches); |
| 470 } |
| 471 |
| 476 } // namespace query_parser | 472 } // namespace query_parser |
| OLD | NEW |