Index: components/bookmarks/browser/bookmark_index.cc |
diff --git a/components/bookmarks/browser/bookmark_index.cc b/components/bookmarks/browser/bookmark_index.cc |
index d76019d290ce9e9e6fefe86524a560d30fc76191..1651b5f16363ccc38d2d1c8b71924688ffaef133 100644 |
--- a/components/bookmarks/browser/bookmark_index.cc |
+++ b/components/bookmarks/browser/bookmark_index.cc |
@@ -62,40 +62,6 @@ struct NodeTypedCountPairExtractNodeFunctor |
} // namespace |
-// Used when finding the set of bookmarks that match a query. Each match |
-// represents a set of terms (as an interator into the Index) matching the |
-// query as well as the set of nodes that contain those terms in their titles. |
-struct BookmarkIndex::Match { |
- // List of terms matching the query. |
- std::list<Index::const_iterator> terms; |
- |
- // The set of nodes matching the terms. As an optimization this is empty |
- // when we match only one term, and is filled in when we get more than one |
- // term. We can do this as when we have only one matching term we know |
- // the set of matching nodes is terms.front()->second. |
- // |
- // Use nodes_begin() and nodes_end() to get an iterator over the set as |
- // it handles the necessary switching between nodes and terms.front(). |
- NodeSet nodes; |
- |
- // Returns an iterator to the beginning of the matching nodes. See |
- // description of nodes for why this should be used over nodes.begin(). |
- NodeSet::const_iterator nodes_begin() const; |
- |
- // Returns an iterator to the beginning of the matching nodes. See |
- // description of nodes for why this should be used over nodes.end(). |
- NodeSet::const_iterator nodes_end() const; |
-}; |
- |
-BookmarkIndex::NodeSet::const_iterator |
- BookmarkIndex::Match::nodes_begin() const { |
- return nodes.empty() ? terms.front()->second.begin() : nodes.begin(); |
-} |
- |
-BookmarkIndex::NodeSet::const_iterator BookmarkIndex::Match::nodes_end() const { |
- return nodes.empty() ? terms.front()->second.end() : nodes.end(); |
-} |
- |
BookmarkIndex::BookmarkIndex(BookmarkClient* client, |
const std::string& languages) |
: client_(client), |
@@ -143,7 +109,7 @@ void BookmarkIndex::GetBookmarksMatching( |
if (terms.empty()) |
return; |
- Matches matches; |
+ NodeSet matches; |
for (size_t i = 0; i < terms.size(); ++i) { |
if (!GetBookmarksMatchingTerm( |
terms[i], i == 0, matching_algorithm, &matches)) { |
@@ -172,23 +138,12 @@ void BookmarkIndex::GetBookmarksMatching( |
AddMatchToResults(*i, &parser, query_nodes.get(), results); |
} |
-void BookmarkIndex::SortMatches(const Matches& matches, |
+void BookmarkIndex::SortMatches(const NodeSet& matches, |
Nodes* sorted_nodes) const { |
- NodeSet nodes; |
- for (Matches::const_iterator i = matches.begin(); i != matches.end(); ++i) { |
-#if !defined(OS_ANDROID) |
- nodes.insert(i->nodes_begin(), i->nodes_end()); |
-#else |
- // Work around a bug in the implementation of std::set::insert in the STL |
- // used on android (http://crbug.com/367050). |
- for (NodeSet::const_iterator n = i->nodes_begin(); n != i->nodes_end(); ++n) |
- nodes.insert(nodes.end(), *n); |
-#endif |
- } |
- sorted_nodes->reserve(sorted_nodes->size() + nodes.size()); |
+ sorted_nodes->reserve(matches.size()); |
if (client_->SupportsTypedCountForNodes()) { |
NodeTypedCountPairs node_typed_counts; |
- client_->GetTypedCountForNodes(nodes, &node_typed_counts); |
+ client_->GetTypedCountForNodes(matches, &node_typed_counts); |
std::sort(node_typed_counts.begin(), |
node_typed_counts.end(), |
NodeTypedCountPairSortFunctor()); |
@@ -197,7 +152,7 @@ void BookmarkIndex::SortMatches(const Matches& matches, |
std::back_inserter(*sorted_nodes), |
NodeTypedCountPairExtractNodeFunctor()); |
} else { |
- sorted_nodes->insert(sorted_nodes->end(), nodes.begin(), nodes.end()); |
+ sorted_nodes->insert(sorted_nodes->end(), matches.begin(), matches.end()); |
} |
} |
@@ -254,7 +209,7 @@ bool BookmarkIndex::GetBookmarksMatchingTerm( |
const base::string16& term, |
bool first_term, |
query_parser::MatchingAlgorithm matching_algorithm, |
- Matches* matches) { |
+ NodeSet* matches) { |
Index::const_iterator i = index_.lower_bound(term); |
if (i == index_.end()) |
return false; |
@@ -266,72 +221,44 @@ bool BookmarkIndex::GetBookmarksMatchingTerm( |
return false; // No bookmarks with this term. |
if (first_term) { |
- Match match; |
- match.terms.push_back(i); |
- matches->push_back(match); |
+ (*matches) = i->second; |
return true; |
} |
- CombineMatchesInPlace(i, matches); |
- } else if (first_term) { |
- // This is the first term and we're doing a prefix match. Loop through |
- // index adding all entries that start with term to matches. |
- while (i != index_.end() && |
- i->first.size() >= term.size() && |
- term.compare(0, term.size(), i->first, 0, term.size()) == 0) { |
- Match match; |
- match.terms.push_back(i); |
- matches->push_back(match); |
- ++i; |
- } |
+ CombineMatchesInPlace(i->second, matches); |
Peter Kasting
2015/01/28 01:59:40
Is the efficiency gain of this function important,
Mark P
2015/01/28 18:35:10
I don't know anything about the efficiency gain; I
|
} else { |
- // Prefix match and not the first term. Loop through index combining |
- // current matches in matches with term, placing result in result. |
- Matches result; |
+ // Loop through index adding all entries that start with term to |
+ // |prefix_matches|. |
+ NodeSet tmp_prefix_matches; |
+ NodeSet* prefix_matches = &tmp_prefix_matches; |
+ // If this is the first term, then store the result directly in |matches| |
+ // to avoid calls to CombineMatchesInPlace (which does a copy). |
+ if (first_term) |
+ prefix_matches = matches; |
Peter Kasting
2015/01/28 01:59:40
Nit:
NodeSet* prefix_matches = first_term ? m
Mark P
2015/01/28 18:35:10
Done.
|
while (i != index_.end() && |
i->first.size() >= term.size() && |
term.compare(0, term.size(), i->first, 0, term.size()) == 0) { |
- CombineMatches(i, *matches, &result); |
+ prefix_matches->insert(i->second.begin(), i->second.end()); |
++i; |
} |
- matches->swap(result); |
+ if (!first_term) |
+ CombineMatchesInPlace(*prefix_matches, matches); |
} |
return !matches->empty(); |
} |
-void BookmarkIndex::CombineMatchesInPlace(const Index::const_iterator& index_i, |
- Matches* matches) { |
- for (size_t i = 0; i < matches->size(); ) { |
- Match* match = &((*matches)[i]); |
- NodeSet intersection; |
- std::set_intersection(match->nodes_begin(), match->nodes_end(), |
- index_i->second.begin(), index_i->second.end(), |
- std::inserter(intersection, intersection.begin())); |
- if (intersection.empty()) { |
- matches->erase(matches->begin() + i); |
- } else { |
- match->terms.push_back(index_i); |
- match->nodes.swap(intersection); |
- ++i; |
- } |
- } |
-} |
- |
-void BookmarkIndex::CombineMatches(const Index::const_iterator& index_i, |
- const Matches& current_matches, |
- Matches* result) { |
- for (size_t i = 0; i < current_matches.size(); ++i) { |
- const Match& match = current_matches[i]; |
- NodeSet intersection; |
- std::set_intersection(match.nodes_begin(), match.nodes_end(), |
- index_i->second.begin(), index_i->second.end(), |
- std::inserter(intersection, intersection.begin())); |
- if (!intersection.empty()) { |
- result->push_back(Match()); |
- Match& combined_match = result->back(); |
- combined_match.terms = match.terms; |
- combined_match.terms.push_back(index_i); |
- combined_match.nodes.swap(intersection); |
- } |
+void BookmarkIndex::CombineMatchesInPlace(const NodeSet& matches_to_incorporate, |
+ NodeSet* matches) { |
+ NodeSet intersection; |
+ std::set_intersection(matches->begin(), |
+ matches->end(), |
+ matches_to_incorporate.begin(), |
+ matches_to_incorporate.end(), |
+ std::inserter(intersection, intersection.begin())); |
+ if (intersection.empty()) { |
+ // In case of an empty intersection, skip the swap() for efficiency. |
Peter Kasting
2015/01/28 01:59:40
Nit: Can move this above conditional and eliminate
Mark P
2015/01/28 18:35:10
Now obsolete.
|
+ matches->clear(); |
+ } else { |
+ matches->swap(intersection); |
} |
} |