Move file enumeration to filepaths.

Review URL: http://codereview.chromium.org/13315

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@6784 0039d316-1c4b-4281-b951-d872f2087c98


CrOS-Libchrome-Original-Commit: 0b733220c5fbef986647fce040c1b5d5e48be2b6
diff --git a/base/file_path.cc b/base/file_path.cc
index 0856029..a938ca6 100644
--- a/base/file_path.cc
+++ b/base/file_path.cc
@@ -77,7 +77,7 @@
 // adhere to their behavior.
 FilePath FilePath::DirName() const {
   FilePath new_path(path_);
-  new_path.StripTrailingSeparators();
+  new_path.StripTrailingSeparatorsInternal();
 
   // The drive letter, if any, always needs to remain in the output.  If there
   // is no drive letter, as will always be the case on platforms which do not
@@ -104,7 +104,7 @@
     new_path.path_.resize(last_separator);
   }
 
-  new_path.StripTrailingSeparators();
+  new_path.StripTrailingSeparatorsInternal();
   if (!new_path.path_.length())
     new_path.path_ = kCurrentDirectory;
 
@@ -113,7 +113,7 @@
 
 FilePath FilePath::BaseName() const {
   FilePath new_path(path_);
-  new_path.StripTrailingSeparators();
+  new_path.StripTrailingSeparatorsInternal();
 
   // The drive letter, if any, is always stripped.
   StringType::size_type letter = FindDriveLetter(new_path.path_);
@@ -148,7 +148,7 @@
   }
 
   FilePath new_path(path_);
-  new_path.StripTrailingSeparators();
+  new_path.StripTrailingSeparatorsInternal();
 
   // Don't append a separator if the path is empty (indicating the current
   // directory) or if the path component is empty (indicating nothing to
@@ -201,7 +201,14 @@
 }
 #endif
 
-void FilePath::StripTrailingSeparators() {
+FilePath FilePath::StripTrailingSeparators() const {
+  FilePath new_path(path_);
+  new_path.StripTrailingSeparatorsInternal();
+  
+  return new_path;
+}
+
+void FilePath::StripTrailingSeparatorsInternal() {
   // If there is no drive letter, start will be 1, which will prevent stripping
   // the leading separator if there is only one separator.  If there is a drive
   // letter, start will be set appropriately to prevent stripping the first
diff --git a/base/file_path.h b/base/file_path.h
index fb2cc57..9049176 100644
--- a/base/file_path.h
+++ b/base/file_path.h
@@ -67,8 +67,8 @@
 
 #include <string>
 
-#include "base/compiler_specific.h"
 #include "base/basictypes.h"
+#include "base/compiler_specific.h"
 
 // Windows-style drive letter support and pathname separator characters can be
 // enabled and disabled independently, to aid testing.  These #defines are
@@ -121,6 +121,11 @@
     return path_ == that.path_;
   }
 
+  // Required for some STL containers and operations
+  bool operator<(const FilePath& that) const {
+    return path_ < that.path_;
+  }
+
   const StringType& value() const { return path_; }
 
   // Returns true if |character| is in kSeparators.
@@ -154,6 +159,10 @@
   // platforms, an absolute path begins with a separator character.
   bool IsAbsolute() const;
 
+  // Returns a copy of this FilePath that does not end with a trailing
+  // separator.
+  FilePath StripTrailingSeparators() const;
+
   // Older Chromium code assumes that paths are always wstrings.
   // This function converts a wstring to a FilePath, and is useful to smooth
   // porting that old code to the FilePath API.
@@ -174,7 +183,7 @@
   // directory, so "////" will become "/", not "".  A leading pair of
   // separators is never stripped, to support alternate roots.  This is used to
   // support UNC paths on Windows.
-  void StripTrailingSeparators();
+  void StripTrailingSeparatorsInternal();
 
   StringType path_;
 };
diff --git a/base/file_util.h b/base/file_util.h
index 41bc70b..7bc7e82 100644
--- a/base/file_util.h
+++ b/base/file_util.h
@@ -51,6 +51,8 @@
 bool EnsureEndsWithSeparator(FilePath* path);
 
 // Modifies a string by trimming all trailing separators from the end.
+// Deprecated. FilePath does this automatically, and if it's constructed from a
+// path with a trailing separator, StripTrailingSeparators() may be used.
 void TrimTrailingSeparator(std::wstring* dir);
 
 // Strips the topmost directory from the end of 'dir'.  Assumes 'dir' does not
@@ -373,26 +375,26 @@
   // NOTE: the pattern only matches the contents of root_path, not files in
   // recursive subdirectories.
   // TODO(erikkay): Fix the pattern matching to work at all levels.
