blob: ab71dbb4bb7f3a1659dc1701fa78bad7ea2b8b7b [file] [log] [blame]
// Copyright 2014 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 "chrome/browser/sync_file_system/subtree_set.h"
#include "base/logging.h"
#include "base/stl_util.h"
#include "webkit/common/fileapi/file_system_util.h"
namespace sync_file_system {
SubtreeSet::Node::Node()
: contained_as_subtree_root(false),
number_of_subtrees_below(0) {
}
SubtreeSet::Node::Node(bool contained_as_subtree_root,
size_t number_of_subtrees_below)
: contained_as_subtree_root(contained_as_subtree_root),
number_of_subtrees_below(number_of_subtrees_below) {
}
SubtreeSet::SubtreeSet() {}
SubtreeSet::~SubtreeSet() {}
bool SubtreeSet::IsDisjointWith(const base::FilePath& subtree_root) const {
base::FilePath::StringType normalized_subtree_root =
fileapi::VirtualPath::GetNormalizedFilePath(subtree_root);
// Check if |subtree_root| contains any of subtrees in the container.
if (ContainsKey(inclusive_ancestors_of_subtree_roots_,
normalized_subtree_root))
return false;
base::FilePath path(normalized_subtree_root);
while (!fileapi::VirtualPath::IsRootPath(path)) {
path = fileapi::VirtualPath::DirName(path);
Subtrees::const_iterator found =
inclusive_ancestors_of_subtree_roots_.find(path.value());
if (found != inclusive_ancestors_of_subtree_roots_.end())
return !found->second.contained_as_subtree_root;
}
return true;
}
bool SubtreeSet::insert(const base::FilePath& subtree_root) {
base::FilePath::StringType normalized_subtree_root =
fileapi::VirtualPath::GetNormalizedFilePath(subtree_root);
if (!IsDisjointWith(subtree_root))
return false;
inclusive_ancestors_of_subtree_roots_[normalized_subtree_root]
= Node(true, 1);
base::FilePath path(normalized_subtree_root);
while (!fileapi::VirtualPath::IsRootPath(path)) {
path = fileapi::VirtualPath::DirName(path);
DCHECK(!inclusive_ancestors_of_subtree_roots_[path.value()]
.contained_as_subtree_root);
++(inclusive_ancestors_of_subtree_roots_[path.value()]
.number_of_subtrees_below);
}
return true;
}
bool SubtreeSet::erase(const base::FilePath& subtree_root) {
base::FilePath::StringType normalized_subtree_root =
fileapi::VirtualPath::GetNormalizedFilePath(subtree_root);
{
Subtrees::iterator found =
inclusive_ancestors_of_subtree_roots_.find(normalized_subtree_root);
if (found == inclusive_ancestors_of_subtree_roots_.end() ||
!found->second.contained_as_subtree_root)
return false;
DCHECK_EQ(1u, found->second.number_of_subtrees_below);
inclusive_ancestors_of_subtree_roots_.erase(found);
}
base::FilePath path(normalized_subtree_root);
while (!fileapi::VirtualPath::IsRootPath(path)) {
path = fileapi::VirtualPath::DirName(path);
Subtrees::iterator found =
inclusive_ancestors_of_subtree_roots_.find(path.value());
if (found == inclusive_ancestors_of_subtree_roots_.end()) {
NOTREACHED();
continue;
}
DCHECK(!found->second.contained_as_subtree_root);
if (!--(found->second.number_of_subtrees_below))
inclusive_ancestors_of_subtree_roots_.erase(found);
}
return true;
}
size_t SubtreeSet::size() const {
Subtrees::const_iterator found =
inclusive_ancestors_of_subtree_roots_.find(fileapi::VirtualPath::kRoot);
if (found == inclusive_ancestors_of_subtree_roots_.end())
return 0;
return found->second.number_of_subtrees_below;
}
} // namespace sync_file_system