summaryrefslogtreecommitdiffstats
path: root/base
diff options
context:
space:
mode:
authorrafaelw@chromium.org <rafaelw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-24 21:28:30 +0000
committerrafaelw@chromium.org <rafaelw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-24 21:28:30 +0000
commit0e4f68db63e565201a6eaa2f600441c37b150d1b (patch)
treeb4cfc4f35e6d8ae7fa6266fd2c3faaed9e006adb /base
parenta86c97ccfe0038b1672d5a06d283561b7f294640 (diff)
downloadchromium_src-0e4f68db63e565201a6eaa2f600441c37b150d1b.zip
chromium_src-0e4f68db63e565201a6eaa2f600441c37b150d1b.tar.gz
chromium_src-0e4f68db63e565201a6eaa2f600441c37b150d1b.tar.bz2
Move PathComponents from file_util to FilePath, add FilePath::IsParent()
r=erikkay,mark Review URL: http://codereview.chromium.org/145026 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@19174 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r--base/file_path.cc72
-rw-r--r--base/file_path.h12
-rw-r--r--base/file_path_unittest.cc102
-rw-r--r--base/file_util.cc28
-rw-r--r--base/file_util.h4
-rw-r--r--base/file_util_unittest.cc51
6 files changed, 186 insertions, 83 deletions
diff --git a/base/file_path.cc b/base/file_path.cc
index a00659e..e3dfbbd 100644
--- a/base/file_path.cc
+++ b/base/file_path.cc
@@ -61,6 +61,16 @@ bool IsPathAbsolute(const FilePath::StringType& path) {
#endif // FILE_PATH_USES_DRIVE_LETTERS
}
+bool AreAllSeparators(FilePath::StringType input) {
+ for (FilePath::StringType::const_iterator it = input.begin();
+ it != input.end(); ++it) {
+ if (!FilePath::IsSeparator(*it))
+ return false;
+ }
+
+ return true;
+}
+
} // namespace
bool FilePath::IsSeparator(CharType character) {
@@ -73,6 +83,68 @@ bool FilePath::IsSeparator(CharType character) {
return false;
}
+void FilePath::GetComponents(std::vector<FilePath::StringType>* components)
+ const {
+ DCHECK(components);
+ if (!components)
+ return;
+ components->clear();
+ if (value().empty())
+ return;
+
+ std::vector<FilePath::StringType> ret_val;
+ FilePath current = *this;
+ FilePath base;
+
+ // Capture path components.
+ while (current != current.DirName()) {
+ base = current.BaseName();
+ if (!AreAllSeparators(base.value()))
+ ret_val.push_back(base.value());
+ current = current.DirName();
+ }
+
+ // Capture root, if any.
+ base = current.BaseName();
+ if (!base.value().empty() && base.value() != kCurrentDirectory)
+ ret_val.push_back(current.BaseName().value());
+
+ // Capture drive letter, if any.
+ FilePath dir = current.DirName();
+ StringType::size_type letter = FindDriveLetter(dir.value());
+ if (letter != FilePath::StringType::npos) {
+ ret_val.push_back(FilePath::StringType(dir.value(), 0, letter + 1));
+ }
+
+ *components = std::vector<FilePath::StringType>(ret_val.rbegin(),
+ ret_val.rend());
+}
+
+bool FilePath::IsParent(const FilePath& child) const {
+ std::vector<FilePath::StringType> parent_components;
+ std::vector<FilePath::StringType> child_components;
+ GetComponents(&parent_components);
+ child.GetComponents(&child_components);
+
+ if (parent_components.size() >= child_components.size())
+ return false;
+ if (parent_components.size() == 0)
+ return false;
+
+ std::vector<FilePath::StringType>::const_iterator parent_comp =
+ parent_components.begin();
+ std::vector<FilePath::StringType>::const_iterator child_comp =
+ child_components.begin();
+ while (parent_comp != parent_components.end()) {
+ if (*parent_comp != *child_comp)
+ return false;
+ ++parent_comp;
+ ++child_comp;
+ }
+
+ return true;
+}
+
// libgen's dirname and basename aren't guaranteed to be thread-safe and aren't
// guaranteed to not modify their input strings, and in fact are implemented
// differently in this regard on different platforms. Don't use them, but
diff --git a/base/file_path.h b/base/file_path.h
index 73de4a6..ae4d36d 100644
--- a/base/file_path.h
+++ b/base/file_path.h
@@ -142,6 +142,18 @@ class FilePath {
// Returns true if |character| is in kSeparators.
static bool IsSeparator(CharType character);
+ // Returns a vector of all of the components of the provided path. It is
+ // equivalent to calling DirName().value() on the path's root component,
+ // and BaseName().value() on each child component.
+ void GetComponents(std::vector<FilePath::StringType>* components) const;
+
+ // Returns true if this FilePath is a strict parent of the |child|. Absolute
+ // and relative paths are accepted i.e. is /foo parent to /foo/bar and
+ // is foo parent to foo/bar. Does not convert paths to absolute, follow
+ // symlinks or directory navigation (e.g. ".."). A path is *NOT* its own
+ // parent.
+ bool IsParent(const FilePath& child) const;
+
// Returns a FilePath corresponding to the directory containing the path
// named by this object, stripping away the file component. If this object
// only contains one component, returns a FilePath identifying
diff --git a/base/file_path_unittest.cc b/base/file_path_unittest.cc
index 3439c6c..0df6838 100644
--- a/base/file_path_unittest.cc
+++ b/base/file_path_unittest.cc
@@ -27,6 +27,11 @@ struct BinaryTestData {
const FilePath::CharType* expected;
};
+struct BinaryBooleanTestData {
+ const FilePath::CharType* inputs[2];
+ bool expected;
+};
+
// file_util winds up using autoreleased objects on the Mac, so this needs
// to be a PlatformTest
class FilePathTest : public PlatformTest {
@@ -375,6 +380,103 @@ TEST_F(FilePathTest, IsAbsolute) {
}
}
+TEST_F(FilePathTest, PathComponentsTest) {
+ const struct UnaryTestData cases[] = {
+ { FPL("//foo/bar/baz/"), FPL("|//|foo|bar|baz")},
+ { FPL("///"), FPL("|/")},
+ { FPL("/foo//bar//baz/"), FPL("|/|foo|bar|baz")},
+ { FPL("/foo/bar/baz/"), FPL("|/|foo|bar|baz")},
+ { FPL("/foo/bar/baz//"), FPL("|/|foo|bar|baz")},
+ { FPL("/foo/bar/baz///"), FPL("|/|foo|bar|baz")},
+ { FPL("/foo/bar/baz"), FPL("|/|foo|bar|baz")},
+ { FPL("/foo/bar.bot/baz.txt"), FPL("|/|foo|bar.bot|baz.txt")},
+ { FPL("//foo//bar/baz"), FPL("|//|foo|bar|baz")},
+ { FPL("/"), FPL("|/")},
+ { FPL("foo"), FPL("|foo")},
+ { FPL(""), FPL("")},
+#if defined(FILE_PATH_USES_DRIVE_LETTERS)
+ { FPL("e:/foo"), FPL("|e:|/|foo")},
+ { FPL("e:/"), FPL("|e:|/")},
+ { FPL("e:"), FPL("|e:")},
+#endif // FILE_PATH_USES_DRIVE_LETTERS
+#if defined(FILE_PATH_USES_WIN_SEPARATORS)
+ { FPL("../foo"), FPL("|..|foo")},
+ { FPL("./foo"), FPL("|foo")},
+ { FPL("../foo/bar/"), FPL("|..|foo|bar") },
+ { FPL("\\\\foo\\bar\\baz\\"), FPL("|\\\\|foo|bar|baz")},
+ { FPL("\\\\\\"), FPL("|\\")},
+ { FPL("\\foo\\\\bar\\\\baz\\"), FPL("|\\|foo|bar|baz")},
+ { FPL("\\foo\\bar\\baz\\"), FPL("|\\|foo|bar|baz")},
+ { FPL("\\foo\\bar\\baz\\\\"), FPL("|\\|foo|bar|baz")},
+ { FPL("\\foo\\bar\\baz\\\\\\"), FPL("|\\|foo|bar|baz")},
+ { FPL("\\foo\\bar\\baz"), FPL("|\\|foo|bar|baz")},
+ { FPL("\\foo\\bar/baz\\\\\\"), FPL("|\\|foo|bar|baz")},
+ { FPL("/foo\\bar\\baz"), FPL("|/|foo|bar|baz")},
+ { FPL("\\foo\\bar.bot\\baz.txt"), FPL("|\\|foo|bar.bot|baz.txt")},
+ { FPL("\\\\foo\\\\bar\\baz"), FPL("|\\\\|foo|bar|baz")},
+ { FPL("\\"), FPL("|\\")},
+#endif // FILE_PATH_USES_WIN_SEPARATORS
+ };
+
+ for (size_t i = 0; i < arraysize(cases); ++i) {
+ FilePath input(cases[i].input);
+ std::vector<FilePath::StringType> comps;
+ input.GetComponents(&comps);
+
+ FilePath::StringType observed;
+ for (size_t j = 0; j < comps.size(); ++j) {
+ observed.append(FILE_PATH_LITERAL("|"), 1);
+ observed.append(comps[j]);
+ }
+ EXPECT_EQ(FilePath::StringType(cases[i].expected), observed) <<
+ "i: " << i << ", input: " << input.value();
+ }
+}
+
+TEST_F(FilePathTest, IsParentTest) {
+ const struct BinaryBooleanTestData cases[] = {
+ { { FPL("/"), FPL("/foo/bar/baz") }, true},
+ { { FPL("/foo/bar"), FPL("/foo/bar/baz") }, true},
+ { { FPL("/foo/bar/"), FPL("/foo/bar/baz") }, true},
+ { { FPL("//foo/bar/"), FPL("//foo/bar/baz") }, true},
+ { { FPL("/foo/bar"), FPL("/foo2/bar/baz") }, false},
+ { { FPL("/foo/bar.txt"), FPL("/foo/bar/baz") }, false},
+ { { FPL("/foo/bar"), FPL("/foo/bar2/baz") }, false},
+ { { FPL("/foo/bar"), FPL("/foo/bar") }, false},
+ { { FPL("/foo/bar/baz"), FPL("/foo/bar") }, false},
+ { { FPL("foo/bar"), FPL("foo/bar/baz") }, true},
+ { { FPL("foo/bar"), FPL("foo2/bar/baz") }, false},
+ { { FPL("foo/bar"), FPL("foo/bar2/baz") }, false},
+ { { FPL(""), FPL("foo") }, false},
+#if defined(FILE_PATH_USES_DRIVE_LETTERS)
+ { { FPL("c:/foo/bar"), FPL("c:/foo/bar/baz") }, true},
+ { { FPL("c:/"), FPL("c:/foo/bar/baz") }, true},
+ { { FPL("c:"), FPL("c:/foo/bar/baz") }, true},
+ { { FPL("c:/foo/bar"), FPL("d:/foo/bar/baz") }, false},
+ { { FPL("c:/foo/bar"), FPL("c:/foo2/bar/baz") }, false},
+ { { FPL("c:/foo/bar"), FPL("c:/foo/bar2/baz") }, false},
+#endif // FILE_PATH_USES_DRIVE_LETTERS
+#if defined(FILE_PATH_USES_WIN_SEPARATORS)
+ { { FPL("\\foo\\bar"), FPL("\\foo\\bar\\baz") }, true},
+ { { FPL("\\foo/bar"), FPL("\\foo\\bar\\baz") }, true},
+ { { FPL("\\foo/bar"), FPL("\\foo/bar/baz") }, true},
+ { { FPL("\\"), FPL("\\foo\\bar\\baz") }, true},
+ { { FPL(""), FPL("\\foo\\bar\\baz") }, false},
+ { { FPL("\\foo\\bar"), FPL("\\foo2\\bar\\baz") }, false},
+ { { FPL("\\foo\\bar"), FPL("\\foo\\bar2\\baz") }, false},
+#endif // FILE_PATH_USES_DRIVE_LETTERS
+ };
+
+ for (size_t i = 0; i < arraysize(cases); ++i) {
+ FilePath parent(cases[i].inputs[0]);
+ FilePath child(cases[i].inputs[1]);
+
+ EXPECT_EQ(parent.IsParent(child), cases[i].expected) <<
+ "i: " << i << ", parent: " << parent.value() << ", child: " <<
+ child.value();
+ }
+}
+
TEST_F(FilePathTest, Extension) {
FilePath base_dir(FILE_PATH_LITERAL("base_dir"));
diff --git a/base/file_util.cc b/base/file_util.cc
index 5f18674..c366a76 100644
--- a/base/file_util.cc
+++ b/base/file_util.cc
@@ -26,34 +26,6 @@ const FilePath::CharType kExtensionSeparator = FILE_PATH_LITERAL('.');
namespace file_util {
-void PathComponents(const FilePath& path,
- std::vector<FilePath::StringType>* components) {
- DCHECK(components);
- if (!components)
- return;
-
- FilePath::StringType path_str = path.value();
- FilePath::StringType::size_type start = 0;
- FilePath::StringType::size_type end =
- path_str.find_first_of(FilePath::kSeparators);
-
- // If the path starts with a separator, add it to components.
- if (end == start) {
- components->push_back(FilePath::StringType(path_str, 0, 1));
- start = end + 1;
- end = path_str.find_first_of(FilePath::kSeparators, start);
- }
- while (end != FilePath::StringType::npos) {
- FilePath::StringType component =
- FilePath::StringType(path_str, start, end - start);
- components->push_back(component);
- start = end + 1;
- end = path_str.find_first_of(FilePath::kSeparators, start);
- }
-
- components->push_back(FilePath::StringType(path_str, start));
-}
-
bool EndsWithSeparator(const FilePath& path) {
FilePath::StringType value = path.value();
if (value.empty())
diff --git a/base/file_util.h b/base/file_util.h
index 39d8f09..30918d3 100644
--- a/base/file_util.h
+++ b/base/file_util.h
@@ -38,10 +38,6 @@ namespace file_util {
//-----------------------------------------------------------------------------
// Functions that operate purely on a path string w/o touching the filesystem:
-// Returns a vector of all of the components of the provided path.
-void PathComponents(const FilePath& path,
- std::vector<FilePath::StringType>* components);
-
// Returns true if the given path ends with a path separator character.
bool EndsWithSeparator(const FilePath& path);
// These two versions are both deprecated. TODO(estade): remove them.
diff --git a/base/file_util_unittest.cc b/base/file_util_unittest.cc
index 738bac8..e510594 100644
--- a/base/file_util_unittest.cc
+++ b/base/file_util_unittest.cc
@@ -1072,57 +1072,6 @@ TEST_F(FileUtilTest, FileEnumeratorOrderTest) {
EXPECT_EQ(FILE_PATH_LITERAL(""), cur_file.value());
}
-void PathComponents(const std::wstring& path,
- std::vector<std::wstring>* components) {
- DCHECK(components != NULL);
- if (components == NULL)
- return;
- std::wstring::size_type start = 0;
- std::wstring::size_type end = path.find('/', start);
-
- // Special case the "/" or "\" directory. On Windows with a drive letter,
- // this code path won't hit, but the right thing should still happen.
- // "E:\foo" will turn into "E:","foo".
- if (end == start) {
- components->push_back(std::wstring(path, 0, 1));
- start = end + 1;
- end = path.find('/', start);
- }
- while (end != std::wstring::npos) {
- std::wstring component = std::wstring(path, start, end - start);
- components->push_back(component);
- start = end + 1;
- end = path.find('/', start);
- }
- std::wstring component = std::wstring(path, start);
- components->push_back(component);
-}
-
-static const struct PathComponentsCase {
- const FilePath::CharType* path;
- const FilePath::CharType* result;
-} kPathComponents[] = {
- {FILE_PATH_LITERAL("/foo/bar/baz/"), FILE_PATH_LITERAL("/|foo|bar|baz|")},
- {FILE_PATH_LITERAL("/foo/bar/baz"), FILE_PATH_LITERAL("/|foo|bar|baz")},
- {FILE_PATH_LITERAL("e:/foo"), FILE_PATH_LITERAL("e:|foo")},
-};
-
-TEST_F(FileUtilTest, PathComponentsTest) {
- for (size_t i = 0; i < arraysize(kPathComponents); ++i) {
- FilePath path(kPathComponents[i].path);
- std::vector<FilePath::StringType> comps;
- file_util::PathComponents(path, &comps);
-
- FilePath::StringType result;
- for (size_t j = 0; j < comps.size(); ++j) {
- result.append(comps[j]);
- if (j < comps.size() - 1)
- result.append(FILE_PATH_LITERAL("|"), 1);
- }
- EXPECT_EQ(kPathComponents[i].result, result);
- }
-}
-
TEST_F(FileUtilTest, Contains) {
FilePath data_dir = test_dir_.Append(FILE_PATH_LITERAL("FilePathTest"));