| Index: sync/syncable/parent_child_index.cc
|
| diff --git a/sync/syncable/parent_child_index.cc b/sync/syncable/parent_child_index.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..c544264d850bdba7570a2780b91347369e6e278a
|
| --- /dev/null
|
| +++ b/sync/syncable/parent_child_index.cc
|
| @@ -0,0 +1,109 @@
|
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "sync/syncable/parent_child_index.h"
|
| +
|
| +#include "base/stl_util.h"
|
| +
|
| +#include "sync/syncable/entry_kernel.h"
|
| +#include "sync/syncable/syncable_id.h"
|
| +
|
| +namespace syncer {
|
| +namespace syncable {
|
| +
|
| +bool ChildComparator::operator()(
|
| + const syncable::EntryKernel* a,
|
| + const syncable::EntryKernel* b) const {
|
| + const UniquePosition& a_pos = a->ref(UNIQUE_POSITION);
|
| + const UniquePosition& b_pos = b->ref(UNIQUE_POSITION);
|
| +
|
| + if (a_pos.IsValid() && b_pos.IsValid()) {
|
| + // Position is important to this type.
|
| + return a_pos.LessThan(b_pos);
|
| + } else if (a_pos.IsValid() && !b_pos.IsValid()) {
|
| + // TODO(rlarocque): Remove these cases.
|
| + // An item with valid position as sibling of one with invalid position.
|
| + // We should not suppport this, but the tests rely on it. For now, just
|
| + // move all invalid position items to the right.
|
| + return true;
|
| + } else if (!a_pos.IsValid() && b_pos.IsValid()) {
|
| + // Mirror of the above case.
|
| + return false;
|
| + } else {
|
| + // Position doesn't matter.
|
| + DCHECK(!a->ref(UNIQUE_POSITION).IsValid());
|
| + DCHECK(!b->ref(UNIQUE_POSITION).IsValid());
|
| + return a->ref(ID) < b->ref(ID);
|
| + }
|
| +}
|
| +
|
| +ParentChildIndex::ParentChildIndex() {
|
| +}
|
| +
|
| +ParentChildIndex::~ParentChildIndex() {
|
| + STLDeleteContainerPairSecondPointers(
|
| + parent_children_map_.begin(), parent_children_map_.end());
|
| +}
|
| +
|
| +bool ParentChildIndex::ShouldInclude(const EntryKernel* entry) {
|
| + // This index excludes deleted items and the root item. The root
|
| + // item is excluded so that it doesn't show up as a child of itself.
|
| + return !entry->ref(IS_DEL) && !entry->ref(ID).IsRoot();
|
| +}
|
| +
|
| +bool ParentChildIndex::Insert(EntryKernel* entry) {
|
| + DCHECK(ShouldInclude(entry));
|
| +
|
| + const syncable::Id& parent_id = entry->ref(PARENT_ID);
|
| + ChildSet* children = NULL;
|
| + ParentChildrenMap::iterator i = parent_children_map_.find(parent_id);
|
| + if (i != parent_children_map_.end()) {
|
| + children = i->second;
|
| + } else {
|
| + children = new ChildSet();
|
| + parent_children_map_.insert(std::make_pair(parent_id, children));
|
| + }
|
| +
|
| + return children->insert(entry).second;
|
| +}
|
| +
|
| +void ParentChildIndex::Remove(EntryKernel* e) {
|
| + ParentChildrenMap::iterator i = parent_children_map_.find(e->ref(PARENT_ID));
|
| + DCHECK(i != parent_children_map_.end());
|
| +
|
| + ChildSet* children = i->second;
|
| + ChildSet::iterator j = children->find(e);
|
| + DCHECK(j != children->end());
|
| +
|
| + children->erase(j);
|
| + if (children->empty()) {
|
| + delete children;
|
| + parent_children_map_.erase(i);
|
| + }
|
| +}
|
| +
|
| +bool ParentChildIndex::Contains(EntryKernel *e) const {
|
| + const syncable::Id& parent_id = e->ref(PARENT_ID);
|
| + ParentChildrenMap::const_iterator i = parent_children_map_.find(parent_id);
|
| + if (i == parent_children_map_.end()) {
|
| + return false;
|
| + }
|
| + const ChildSet* children = i->second;
|
| + DCHECK(children && !children->empty());
|
| + return children->count(e) > 0;
|
| +}
|
| +
|
| +const ChildSet* ParentChildIndex::GetChildren(const syncable::Id& id) {
|
| + ParentChildrenMap::iterator i = parent_children_map_.find(id);
|
| + if (i == parent_children_map_.end()) {
|
| + return NULL;
|
| + }
|
| +
|
| + // A successful lookup implies at least some children exist.
|
| + DCHECK(!i->second->empty());
|
| + return i->second;
|
| +}
|
| +
|
| +} // namespace syncable
|
| +} // namespace syncer
|
|
|