Index: base/file_path.cc |
=================================================================== |
--- base/file_path.cc (revision 7805) |
+++ base/file_path.cc (working copy) |
@@ -21,6 +21,9 @@ |
const FilePath::CharType FilePath::kCurrentDirectory[] = FILE_PATH_LITERAL("."); |
const FilePath::CharType FilePath::kParentDirectory[] = FILE_PATH_LITERAL(".."); |
+const FilePath::CharType FilePath::kExtensionSeparator = FILE_PATH_LITERAL('.'); |
+ |
+ |
namespace { |
// If this FilePath contains a drive letter specification, returns the |
@@ -38,10 +41,8 @@ |
(path[0] >= L'a' && path[0] <= L'z'))) { |
return 1; |
} |
+#endif // FILE_PATH_USES_DRIVE_LETTERS |
return FilePath::StringType::npos; |
-#else // FILE_PATH_USES_DRIVE_LETTERS |
- return FilePath::StringType::npos; |
-#endif // FILE_PATH_USES_DRIVE_LETTERS |
} |
bool IsPathAbsolute(const FilePath::StringType& path) { |
@@ -136,7 +137,83 @@ |
return new_path; |
} |
-FilePath FilePath::Append(const FilePath::StringType& component) const { |
+FilePath::StringType FilePath::Extension() const { |
+ // BaseName() calls StripTrailingSeparators, so cases like /foo.baz/// work. |
+ StringType base = BaseName().value(); |
+ |
+ // Special case "." and ".." |
+ if (base == kCurrentDirectory || base == kParentDirectory) |
+ return StringType(); |
+ |
+ const StringType::size_type last_dot = base.rfind(kExtensionSeparator); |
+ if (last_dot == StringType::npos) |
+ return StringType(); |
+ return StringType(base, last_dot); |
+} |
+ |
+FilePath FilePath::RemoveExtension() const { |
+ StringType ext = Extension(); |
+ // It's important to check Extension() since that verifies that the |
+ // kExtensionSeparator actually appeared in the last path component. |
+ if (ext.empty()) |
+ return FilePath(path_); |
+ // Since Extension() verified that the extension is in fact in the last path |
+ // component, this substr will effectively strip trailing separators. |
+ const StringType::size_type last_dot = path_.rfind(kExtensionSeparator); |
+ return FilePath(path_.substr(0, last_dot)); |
+} |
+ |
+FilePath FilePath::InsertBeforeExtension(const StringType& suffix) const { |
+ if (suffix.empty()) |
+ return FilePath(path_); |
+ |
+ if (path_.empty()) |
+ return FilePath(); |
+ |
+ StringType base = BaseName().value(); |
+ if (base.empty()) |
+ return FilePath(); |
+ if (*(base.end() - 1) == kExtensionSeparator) { |
+ // Special case "." and ".." |
+ if (base == kCurrentDirectory || base == kParentDirectory) { |
+ return FilePath(); |
+ } |
+ } |
+ |
+ StringType ext = Extension(); |
+ StringType ret = RemoveExtension().value(); |
+ ret.append(suffix); |
+ ret.append(ext); |
+ return FilePath(ret); |
+} |
+ |
+FilePath FilePath::ReplaceExtension(const StringType& extension) const { |
+ if (path_.empty()) |
+ return FilePath(); |
+ |
+ StringType base = BaseName().value(); |
+ if (base.empty()) |
+ return FilePath(); |
+ if (*(base.end() - 1) == kExtensionSeparator) { |
+ // Special case "." and ".." |
+ if (base == kCurrentDirectory || base == kParentDirectory) { |
+ return FilePath(); |
+ } |
+ } |
+ |
+ FilePath no_ext = RemoveExtension(); |
+ // If the new extension is "" or ".", then just remove the current extension. |
+ if (extension.empty() || extension == StringType(1, kExtensionSeparator)) |
+ return no_ext; |
+ |
+ StringType str = no_ext.value(); |
+ if (extension[0] != kExtensionSeparator) |
+ str.append(1, kExtensionSeparator); |
+ str.append(extension); |
+ return FilePath(str); |
+} |
+ |
+FilePath FilePath::Append(const StringType& component) const { |
DCHECK(!IsPathAbsolute(component)); |
if (path_.compare(kCurrentDirectory) == 0) { |
// Append normally doesn't do any normalization, but as a special case, |