Remove file_util::kPathSeparator from posix.

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

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


CrOS-Libchrome-Original-Commit: b9e04f0654a99b6bb0b626df14e15ec4f9a8bf9d
diff --git a/base/file_path.cc b/base/file_path.cc
index 4cafd1f..98a4703 100644
--- a/base/file_path.cc
+++ b/base/file_path.cc
@@ -18,10 +18,9 @@
 const FilePath::CharType FilePath::kCurrentDirectory[] = FILE_PATH_LITERAL(".");
 const FilePath::CharType FilePath::kParentDirectory[] = FILE_PATH_LITERAL("..");
 
-// Returns true if |character| is in kSeparators.
-static bool IsSeparator(FilePath::CharType character) {
-  for (size_t i = 0; i < arraysize(FilePath::kSeparators) - 1; ++i) {
-    if (character == FilePath::kSeparators[i]) {
+bool FilePath::IsSeparator(CharType character) {
+  for (size_t i = 0; i < arraysize(kSeparators) - 1; ++i) {
+    if (character == kSeparators[i]) {
       return true;
     }
   }
diff --git a/base/file_path.h b/base/file_path.h
index 1ebb299..fc55a7a 100644
--- a/base/file_path.h
+++ b/base/file_path.h
@@ -123,6 +123,9 @@
 
   const StringType& value() const { return path_; }
 
+  // Returns true if |character| is in kSeparators.
+  static bool IsSeparator(CharType character);
+
   // 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_util.cc b/base/file_util.cc
index 10ab164..187e7b0 100644
--- a/base/file_util.cc
+++ b/base/file_util.cc
@@ -13,41 +13,45 @@
 #include "base/string_util.h"
 #include "unicode/uniset.h"
 
+#include "base/string_piece.h"
+#include "base/sys_string_conversions.h"
+
 namespace file_util {
 
-const wchar_t kExtensionSeparator = L'.';
-
-void PathComponents(const std::wstring& path,
-                    std::vector<std::wstring>* components) {
-  DCHECK(components != NULL);
-  if (components == NULL)
+void PathComponents(const FilePath& path,
+                    std::vector<FilePath::StringType>* components) {
+  DCHECK(components);
+  if (!components)
     return;
-  std::wstring::size_type start = 0;
-  std::wstring::size_type end = path.find(kPathSeparator, 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".
+  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(std::wstring(path, 0, 1));
+    components->push_back(FilePath::StringType(path_str, 0, 1));
     start = end + 1;
-    end = path.find(kPathSeparator, start);
+    end = path_str.find_first_of(FilePath::kSeparators, start);
   }
-  while (end != std::wstring::npos) {
-    std::wstring component = std::wstring(path, start, end - 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.find(kPathSeparator, start);
+    end = path_str.find_first_of(FilePath::kSeparators, start);
   }
-  std::wstring component = std::wstring(path, start);
-  components->push_back(component);
+
+  components->push_back(FilePath::StringType(path_str, start));
 }
 
-bool EndsWithSeparator(const FilePath& file_path) {
-  std::wstring path = file_path.ToWStringHack();
-  bool is_sep = (path.length() > 0 &&
-      path[path.length() - 1] == kPathSeparator);
-  return is_sep;
+bool EndsWithSeparator(const FilePath& path) {
+  FilePath::StringType value = path.value();
+  if (value.empty())
+    return false;
+
+  return FilePath::IsSeparator(value[value.size() - 1]);
 }
 
 bool EnsureEndsWithSeparator(FilePath* path) {
@@ -69,34 +73,6 @@
     dir->resize(dir->length() - 1);
 }
 
-void UpOneDirectory(std::wstring* dir) {
-  TrimTrailingSeparator(dir);
-
-  std::wstring::size_type last_sep = dir->find_last_of(kPathSeparator);
-  if (last_sep != std::wstring::npos)
-    dir->resize(last_sep);
-}
-
-void UpOneDirectoryOrEmpty(std::wstring* dir) {
-  TrimTrailingSeparator(dir);
-
-  std::wstring::size_type last_sep = dir->find_last_of(kPathSeparator);
-  if (last_sep != std::wstring::npos)
-    dir->resize(last_sep);
-  else
-    dir->clear();
-}
-
-void TrimFilename(std::wstring* path) {
-  if (EndsWithSeparator(path)) {
-    TrimTrailingSeparator(path);
-  } else {
-    std::wstring::size_type last_sep = path->find_last_of(kPathSeparator);
-    if (last_sep != std::wstring::npos)
-      path->resize(last_sep);
-  }
-}
-
 std::wstring GetFilenameFromPath(const std::wstring& path) {
   // TODO(erikkay): fix this - it's not using kPathSeparator, but win unit test
   // are exercising '/' as a path separator as well.
@@ -118,34 +94,6 @@
   return file_name.substr(0, last_dot);
 }
 
-void AppendToPath(std::wstring* path, const std::wstring& new_ending) {
-  if (!path) {
-    NOTREACHED();
-    return;  // Don't crash in this function in release builds.
-  }
-
-  if (!EndsWithSeparator(path))
-    path->push_back(kPathSeparator);
-  path->append(new_ending);
-}
-
-void InsertBeforeExtension(std::wstring* path, const std::wstring& suffix) {
-  DCHECK(path);
-
-  const std::wstring::size_type last_dot = path->rfind(kExtensionSeparator);
-  const std::wstring::size_type last_sep = path->rfind(kPathSeparator);
-
-  if (last_dot == std::wstring::npos ||
-      (last_sep != std::wstring::npos && last_dot < last_sep)) {
-    // The path looks something like "C:\pics.old\jojo" or "C:\pics\jojo".
-    // We should just append the suffix to the entire path.
-    path->append(suffix);
-    return;
-  }
-
-  path->insert(last_dot, suffix);
-}
-
 void ReplaceIllegalCharacters(std::wstring* file_name, int replace_char) {
   DCHECK(file_name);
 
@@ -216,39 +164,6 @@
 #endif
 }
 
-// Appends the extension to file adding a '.' if extension doesn't contain one.
-// This does nothing if extension is empty or '.'. This is used internally by
-// ReplaceExtension.
-static void AppendExtension(const std::wstring& extension,
-                            std::wstring* file) {
-  if (!extension.empty() && extension != L".") {
-    if (extension[0] != L'.')
-      file->append(L".");
-    file->append(extension);
-  }
-}
-
-void ReplaceExtension(std::wstring* file_name, const std::wstring& extension) {
-  const std::wstring::size_type last_dot = file_name->rfind(L'.');
-  if (last_dot == std::wstring::npos) {
-    // No extension, just append the supplied extension.
-    AppendExtension(extension, file_name);
-    return;
-  }
-  const std::wstring::size_type last_separator =
-      file_name->rfind(kPathSeparator);
-  if (last_separator != std::wstring::npos && last_dot < last_separator) {
-    // File name doesn't have extension, but one of the directories does; don't
-    // replace it, just append the supplied extension. For example
-    // 'c:\tmp.bar\foo'.
-    AppendExtension(extension, file_name);
-    return;
-  }
-  std::wstring result = file_name->substr(0, last_dot);
-  AppendExtension(extension, &result);
-  file_name->swap(result);
-}
-
 bool ContentsEqual(const FilePath& filename1, const FilePath& filename2) {
   // We open the file in binary format even if they are text files because
   // we are just comparing that bytes are exactly same in both files and not
@@ -257,7 +172,7 @@
                       std::ios::in | std::ios::binary);
   std::ifstream file2(filename2.value().c_str(),
                       std::ios::in | std::ios::binary);
-  
+
   // Even if both files aren't openable (and thus, in some sense, "equal"),
   // any unusable file yields a result of "false".
   if (!file1.is_open() || !file2.is_open())
@@ -323,22 +238,15 @@
   *path_str = path.ToWStringHack();
   return true;
 }
-bool Delete(const std::wstring& path, bool recursive) {
-  return Delete(FilePath::FromWStringHack(path), recursive);
-}
-bool EndsWithSeparator(std::wstring* path) {
-  return EndsWithSeparator(FilePath::FromWStringHack(*path));
-}
-bool EndsWithSeparator(const std::wstring& path) {
-  return EndsWithSeparator(FilePath::FromWStringHack(path));
-}
-bool Move(const std::wstring& from_path, const std::wstring& to_path) {
-  return Move(FilePath::FromWStringHack(from_path),
-              FilePath::FromWStringHack(to_path));
-}
-bool CopyFile(const std::wstring& from_path, const std::wstring& to_path) {
-  return CopyFile(FilePath::FromWStringHack(from_path),
-                  FilePath::FromWStringHack(to_path));
+void AppendToPath(std::wstring* path, const std::wstring& new_ending) {
+  if (!path) {
+    NOTREACHED();
+    return;  // Don't crash in this function in release builds.
+  }
+
+  if (!EndsWithSeparator(path))
+    path->push_back(FilePath::kSeparators[0]);
+  path->append(new_ending);
 }
 bool CopyDirectory(const std::wstring& from_path, const std::wstring& to_path,
                    bool recursive) {
@@ -346,17 +254,15 @@
                        FilePath::FromWStringHack(to_path),
                        recursive);
 }
-bool PathExists(const std::wstring& path) {
-  return PathExists(FilePath::FromWStringHack(path));
-}
-bool DirectoryExists(const std::wstring& path) {
-  return DirectoryExists(FilePath::FromWStringHack(path));
-}
 bool ContentsEqual(const std::wstring& filename1,
                    const std::wstring& filename2) {
   return ContentsEqual(FilePath::FromWStringHack(filename1),
                        FilePath::FromWStringHack(filename2));
 }
+bool CopyFile(const std::wstring& from_path, const std::wstring& to_path) {
+  return CopyFile(FilePath::FromWStringHack(from_path),
+                  FilePath::FromWStringHack(to_path));
+}
 bool CreateDirectory(const std::wstring& full_path) {
   return CreateDirectory(FilePath::FromWStringHack(full_path));
 }
@@ -367,6 +273,18 @@
   *temp_file = temp_file_path.ToWStringHack();
   return true;
 }
+bool Delete(const std::wstring& path, bool recursive) {
+  return Delete(FilePath::FromWStringHack(path), recursive);
+}
+bool DirectoryExists(const std::wstring& path) {
+  return DirectoryExists(FilePath::FromWStringHack(path));
+}
+bool EndsWithSeparator(std::wstring* path) {
+  return EndsWithSeparator(FilePath::FromWStringHack(*path));
+}
+bool EndsWithSeparator(const std::wstring& path) {
+  return EndsWithSeparator(FilePath::FromWStringHack(path));
+}
 bool GetCurrentDirectory(std::wstring* path_str) {
   FilePath path;
   if (!GetCurrentDirectory(&path))
@@ -387,12 +305,43 @@
   *path_str = path.ToWStringHack();
   return true;
 }
+bool Move(const std::wstring& from_path, const std::wstring& to_path) {
+  return Move(FilePath::FromWStringHack(from_path),
+              FilePath::FromWStringHack(to_path));
+}
 FILE* OpenFile(const std::wstring& filename, const char* mode) {
   return OpenFile(FilePath::FromWStringHack(filename), mode);
 }
+bool PathExists(const std::wstring& path) {
+  return PathExists(FilePath::FromWStringHack(path));
+}
 bool SetCurrentDirectory(const std::wstring& directory) {
   return SetCurrentDirectory(FilePath::FromWStringHack(directory));
 }
-
+void TrimFilename(std::wstring* path) {
+  if (EndsWithSeparator(path)) {
+    TrimTrailingSeparator(path);
+  } else {
+    *path = FilePath::FromWStringHack(*path).DirName().ToWStringHack();
+  }
+}
+void UpOneDirectory(std::wstring* dir) {
+  FilePath path = FilePath::FromWStringHack(*dir);
+  FilePath directory = path.DirName();
+  // If there is no separator, we will get back kCurrentDirectory.
+  // In this case don't change |dir|.
+  if (directory.value() != FilePath::kCurrentDirectory)
+    *dir = directory.ToWStringHack();
+}
+void UpOneDirectoryOrEmpty(std::wstring* dir) {
+  FilePath path = FilePath::FromWStringHack(*dir);
+  FilePath directory = path.DirName();
+  // If there is no separator, we will get back kCurrentDirectory.
+  // In this case, clear dir.
+  if (directory == path || directory.value() == FilePath::kCurrentDirectory)
+    dir->clear();
+  else
+    *dir = directory.ToWStringHack();
+}
 }  // namespace
 
diff --git a/base/file_util.h b/base/file_util.h
index 3fa6773..eebf3af 100644
--- a/base/file_util.h
+++ b/base/file_util.h
@@ -24,23 +24,31 @@
 #include <vector>
 
 #include "base/basictypes.h"
-
-class FilePath;
+#include "base/file_path.h"
 
 namespace file_util {
 
 //-----------------------------------------------------------------------------
 // Constants
 
+#if defined(OS_WIN)
+// The use of this constant is deprecated. Instead use file_util or FilePath
+// functions (Append, TrimTrailingSeparator, etc.), or use
+// FilePath::kSeparator[0].
 extern const wchar_t kPathSeparator;
-
+#endif
 
 //-----------------------------------------------------------------------------
 // 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);
+#if defined(OS_WIN)
+// Deprecated temporary compatibility function.
 void PathComponents(const std::wstring& path,
                     std::vector<std::wstring>* components);
+#endif
 
 // Returns true if the given path ends with a path separator character.
 bool EndsWithSeparator(const FilePath& path);
@@ -58,14 +66,17 @@
 // Strips the topmost directory from the end of 'dir'.  Assumes 'dir' does not
 // refer to a file.
 // If 'dir' is a root directory, return without change.
+// Deprecated. Use FilePath::DirName instead.
 void UpOneDirectory(std::wstring* dir);
-
 // Strips the topmost directory from the end of 'dir'.  Assumes 'dir' does not
 // refer to a file.
 // If 'dir' is a root directory, the result becomes empty string.
+// Deprecated. Use FilePath::DirName instead.
 void UpOneDirectoryOrEmpty(std::wstring* dir);
 
-// Strips the filename component from the end of 'path'.
+// Strips the filename component from the end of 'path'. If path ends with a
+// separator, then just drop the separator.
+// Deprecated. Use FilePath::DirName instead.
 void TrimFilename(std::wstring* path);
 
 // Returns the filename portion of 'path', without any leading \'s or /'s.
@@ -98,6 +109,9 @@
 // Deprecated temporary compatibility function.
 bool AbsolutePath(std::wstring* path);
 
+// TODO(port): create FilePath versions of these functions, and remove this
+// platform define.
+#if defined(OS_WIN)
 // Inserts |suffix| after the file name portion of |path| but before the
 // extension.
 // Examples:
@@ -107,6 +121,12 @@
 // path == "C:\pics.old\jojo" suffix == " (1)", returns "C:\pics.old\jojo (1)"
 void InsertBeforeExtension(std::wstring* path, const std::wstring& suffix);
 
+// Replaces the extension of |file_name| with |extension|.  If |file_name|
+// does not have an extension, them |extension| is added.  If |extension| is
+// empty, then the extension is removed from |file_name|.
+void ReplaceExtension(std::wstring* file_name, const std::wstring& extension);
+#endif
+
 // Replaces characters in 'file_name' that are illegal for file names with
 // 'replace_char'. 'file_name' must not be a full or relative path, but just the
 // file name component. Any leading or trailing whitespace in 'file_name' is
@@ -116,11 +136,6 @@
 //   'replace_char' is '-'.
 void ReplaceIllegalCharacters(std::wstring* file_name, int replace_char);
 
-// Replaces the extension of |file_name| with |extension|.  If |file_name|
-// does not have an extension, them |extension| is added.  If |extention| is
-// empty, then the extension is removed from |file_name|.
-void ReplaceExtension(std::wstring* file_name, const std::wstring& extension);
-
 //-----------------------------------------------------------------------------
 // Functions that involve filesystem access or modification:
 
diff --git a/base/file_util_linux.cc b/base/file_util_linux.cc
index f776c91..1d13c89 100644
--- a/base/file_util_linux.cc
+++ b/base/file_util_linux.cc
@@ -15,8 +15,6 @@
 
 namespace file_util {
 
-const wchar_t kPathSeparator = L'/';
-
 bool GetTempDir(FilePath* path) {
   const char* tmp = getenv("TMPDIR");
   if (tmp)
@@ -30,7 +28,7 @@
   int infile = open(from_path.value().c_str(), O_RDONLY);
   if (infile < 0)
     return false;
-  
+
   int outfile = creat(to_path.value().c_str(), 0666);
   if (outfile < 0) {
     close(infile);
diff --git a/base/file_util_unittest.cc b/base/file_util_unittest.cc
index d2cfcfb..90066ff 100644
--- a/base/file_util_unittest.cc
+++ b/base/file_util_unittest.cc
@@ -147,6 +147,8 @@
 #endif
 }
 
+// TODO(port): enable this test for non-Windows.
+#if defined(OS_WIN)
 static const struct InsertBeforeExtensionCase {
   std::wstring path;
   std::wstring suffix;
@@ -204,6 +206,7 @@
     EXPECT_EQ(path, kInsertBeforeExtension[i].result);
   }
 }
+#endif  // defined(OS_WIN)
 
 static const struct filename_case {
   const wchar_t* path;
@@ -785,6 +788,8 @@
   }
 }
 
+// TODO(port): enable this test for non-windows.
+#if defined(OS_WIN)
 static const struct ReplaceExtensionCase {
   std::wstring file_name;
   std::wstring extension;
@@ -827,6 +832,7 @@
   file_util::ReplaceExtension(&result_path, L".baz");
   EXPECT_EQ(path + L".baz", result_path);
 }
+#endif  // defined(OS_WIN)
 
 TEST_F(FileUtilTest, FileEnumeratorTest) {
   // Test an empty directory.
@@ -925,4 +931,56 @@
                                     // (we don't care what).
 }
 
+
+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 {
+  std::wstring path;
+  FilePath::StringType result;
+} kPathComponents[] = {
+  {L"/foo/bar/baz/", FILE_PATH_LITERAL("/|foo|bar|baz|")},
+  {L"/foo/bar/baz", FILE_PATH_LITERAL("/|foo|bar|baz")},
+  {L"e:/foo", FILE_PATH_LITERAL("e:|foo")},
+};
+
+TEST_F(FileUtilTest, PathComponentsTest) {
+  for (size_t i = 0; i < arraysize(kPathComponents); ++i) {
+    FilePath path = FilePath::FromWStringHack(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);
+  }
+}
+
 }  // namespace