Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(64)

Side by Side Diff: chrome/browser/history/query_parser.cc

Issue 9316129: Don't strip punctuation inside quotes in history search queries. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Add unit tests to verify fix. Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | chrome/browser/history/text_database_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "chrome/browser/history/query_parser.h" 5 #include "chrome/browser/history/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 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 73
74 // A QueryNodeWord is a single word in the query. 74 // A QueryNodeWord is a single word in the query.
75 class QueryNodeWord : public QueryNode { 75 class QueryNodeWord : public QueryNode {
76 public: 76 public:
77 explicit QueryNodeWord(const string16& word); 77 explicit QueryNodeWord(const string16& word);
78 virtual ~QueryNodeWord(); 78 virtual ~QueryNodeWord();
79 79
80 const string16& word() const { return word_; } 80 const string16& word() const { return word_; }
81 81
82 void set_literal(bool literal) { literal_ = literal; } 82 void set_literal(bool literal) { literal_ = literal; }
83 void AppendText(const string16& text) { word_ += text; }
mrossetti 2012/02/07 01:05:57 We generally only inline simple getters and setter
83 84
84 // QueryNode: 85 // QueryNode:
85 virtual int AppendToSQLiteQuery(string16* query) const OVERRIDE; 86 virtual int AppendToSQLiteQuery(string16* query) const OVERRIDE;
86 virtual bool IsWord() const OVERRIDE; 87 virtual bool IsWord() const OVERRIDE;
87 virtual bool Matches(const string16& word, bool exact) const OVERRIDE; 88 virtual bool Matches(const string16& word, bool exact) const OVERRIDE;
88 virtual bool HasMatchIn( 89 virtual bool HasMatchIn(
89 const std::vector<QueryWord>& words, 90 const std::vector<QueryWord>& words,
90 Snippet::MatchPositions* match_positions) const OVERRIDE; 91 Snippet::MatchPositions* match_positions) const OVERRIDE;
91 virtual void AppendWords(std::vector<string16>* words) const OVERRIDE; 92 virtual void AppendWords(std::vector<string16>* words) const OVERRIDE;
92 93
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
358 // TODO(evanm): support a locale here 359 // TODO(evanm): support a locale here
359 if (!iter.Init()) 360 if (!iter.Init())
360 return false; 361 return false;
361 362
362 // To handle nesting, we maintain a stack of QueryNodeLists. 363 // To handle nesting, we maintain a stack of QueryNodeLists.
363 // The last element (back) of the stack contains the current, deepest node. 364 // The last element (back) of the stack contains the current, deepest node.
364 std::vector<QueryNodeList*> query_stack; 365 std::vector<QueryNodeList*> query_stack;
365 query_stack.push_back(root); 366 query_stack.push_back(root);
366 367
367 bool in_quotes = false; // whether we're currently in a quoted phrase 368 bool in_quotes = false; // whether we're currently in a quoted phrase
369 QueryNodeWord* current_word = NULL;
368 while (iter.Advance()) { 370 while (iter.Advance()) {
369 // Just found a span between 'prev' (inclusive) and 'pos' (exclusive). It 371 // Just found a span between 'prev' (inclusive) and 'pos' (exclusive). It
370 // is not necessarily a word, but could also be a sequence of punctuation 372 // is not necessarily a word, but could also be a sequence of punctuation
371 // or whitespace. 373 // or whitespace.
372 if (iter.IsWord()) { 374 if (IsQueryQuote(query[iter.prev()])) {
373 QueryNodeWord* word_node = new QueryNodeWord(iter.GetString()); 375 if (!in_quotes) {
376 QueryNodeList* quotes_node = new QueryNodePhrase;
377 query_stack.back()->AddChild(quotes_node);
378 query_stack.push_back(quotes_node);
379 in_quotes = true;
380 } else {
381 query_stack.pop_back(); // Stop adding to the quoted phrase.
382 in_quotes = false;
383 }
384 current_word = NULL;
385 } else if (iter.IsWord() || in_quotes) {
mrossetti 2012/02/07 01:05:57 Okay, as you can see from the unit tests, trying t
386 if (current_word) {
387 current_word->AppendText(iter.GetString());
388 } else {
389 current_word = new QueryNodeWord(iter.GetString());
390 query_stack.back()->AddChild(current_word);
mrossetti 2012/02/07 01:05:57 Do the set_literal here...
391 }
374 if (in_quotes) 392 if (in_quotes)
mrossetti 2012/02/07 01:05:57 ...not here.
375 word_node->set_literal(true); 393 current_word->set_literal(true);
376 query_stack.back()->AddChild(word_node); 394 } else { // Punctuation or whitespace outside quotes.
mrossetti 2012/02/07 01:05:57 These empty braces are just screaming for somethin
377 } else { // Punctuation.
378 if (IsQueryQuote(query[iter.prev()])) {
379 if (!in_quotes) {
380 QueryNodeList* quotes_node = new QueryNodePhrase;
381 query_stack.back()->AddChild(quotes_node);
382 query_stack.push_back(quotes_node);
383 in_quotes = true;
384 } else {
385 query_stack.pop_back(); // Stop adding to the quoted phrase.
386 in_quotes = false;
387 }
388 }
389 } 395 }
390 } 396 }
391 397
392 root->RemoveEmptySubnodes(); 398 root->RemoveEmptySubnodes();
393 return true; 399 return true;
394 } 400 }
395 401
396 void QueryParser::ExtractQueryWords(const string16& text, 402 void QueryParser::ExtractQueryWords(const string16& text,
397 std::vector<QueryWord>* words) { 403 std::vector<QueryWord>* words) {
398 base::i18n::BreakIterator iter(text, base::i18n::BreakIterator::BREAK_WORD); 404 base::i18n::BreakIterator iter(text, base::i18n::BreakIterator::BREAK_WORD);
399 // TODO(evanm): support a locale here 405 // TODO(evanm): support a locale here
400 if (!iter.Init()) 406 if (!iter.Init())
401 return; 407 return;
402 408
403 while (iter.Advance()) { 409 while (iter.Advance()) {
404 // Just found a span between 'prev' (inclusive) and 'pos' (exclusive). It 410 // Just found a span between 'prev' (inclusive) and 'pos' (exclusive). It
405 // is not necessarily a word, but could also be a sequence of punctuation 411 // is not necessarily a word, but could also be a sequence of punctuation
406 // or whitespace. 412 // or whitespace.
407 if (iter.IsWord()) { 413 if (iter.IsWord()) {
408 string16 word = iter.GetString(); 414 string16 word = iter.GetString();
409 if (!word.empty()) { 415 if (!word.empty()) {
410 words->push_back(QueryWord()); 416 words->push_back(QueryWord());
411 words->back().word = word; 417 words->back().word = word;
412 words->back().position = iter.prev(); 418 words->back().position = iter.prev();
413 } 419 }
414 } 420 }
415 } 421 }
416 } 422 }
OLDNEW
« no previous file with comments | « no previous file | chrome/browser/history/text_database_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698