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 |