| Index: base/file_path.cc
|
| ===================================================================
|
| --- base/file_path.cc (revision 30151)
|
| +++ base/file_path.cc (working copy)
|
| @@ -158,6 +158,75 @@
|
| #endif // defined(FILE_PATH_USES_DRIVE_LETTERS)
|
| }
|
|
|
| +bool FilePath::AppendAndResolveRelative(const FilePath& relative_path,
|
| + FilePath* path) const {
|
| + DCHECK(path);
|
| + if (!path || relative_path.IsAbsolute())
|
| + return false;
|
| +
|
| + FilePath full_path = Append(relative_path);
|
| + // Is it worth looking for parent references?
|
| + if (!full_path.ReferencesParent()) {
|
| + *path = full_path;
|
| + return true;
|
| + }
|
| +
|
| + // If the parent has a drive letter, then we must not remove the first
|
| + // component, which is the drive letter.
|
| + bool drive_letter = (FindDriveLetter(full_path.path_) !=
|
| + FilePath::StringType::npos);
|
| +
|
| + std::vector<FilePath::StringType> components;
|
| + full_path.GetComponents(&components);
|
| + std::vector<FilePath::StringType>::iterator it = components.begin();
|
| + // Start by removing any kCurrentDirectory component, since they may
|
| + // fool us into not going back to the appropriate parent level.
|
| + for (; it != components.end(); ++it) {
|
| + if (*it == kCurrentDirectory) {
|
| + // erase returns an iterator to the next component.
|
| + it = components.erase(it);
|
| + // So now, go back to previous iterator,
|
| + // so that we can appropriately process the next one as we loop.
|
| + --it;
|
| + }
|
| + }
|
| +
|
| + // Now parse the component looking for kParentDirectory and remove them as
|
| + // well as the previous component.
|
| + it = components.begin();
|
| + for (; it != components.end(); ++it) {
|
| + if (*it == kParentDirectory) {
|
| + // Did we reach the beginning?
|
| + if (it == components.begin() ||
|
| + (drive_letter && (it - 1) == components.begin())) {
|
| + return false;
|
| + }
|
| + // Remove the previous component, as well as the current one.
|
| + std::vector<FilePath::StringType>::iterator previous = it - 1;
|
| + // Unless the previous is at the beginning.
|
| + if (previous == components.begin() ||
|
| + (drive_letter && (previous - 1) == components.begin())) {
|
| + return false;
|
| + }
|
| + // vector::erase doesn't erase _Last, it erases [_First, _Last[,
|
| + // so we must increment current which we want erased.
|
| + it = components.erase(previous, it + 1);
|
| + // And go back to previous so that we can process the next one as we loop.
|
| + --it;
|
| + }
|
| + }
|
| +
|
| + // Now reconstruct the path with the components that were left in.
|
| + it = components.begin();
|
| + // We start with the first component, in case it is absolute
|
| + // and absolute paths can't be appended.
|
| + *path = FilePath(*it);
|
| + for (++it; it != components.end(); ++it)
|
| + *path = path->Append(*it);
|
| +
|
| + return true;
|
| +}
|
| +
|
| bool FilePath::IsParent(const FilePath& child) const {
|
| return AppendRelativePath(child, NULL);
|
| }
|
|
|