diff options
-rw-r--r-- | base/file_path.cc | 72 | ||||
-rw-r--r-- | base/file_path.h | 12 | ||||
-rw-r--r-- | base/file_path_unittest.cc | 102 | ||||
-rw-r--r-- | base/file_util.cc | 28 | ||||
-rw-r--r-- | base/file_util.h | 4 | ||||
-rw-r--r-- | base/file_util_unittest.cc | 51 | ||||
-rw-r--r-- | chrome/browser/importer/ie_importer.cc | 3 |
7 files changed, 188 insertions, 84 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")); diff --git a/chrome/browser/importer/ie_importer.cc b/chrome/browser/importer/ie_importer.cc index 41039ff..9db6396 100644 --- a/chrome/browser/importer/ie_importer.cc +++ b/chrome/browser/importer/ie_importer.cc @@ -14,6 +14,7 @@ #include "app/l10n_util.h" #include "app/win_util.h" +#include "base/file_path.h" #include "base/file_util.h" #include "base/registry.h" #include "base/string_util.h" @@ -516,7 +517,7 @@ void IEImporter::ParseFavoritesFolder(const FavoritesInfo& info, entry.url = url; entry.creation_time = GetFileCreationTime(*it); if (!relative_path.empty()) - file_util::PathComponents(relative_path, &entry.path); + relative_path.GetComponents(&entry.path); // Flatten the bookmarks in Link folder onto bookmark toolbar. Otherwise, // put it into "Other bookmarks". |