-  FileEnumerator(const std::wstring& root_path,
+  FileEnumerator(const FilePath& root_path,
                  bool recursive,
                  FileEnumerator::FILE_TYPE file_type);
-  FileEnumerator(const std::wstring& root_path,
+  FileEnumerator(const FilePath& root_path,
                  bool recursive,
                  FileEnumerator::FILE_TYPE file_type,
-                 const std::wstring& pattern);
+                 const FilePath::StringType& pattern);
   ~FileEnumerator();
 
   // Returns an empty string if there are no more results.
-  std::wstring Next();
+  FilePath Next();
 
   // Write the file info into |info|.
   void GetFindInfo(FindInfo* info);
 
  private:
-  std::wstring root_path_;
+  FilePath root_path_;
   bool recursive_;
   FILE_TYPE file_type_;
-  std::wstring pattern_;  // Empty when we want to find everything.
+  FilePath pattern_;  // Empty when we want to find everything.
 
   // Set to true when there is a find operation open. This way, we can lazily
   // start the operations when the caller calls Next().
@@ -400,7 +402,7 @@
 
   // A stack that keeps track of which subdirectories we still need to
   // enumerate in the breadth-first search.
-  std::stack<std::wstring> pending_paths_;
+  std::stack<FilePath> pending_paths_;
 
 #if defined(OS_WIN)
   WIN32_FIND_DATA find_data_;
diff --git a/base/file_util_posix.cc b/base/file_util_posix.cc
index 5760a68..153f70a 100644
--- a/base/file_util_posix.cc
+++ b/base/file_util_posix.cc
@@ -378,7 +378,7 @@
   return !ret;
 }
 
-FileEnumerator::FileEnumerator(const std::wstring& root_path,
+FileEnumerator::FileEnumerator(const FilePath& root_path,
                                bool recursive,
                                FileEnumerator::FILE_TYPE file_type)
     : recursive_(recursive),
@@ -388,19 +388,19 @@
   pending_paths_.push(root_path);
 }
 
-FileEnumerator::FileEnumerator(const std::wstring& root_path,
+FileEnumerator::FileEnumerator(const FilePath& root_path,
                                bool recursive,
                                FileEnumerator::FILE_TYPE file_type,
-                               const std::wstring& pattern)
+                               const FilePath::StringType& pattern)
     : recursive_(recursive),
       file_type_(file_type),
-      pattern_(root_path),
+      pattern_(root_path.value()),
       is_in_find_op_(false),
       fts_(NULL) {
   // The Windows version of this code only matches against items in the top-most
   // directory, and we're comparing fnmatch against full paths, so this is the
   // easiest way to get the right pattern.
-  AppendToPath(&pattern_, pattern);
+  pattern_ = pattern_.Append(pattern);
   pending_paths_.push(root_path);
 }
 
@@ -423,20 +423,20 @@
 // the fts enumeration doesn't match (type, pattern, etc.).  In the case of
 // large directories with many files this can be quite deep.
 // TODO(erikkay) - get rid of this recursive pattern
