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.
5 #include "sync/syncable/parent_child_index.h"
7 #include "base/stl_util.h"
9 #include "sync/syncable/entry_kernel.h"
10 #include "sync/syncable/syncable_id.h"
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
);
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 this case.
26 // An item with valid position as sibling of one with invalid position.
27 // We should not support this, but the tests rely on it. For now, just
28 // move all invalid position items to the right.
30 } else if (!a_pos
.IsValid() && b_pos
.IsValid()) {
31 // TODO(rlarocque): Remove this case.
32 // Mirror of the above case.
35 // Position doesn't matter.
36 DCHECK(!a
->ref(UNIQUE_POSITION
).IsValid());
37 DCHECK(!b
->ref(UNIQUE_POSITION
).IsValid());
38 return a
->ref(ID
) < b
->ref(ID
);
42 ParentChildIndex::ParentChildIndex() {
45 ParentChildIndex::~ParentChildIndex() {
46 STLDeleteContainerPairSecondPointers(
47 parent_children_map_
.begin(), parent_children_map_
.end());
50 bool ParentChildIndex::ShouldInclude(const EntryKernel
* entry
) {
51 // This index excludes deleted items and the root item. The root
52 // item is excluded so that it doesn't show up as a child of itself.
53 return !entry
->ref(IS_DEL
) && !entry
->ref(ID
).IsRoot();
56 bool ParentChildIndex::Insert(EntryKernel
* entry
) {
57 DCHECK(ShouldInclude(entry
));
59 const syncable::Id
& parent_id
= entry
->ref(PARENT_ID
);
60 OrderedChildSet
* children
= NULL
;
61 ParentChildrenMap::iterator i
= parent_children_map_
.find(parent_id
);
62 if (i
!= parent_children_map_
.end()) {
65 children
= new OrderedChildSet();
66 parent_children_map_
.insert(std::make_pair(parent_id
, children
));
69 return children
->insert(entry
).second
;
72 // Like the other containers used to help support the syncable::Directory, this
73 // one does not own any EntryKernels. This function removes references to the
74 // given EntryKernel but does not delete it.
75 void ParentChildIndex::Remove(EntryKernel
* e
) {
76 ParentChildrenMap::iterator parent
=
77 parent_children_map_
.find(e
->ref(PARENT_ID
));
78 DCHECK(parent
!= parent_children_map_
.end());
80 OrderedChildSet
* children
= parent
->second
;
81 OrderedChildSet::iterator j
= children
->find(e
);
82 DCHECK(j
!= children
->end());
85 if (children
->empty()) {
87 parent_children_map_
.erase(parent
);
91 bool ParentChildIndex::Contains(EntryKernel
*e
) const {
92 const syncable::Id
& parent_id
= e
->ref(PARENT_ID
);
93 ParentChildrenMap::const_iterator parent
=
94 parent_children_map_
.find(parent_id
);
95 if (parent
== parent_children_map_
.end()) {
98 const OrderedChildSet
* children
= parent
->second
;
99 DCHECK(children
&& !children
->empty());
100 return children
->count(e
) > 0;
103 const OrderedChildSet
* ParentChildIndex::GetChildren(const syncable::Id
& id
) {
104 ParentChildrenMap::iterator parent
= parent_children_map_
.find(id
);
105 if (parent
== parent_children_map_
.end()) {
109 // A successful lookup implies at least some children exist.
110 DCHECK(!parent
->second
->empty());
111 return parent
->second
;
114 } // namespace syncable
115 } // namespace syncer