| OLD | NEW |
| 1 // Copyright (c) 2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/file_path.h" | 5 #include "base/file_path.h" |
| 6 #include "base/logging.h" | 6 #include "base/logging.h" |
| 7 | 7 |
| 8 // These includes are just for the *Hack functions, and should be removed | 8 // These includes are just for the *Hack functions, and should be removed |
| 9 // when those functions are removed. | 9 // when those functions are removed. |
| 10 #include "base/string_piece.h" | 10 #include "base/string_piece.h" |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 70 | 70 |
| 71 return false; | 71 return false; |
| 72 } | 72 } |
| 73 | 73 |
| 74 // libgen's dirname and basename aren't guaranteed to be thread-safe and aren't | 74 // libgen's dirname and basename aren't guaranteed to be thread-safe and aren't |
| 75 // guaranteed to not modify their input strings, and in fact are implmeneted | 75 // guaranteed to not modify their input strings, and in fact are implmeneted |
| 76 // differently in this regard on different platforms. Don't use them, but | 76 // differently in this regard on different platforms. Don't use them, but |
| 77 // adhere to their behavior. | 77 // adhere to their behavior. |
| 78 FilePath FilePath::DirName() const { | 78 FilePath FilePath::DirName() const { |
| 79 FilePath new_path(path_); | 79 FilePath new_path(path_); |
| 80 new_path.StripTrailingSeparators(); | 80 new_path.StripTrailingSeparatorsInternal(); |
| 81 | 81 |
| 82 // The drive letter, if any, always needs to remain in the output. If there | 82 // The drive letter, if any, always needs to remain in the output. If there |
| 83 // is no drive letter, as will always be the case on platforms which do not | 83 // is no drive letter, as will always be the case on platforms which do not |
| 84 // support drive letters, letter will be npos, or -1, so the comparisons and | 84 // support drive letters, letter will be npos, or -1, so the comparisons and |
| 85 // resizes below using letter will still be valid. | 85 // resizes below using letter will still be valid. |
| 86 StringType::size_type letter = FindDriveLetter(new_path.path_); | 86 StringType::size_type letter = FindDriveLetter(new_path.path_); |
| 87 | 87 |
| 88 StringType::size_type last_separator = | 88 StringType::size_type last_separator = |
| 89 new_path.path_.find_last_of(kSeparators, StringType::npos, | 89 new_path.path_.find_last_of(kSeparators, StringType::npos, |
| 90 arraysize(kSeparators) - 1); | 90 arraysize(kSeparators) - 1); |
| 91 if (last_separator == StringType::npos) { | 91 if (last_separator == StringType::npos) { |
| 92 // path_ is in the current directory. | 92 // path_ is in the current directory. |
| 93 new_path.path_.resize(letter + 1); | 93 new_path.path_.resize(letter + 1); |
| 94 } else if (last_separator == letter + 1) { | 94 } else if (last_separator == letter + 1) { |
| 95 // path_ is in the root directory. | 95 // path_ is in the root directory. |
| 96 new_path.path_.resize(letter + 2); | 96 new_path.path_.resize(letter + 2); |
| 97 } else if (last_separator == letter + 2 && | 97 } else if (last_separator == letter + 2 && |
| 98 IsSeparator(new_path.path_[letter + 1])) { | 98 IsSeparator(new_path.path_[letter + 1])) { |
| 99 // path_ is in "//" (possibly with a drive letter); leave the double | 99 // path_ is in "//" (possibly with a drive letter); leave the double |
| 100 // separator intact indicating alternate root. | 100 // separator intact indicating alternate root. |
| 101 new_path.path_.resize(letter + 3); | 101 new_path.path_.resize(letter + 3); |
| 102 } else if (last_separator != 0) { | 102 } else if (last_separator != 0) { |
| 103 // path_ is somewhere else, trim the basename. | 103 // path_ is somewhere else, trim the basename. |
| 104 new_path.path_.resize(last_separator); | 104 new_path.path_.resize(last_separator); |
| 105 } | 105 } |
| 106 | 106 |
| 107 new_path.StripTrailingSeparators(); | 107 new_path.StripTrailingSeparatorsInternal(); |
| 108 if (!new_path.path_.length()) | 108 if (!new_path.path_.length()) |
| 109 new_path.path_ = kCurrentDirectory; | 109 new_path.path_ = kCurrentDirectory; |
| 110 | 110 |
| 111 return new_path; | 111 return new_path; |
| 112 } | 112 } |
| 113 | 113 |
| 114 FilePath FilePath::BaseName() const { | 114 FilePath FilePath::BaseName() const { |
| 115 FilePath new_path(path_); | 115 FilePath new_path(path_); |
| 116 new_path.StripTrailingSeparators(); | 116 new_path.StripTrailingSeparatorsInternal(); |
| 117 | 117 |
| 118 // The drive letter, if any, is always stripped. | 118 // The drive letter, if any, is always stripped. |
| 119 StringType::size_type letter = FindDriveLetter(new_path.path_); | 119 StringType::size_type letter = FindDriveLetter(new_path.path_); |
| 120 if (letter != StringType::npos) { | 120 if (letter != StringType::npos) { |
| 121 new_path.path_.erase(0, letter + 1); | 121 new_path.path_.erase(0, letter + 1); |
| 122 } | 122 } |
| 123 | 123 |
| 124 // Keep everything after the final separator, but if the pathname is only | 124 // Keep everything after the final separator, but if the pathname is only |
| 125 // one character and it's a separator, leave it alone. | 125 // one character and it's a separator, leave it alone. |
| 126 StringType::size_type last_separator = | 126 StringType::size_type last_separator = |
| (...skipping 14 matching lines...) Expand all Loading... |
| 141 // when appending to kCurrentDirectory, just return a new path for the | 141 // when appending to kCurrentDirectory, just return a new path for the |
| 142 // component argument. Appending component to kCurrentDirectory would | 142 // component argument. Appending component to kCurrentDirectory would |
| 143 // serve no purpose other than needlessly lengthening the path, and | 143 // serve no purpose other than needlessly lengthening the path, and |
| 144 // it's likely in practice to wind up with FilePath objects containing | 144 // it's likely in practice to wind up with FilePath objects containing |
| 145 // only kCurrentDirectory when calling DirName on a single relative path | 145 // only kCurrentDirectory when calling DirName on a single relative path |
| 146 // component. | 146 // component. |
| 147 return FilePath(component); | 147 return FilePath(component); |
| 148 } | 148 } |
| 149 | 149 |
| 150 FilePath new_path(path_); | 150 FilePath new_path(path_); |
| 151 new_path.StripTrailingSeparators(); | 151 new_path.StripTrailingSeparatorsInternal(); |
| 152 | 152 |
| 153 // Don't append a separator if the path is empty (indicating the current | 153 // Don't append a separator if the path is empty (indicating the current |
| 154 // directory) or if the path component is empty (indicating nothing to | 154 // directory) or if the path component is empty (indicating nothing to |
| 155 // append). | 155 // append). |
| 156 if (component.length() > 0 && new_path.path_.length() > 0) { | 156 if (component.length() > 0 && new_path.path_.length() > 0) { |
| 157 | 157 |
| 158 // Don't append a separator if the path still ends with a trailing | 158 // Don't append a separator if the path still ends with a trailing |
| 159 // separator after stripping (indicating the root directory). | 159 // separator after stripping (indicating the root directory). |
| 160 if (!IsSeparator(new_path.path_[new_path.path_.length() - 1])) { | 160 if (!IsSeparator(new_path.path_[new_path.path_.length() - 1])) { |
| 161 | 161 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 194 #elif defined(OS_WIN) | 194 #elif defined(OS_WIN) |
| 195 // static | 195 // static |
| 196 FilePath FilePath::FromWStringHack(const std::wstring& wstring) { | 196 FilePath FilePath::FromWStringHack(const std::wstring& wstring) { |
| 197 return FilePath(wstring); | 197 return FilePath(wstring); |
| 198 } | 198 } |
| 199 std::wstring FilePath::ToWStringHack() const { | 199 std::wstring FilePath::ToWStringHack() const { |
| 200 return path_; | 200 return path_; |
| 201 } | 201 } |
| 202 #endif | 202 #endif |
| 203 | 203 |
| 204 void FilePath::StripTrailingSeparators() { | 204 FilePath FilePath::StripTrailingSeparators() const { |
| 205 FilePath new_path(path_); |
| 206 new_path.StripTrailingSeparatorsInternal(); |
| 207 |
| 208 return new_path; |
| 209 } |
| 210 |
| 211 void FilePath::StripTrailingSeparatorsInternal() { |
| 205 // If there is no drive letter, start will be 1, which will prevent stripping | 212 // If there is no drive letter, start will be 1, which will prevent stripping |
| 206 // the leading separator if there is only one separator. If there is a drive | 213 // the leading separator if there is only one separator. If there is a drive |
| 207 // letter, start will be set appropriately to prevent stripping the first | 214 // letter, start will be set appropriately to prevent stripping the first |
| 208 // separator following the drive letter, if a separator immediately follows | 215 // separator following the drive letter, if a separator immediately follows |
| 209 // the drive letter. | 216 // the drive letter. |
| 210 StringType::size_type start = FindDriveLetter(path_) + 2; | 217 StringType::size_type start = FindDriveLetter(path_) + 2; |
| 211 | 218 |
| 212 StringType::size_type last_stripped = StringType::npos; | 219 StringType::size_type last_stripped = StringType::npos; |
| 213 for (StringType::size_type pos = path_.length(); | 220 for (StringType::size_type pos = path_.length(); |
| 214 pos > start && IsSeparator(path_[pos - 1]); | 221 pos > start && IsSeparator(path_[pos - 1]); |
| 215 --pos) { | 222 --pos) { |
| 216 // If the string only has two separators and they're at the beginning, | 223 // If the string only has two separators and they're at the beginning, |
| 217 // don't strip them, unless the string began with more than two separators. | 224 // don't strip them, unless the string began with more than two separators. |
| 218 if (pos != start + 1 || last_stripped == start + 2 || | 225 if (pos != start + 1 || last_stripped == start + 2 || |
| 219 !IsSeparator(path_[start - 1])) { | 226 !IsSeparator(path_[start - 1])) { |
| 220 path_.resize(pos - 1); | 227 path_.resize(pos - 1); |
| 221 last_stripped = pos; | 228 last_stripped = pos; |
| 222 } | 229 } |
| 223 } | 230 } |
| 224 } | 231 } |
| OLD | NEW |