OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "sync/syncable/parent_child_index.h" |
| 6 |
| 7 #include "base/stl_util.h" |
| 8 |
| 9 #include "sync/syncable/entry_kernel.h" |
| 10 #include "sync/syncable/syncable_id.h" |
| 11 |
| 12 namespace syncer { |
| 13 namespace syncable { |
| 14 |
| 15 bool ChildComparator::operator()( |
| 16 const syncable::EntryKernel* a, |
| 17 const syncable::EntryKernel* b) const { |
| 18 const UniquePosition& a_pos = a->ref(UNIQUE_POSITION); |
| 19 const UniquePosition& b_pos = b->ref(UNIQUE_POSITION); |
| 20 |
| 21 if (a_pos.IsValid() && b_pos.IsValid()) { |
| 22 // Position is important to this type. |
| 23 return a_pos.LessThan(b_pos); |
| 24 } else if (a_pos.IsValid() && !b_pos.IsValid()) { |
| 25 // TODO(rlarocque): Remove these cases. |
| 26 // An item with valid position as sibling of one with invalid position. |
| 27 // We should not suppport this, but the tests rely on it. For now, just |
| 28 // move all invalid position items to the right. |
| 29 return true; |
| 30 } else if (!a_pos.IsValid() && b_pos.IsValid()) { |
| 31 // Mirror of the above case. |
| 32 return false; |
| 33 } else { |
| 34 // Position doesn't matter. |
| 35 DCHECK(!a->ref(UNIQUE_POSITION).IsValid()); |
| 36 DCHECK(!b->ref(UNIQUE_POSITION).IsValid()); |
| 37 return a->ref(ID) < b->ref(ID); |
| 38 } |
| 39 } |
| 40 |
| 41 ParentChildIndex::ParentChildIndex() { |
| 42 } |
| 43 |
| 44 ParentChildIndex::~ParentChildIndex() { |
| 45 STLDeleteContainerPairSecondPointers( |
| 46 parent_children_map_.begin(), parent_children_map_.end()); |
| 47 } |
| 48 |
| 49 bool ParentChildIndex::ShouldInclude(const EntryKernel* entry) { |
| 50 // This index excludes deleted items and the root item. The root |
| 51 // item is excluded so that it doesn't show up as a child of itself. |
| 52 return !entry->ref(IS_DEL) && !entry->ref(ID).IsRoot(); |
| 53 } |
| 54 |
| 55 bool ParentChildIndex::Insert(EntryKernel* entry) { |
| 56 DCHECK(ShouldInclude(entry)); |
| 57 |
| 58 const syncable::Id& parent_id = entry->ref(PARENT_ID); |
| 59 ChildSet* children = NULL; |
| 60 ParentChildrenMap::iterator i = parent_children_map_.find(parent_id); |
| 61 if (i != parent_children_map_.end()) { |
| 62 children = i->second; |
| 63 } else { |
| 64 children = new ChildSet(); |
| 65 parent_children_map_.insert(std::make_pair(parent_id, children)); |
| 66 } |
| 67 |
| 68 return children->insert(entry).second; |
| 69 } |
| 70 |
| 71 void ParentChildIndex::Remove(EntryKernel* e) { |
| 72 ParentChildrenMap::iterator i = parent_children_map_.find(e->ref(PARENT_ID)); |
| 73 DCHECK(i != parent_children_map_.end()); |
| 74 |
| 75 ChildSet* children = i->second; |
| 76 ChildSet::iterator j = children->find(e); |
| 77 DCHECK(j != children->end()); |
| 78 |
| 79 children->erase(j); |
| 80 if (children->empty()) { |
| 81 delete children; |
| 82 parent_children_map_.erase(i); |
| 83 } |
| 84 } |
| 85 |
| 86 bool ParentChildIndex::Contains(EntryKernel *e) const { |
| 87 const syncable::Id& parent_id = e->ref(PARENT_ID); |
| 88 ParentChildrenMap::const_iterator i = parent_children_map_.find(parent_id); |
| 89 if (i == parent_children_map_.end()) { |
| 90 return false; |
| 91 } |
| 92 const ChildSet* children = i->second; |
| 93 DCHECK(children && !children->empty()); |
| 94 return children->count(e) > 0; |
| 95 } |
| 96 |
| 97 const ChildSet* ParentChildIndex::GetChildren(const syncable::Id& id) { |
| 98 ParentChildrenMap::iterator i = parent_children_map_.find(id); |
| 99 if (i == parent_children_map_.end()) { |
| 100 return NULL; |
| 101 } |
| 102 |
| 103 // A successful lookup implies at least some children exist. |
| 104 DCHECK(!i->second->empty()); |
| 105 return i->second; |
| 106 } |
| 107 |
| 108 } // namespace syncable |
| 109 } // namespace syncer |
OLD | NEW |