-std::wstring FileEnumerator::Next() {
+FilePath FileEnumerator::Next() {
   if (!is_in_find_op_) {
     if (pending_paths_.empty())
-      return std::wstring();
+      return FilePath();
 
     // The last find FindFirstFile operation is done, prepare a new one.
     root_path_ = pending_paths_.top();
-    TrimTrailingSeparator(&root_path_);
+    root_path_ = root_path_.StripTrailingSeparators();
     pending_paths_.pop();
 
     // Start a new find operation.
     int ftsflags = FTS_LOGICAL;
     char top_dir[PATH_MAX];
-    base::strlcpy(top_dir, WideToUTF8(root_path_).c_str(), sizeof(top_dir));
+    base::strlcpy(top_dir, root_path_.value().c_str(), sizeof(top_dir));
     char* dir_list[2] = { top_dir, NULL };
     fts_ = fts_open(dir_list, ftsflags, NULL);
     if (!fts_)
@@ -458,15 +458,15 @@
 
   // Patterns are only matched on the items in the top-most directory.
   // (see Windows implementation)
-  if (fts_ent_->fts_level == 1 && pattern_.length() > 0) {
-    if (fnmatch(WideToUTF8(pattern_).c_str(), fts_ent_->fts_path, 0) != 0) {
+  if (fts_ent_->fts_level == 1 && pattern_.value().length() > 0) {
+    if (fnmatch(pattern_.value().c_str(), fts_ent_->fts_path, 0) != 0) {
       if (fts_ent_->fts_info == FTS_D)
         fts_set(fts_, fts_ent_, FTS_SKIP);
       return Next();
     }
   }
 
-  std::wstring cur_file(UTF8ToWide(fts_ent_->fts_path));
+  FilePath cur_file(fts_ent_->fts_path);
   if (fts_ent_->fts_info == FTS_D) {
     // If not recursive, then prune children.
     if (!recursive_)
diff --git a/base/file_util_unittest.cc b/base/file_util_unittest.cc
index 4c7743a..a8855e9 100644
--- a/base/file_util_unittest.cc
+++ b/base/file_util_unittest.cc
@@ -55,9 +55,9 @@
 class FindResultCollector {
  public:
   FindResultCollector(file_util::FileEnumerator& enumerator) {
-    std::wstring cur_file;
-    while (!(cur_file = enumerator.Next()).empty()) {
-      FilePath::StringType path = FilePath::FromWStringHack(cur_file).value();
+    FilePath cur_file;
+    while (!(cur_file = enumerator.Next()).value().empty()) {
+      FilePath::StringType path = cur_file.value();
       // The file should not be returned twice.
       EXPECT_TRUE(files_.end() == files_.find(path))
           << "Same file returned twice";
@@ -830,10 +830,10 @@
 
 TEST_F(FileUtilTest, FileEnumeratorTest) {
   // Test an empty directory.
-  file_util::FileEnumerator f0(test_dir_.ToWStringHack(), true,
+  file_util::FileEnumerator f0(test_dir_, true,
       file_util::FileEnumerator::FILES_AND_DIRECTORIES);
-  EXPECT_EQ(f0.Next(), L"");
-  EXPECT_EQ(f0.Next(), L"");
+  EXPECT_EQ(f0.Next().value(), FILE_PATH_LITERAL(""));
+  EXPECT_EQ(f0.Next().value(), FILE_PATH_LITERAL(""));
 
   // create the directories
   FilePath dir1 = test_dir_.Append(FILE_PATH_LITERAL("dir1"));
@@ -857,7 +857,7 @@
   FilePath file2_abs = test_dir_.Append(FILE_PATH_LITERAL("file2.txt"));
 
   // Only enumerate files.
-  file_util::FileEnumerator f1(test_dir_.ToWStringHack(), true,
+  file_util::FileEnumerator f1(test_dir_, true,
                                file_util::FileEnumerator::FILES);
   FindResultCollector c1(f1);
   EXPECT_TRUE(c1.HasFile(file1));
@@ -867,7 +867,7 @@
   EXPECT_EQ(c1.size(), 4);
 
   // Only enumerate directories.
-  file_util::FileEnumerator f2(test_dir_.ToWStringHack(), true,
+  file_util::FileEnumerator f2(test_dir_, true,
                                file_util::FileEnumerator::DIRECTORIES);
   FindResultCollector c2(f2);
   EXPECT_TRUE(c2.HasFile(dir1));
@@ -877,14 +877,14 @@
 
   // Only enumerate directories non-recursively.
   file_util::FileEnumerator f2_non_recursive(
-      test_dir_.ToWStringHack(), false, file_util::FileEnumerator::DIRECTORIES);
+      test_dir_, false, file_util::FileEnumerator::DIRECTORIES);
   FindResultCollector c2_non_recursive(f2_non_recursive);
   EXPECT_TRUE(c2_non_recursive.HasFile(dir1));
   EXPECT_TRUE(c2_non_recursive.HasFile(dir2));
   EXPECT_EQ(c2_non_recursive.size(), 2);
 
   // Enumerate files and directories.
-  file_util::FileEnumerator f3(test_dir_.ToWStringHack(), true,
+  file_util::FileEnumerator f3(test_dir_, true,
       file_util::FileEnumerator::FILES_AND_DIRECTORIES);
   FindResultCollector c3(f3);
   EXPECT_TRUE(c3.HasFile(dir1));
@@ -897,7 +897,7 @@
   EXPECT_EQ(c3.size(), 7);
 
   // Non-recursive operation.
-  file_util::FileEnumerator f4(test_dir_.ToWStringHack(), false,
+  file_util::FileEnumerator f4(test_dir_, false,
       file_util::FileEnumerator::FILES_AND_DIRECTORIES);
   FindResultCollector c4(f4);
   EXPECT_TRUE(c4.HasFile(dir2));
@@ -907,8 +907,9 @@
   EXPECT_EQ(c4.size(), 4);
 
   // Enumerate with a pattern.
-  file_util::FileEnumerator f5(test_dir_.ToWStringHack(), true,
-      file_util::FileEnumerator::FILES_AND_DIRECTORIES, L"dir*");
+  file_util::FileEnumerator f5(test_dir_, true,
+      file_util::FileEnumerator::FILES_AND_DIRECTORIES,
+      FILE_PATH_LITERAL("dir*"));
   FindResultCollector c5(f5);
   EXPECT_TRUE(c5.HasFile(dir1));
   EXPECT_TRUE(c5.HasFile(dir2));
@@ -919,10 +920,10 @@
 
   // Make sure the destructor closes the find handle while in the middle of a
   // query to allow TearDown to delete the directory.
-  file_util::FileEnumerator f6(test_dir_.ToWStringHack(), true,
+  file_util::FileEnumerator f6(test_dir_, true,
       file_util::FileEnumerator::FILES_AND_DIRECTORIES);
-  EXPECT_FALSE(f6.Next().empty());  // Should have found something
-                                    // (we don't care what).
+  EXPECT_FALSE(f6.Next().value().empty());  // Should have found something
+                                            // (we don't care what).
 }