OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 class _Path implements Path { | 5 class _Path implements Path { |
6 final String _path; | 6 final String _path; |
| 7 final bool isWindowsShare; |
7 | 8 |
8 _Path(String source) : _path = source; | 9 _Path(String source) : _path = source, isWindowsShare = false; |
9 _Path.fromNative(String source) : _path = _clean(source); | |
10 | 10 |
11 int get hashCode => _path.hashCode; | 11 _Path.fromNative(String source) |
| 12 : _path = _clean(source), isWindowsShare = _isWindowsShare(source); |
| 13 |
| 14 _Path._internal(String this._path, bool this.isWindowsShare); |
12 | 15 |
13 static String _clean(String source) { | 16 static String _clean(String source) { |
14 switch (Platform.operatingSystem) { | 17 if (Platform.operatingSystem == 'windows') return _cleanWindows(source); |
15 case 'windows': | 18 return source; |
16 return _cleanWindows(source); | |
17 default: | |
18 return source; | |
19 } | |
20 } | 19 } |
21 | 20 |
22 static String _cleanWindows(source) { | 21 static String _cleanWindows(String source) { |
23 // Change \ to /. | 22 // Change \ to /. |
24 var clean = source.replaceAll('\\', '/'); | 23 var clean = source.replaceAll('\\', '/'); |
25 // Add / before intial [Drive letter]: | 24 // Add / before intial [Drive letter]: |
26 if (clean.length >= 2 && clean[1] == ':') { | 25 if (clean.length >= 2 && clean[1] == ':') { |
27 clean = '/$clean'; | 26 clean = '/$clean'; |
28 } | 27 } |
| 28 if (_isWindowsShare(source)) { |
| 29 return clean.substring(1, clean.length); |
| 30 } |
29 return clean; | 31 return clean; |
30 } | 32 } |
31 | 33 |
| 34 static bool _isWindowsShare(String source) { |
| 35 return Platform.operatingSystem == 'windows' && source.startsWith('\\\\'); |
| 36 } |
| 37 |
| 38 int get hashCode => _path.hashCode; |
32 bool get isEmpty => _path.isEmpty; | 39 bool get isEmpty => _path.isEmpty; |
33 bool get isAbsolute => _path.startsWith('/'); | 40 bool get isAbsolute => _path.startsWith('/'); |
34 bool get hasTrailingSeparator => _path.endsWith('/'); | 41 bool get hasTrailingSeparator => _path.endsWith('/'); |
35 | 42 |
36 String toString() => _path; | 43 String toString() => _path; |
37 | 44 |
38 Path relativeTo(Path base) { | 45 Path relativeTo(Path base) { |
39 // Throws exception if an unimplemented or impossible case is reached. | 46 // Throws exception if an unimplemented or impossible case is reached. |
40 // Returns a path "relative" such that | 47 // Returns a path "relative" such that |
41 // base.join(relative) == this.canonicalize. | 48 // base.join(relative) == this.canonicalize. |
42 // Throws an exception if no such path exists, or the case is not | 49 // Throws an exception if no such path exists, or the case is not |
43 // implemented yet. | 50 // implemented yet. |
44 var basePath = base.toString(); | 51 var basePath = base.toString(); |
45 if (base.isAbsolute && _path.startsWith(basePath)) { | 52 if (base.isAbsolute && _path.startsWith(basePath) && |
| 53 base.isWindowsShare == isWindowsShare) { |
46 if (_path == basePath) return new Path('.'); | 54 if (_path == basePath) return new Path('.'); |
47 if (base.hasTrailingSeparator) { | 55 if (base.hasTrailingSeparator) { |
48 return new Path(_path.substring(basePath.length)); | 56 return new Path(_path.substring(basePath.length)); |
49 } | 57 } |
50 if (_path[basePath.length] == '/') { | 58 if (_path[basePath.length] == '/') { |
51 return new Path(_path.substring(basePath.length + 1)); | 59 return new Path(_path.substring(basePath.length + 1)); |
52 } | 60 } |
53 } else if (base.isAbsolute && isAbsolute) { | 61 } else if (base.isAbsolute && isAbsolute && |
| 62 base.isWindowsShare == isWindowsShare) { |
54 List<String> baseSegments = base.canonicalize().segments(); | 63 List<String> baseSegments = base.canonicalize().segments(); |
55 List<String> pathSegments = canonicalize().segments(); | 64 List<String> pathSegments = canonicalize().segments(); |
56 int common = 0; | 65 int common = 0; |
57 int length = min(pathSegments.length, baseSegments.length); | 66 int length = min(pathSegments.length, baseSegments.length); |
58 while (common < length && pathSegments[common] == baseSegments[common]) { | 67 while (common < length && pathSegments[common] == baseSegments[common]) { |
59 common++; | 68 common++; |
60 } | 69 } |
61 final sb = new StringBuffer(); | 70 final sb = new StringBuffer(); |
62 | 71 |
63 for (int i = common + 1; i < baseSegments.length; i++) { | 72 for (int i = common + 1; i < baseSegments.length; i++) { |
(...skipping 19 matching lines...) Expand all Loading... |
83 | 92 |
84 Path join(Path further) { | 93 Path join(Path further) { |
85 if (further.isAbsolute) { | 94 if (further.isAbsolute) { |
86 throw new ArgumentError( | 95 throw new ArgumentError( |
87 "Path.join called with absolute Path as argument."); | 96 "Path.join called with absolute Path as argument."); |
88 } | 97 } |
89 if (isEmpty) { | 98 if (isEmpty) { |
90 return further.canonicalize(); | 99 return further.canonicalize(); |
91 } | 100 } |
92 if (hasTrailingSeparator) { | 101 if (hasTrailingSeparator) { |
93 return new Path('$_path${further}').canonicalize(); | 102 var joined = new _Path._internal('$_path${further}', isWindowsShare); |
| 103 return joined.canonicalize(); |
94 } | 104 } |
95 return new Path('$_path/${further}').canonicalize(); | 105 var joined = new _Path._internal('$_path/${further}', isWindowsShare); |
| 106 return joined.canonicalize(); |
96 } | 107 } |
97 | 108 |
98 // Note: The URI RFC names for these operations are normalize, resolve, and | 109 // Note: The URI RFC names for these operations are normalize, resolve, and |
99 // relativize. | 110 // relativize. |
100 Path canonicalize() { | 111 Path canonicalize() { |
101 if (isCanonical) return this; | 112 if (isCanonical) return this; |
102 return makeCanonical(); | 113 return makeCanonical(); |
103 } | 114 } |
104 | 115 |
105 bool get isCanonical { | 116 bool get isCanonical { |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
175 segmentsToJoin.add(''); | 186 segmentsToJoin.add(''); |
176 } else { | 187 } else { |
177 segmentsToJoin.add('.'); | 188 segmentsToJoin.add('.'); |
178 } | 189 } |
179 } else { | 190 } else { |
180 segmentsToJoin.addAll(newSegs); | 191 segmentsToJoin.addAll(newSegs); |
181 if (hasTrailingSeparator) { | 192 if (hasTrailingSeparator) { |
182 segmentsToJoin.add(''); | 193 segmentsToJoin.add(''); |
183 } | 194 } |
184 } | 195 } |
185 return new Path(Strings.join(segmentsToJoin, '/')); | 196 return new _Path._internal(Strings.join(segmentsToJoin, '/'), |
| 197 isWindowsShare); |
186 } | 198 } |
187 | 199 |
188 String toNativePath() { | 200 String toNativePath() { |
189 if (Platform.operatingSystem == 'windows') { | 201 if (Platform.operatingSystem == 'windows') { |
190 String nativePath = _path; | 202 String nativePath = _path; |
191 // Drop '/' before a drive letter. | 203 // Drop '/' before a drive letter. |
192 if (nativePath.length >= 3 && | 204 if (nativePath.length >= 3 && |
193 nativePath.startsWith('/') && | 205 nativePath.startsWith('/') && |
194 nativePath[2] == ':') { | 206 nativePath[2] == ':') { |
195 nativePath = nativePath.substring(1); | 207 nativePath = nativePath.substring(1); |
196 } | 208 } |
197 nativePath = nativePath.replaceAll('/', '\\'); | 209 nativePath = nativePath.replaceAll('/', '\\'); |
| 210 if (isWindowsShare) { |
| 211 return '\\$nativePath'; |
| 212 } |
198 return nativePath; | 213 return nativePath; |
199 } | 214 } |
200 return _path; | 215 return _path; |
201 } | 216 } |
202 | 217 |
203 List<String> segments() { | 218 List<String> segments() { |
204 List result = _path.split('/'); | 219 List result = _path.split('/'); |
205 if (isAbsolute) result.removeRange(0, 1); | 220 if (isAbsolute) result.removeRange(0, 1); |
206 if (hasTrailingSeparator) result.removeLast(); | 221 if (hasTrailingSeparator) result.removeLast(); |
207 return result; | 222 return result; |
208 } | 223 } |
209 | 224 |
210 Path append(String finalSegment) { | 225 Path append(String finalSegment) { |
211 if (isEmpty) { | 226 if (isEmpty) { |
212 return new Path(finalSegment); | 227 return new _Path._internal(finalSegment, isWindowsShare); |
213 } else if (hasTrailingSeparator) { | 228 } else if (hasTrailingSeparator) { |
214 return new Path('$_path$finalSegment'); | 229 return new _Path._internal('$_path$finalSegment', isWindowsShare); |
215 } else { | 230 } else { |
216 return new Path('$_path/$finalSegment'); | 231 return new _Path._internal('$_path/$finalSegment', isWindowsShare); |
217 } | 232 } |
218 } | 233 } |
219 | 234 |
220 String get filenameWithoutExtension { | 235 String get filenameWithoutExtension { |
221 var name = filename; | 236 var name = filename; |
222 if (name == '.' || name == '..') return name; | 237 if (name == '.' || name == '..') return name; |
223 int pos = name.lastIndexOf('.'); | 238 int pos = name.lastIndexOf('.'); |
224 return (pos < 0) ? name : name.substring(0, pos); | 239 return (pos < 0) ? name : name.substring(0, pos); |
225 } | 240 } |
226 | 241 |
227 String get extension { | 242 String get extension { |
228 var name = filename; | 243 var name = filename; |
229 int pos = name.lastIndexOf('.'); | 244 int pos = name.lastIndexOf('.'); |
230 return (pos < 0) ? '' : name.substring(pos + 1); | 245 return (pos < 0) ? '' : name.substring(pos + 1); |
231 } | 246 } |
232 | 247 |
233 Path get directoryPath { | 248 Path get directoryPath { |
234 int pos = _path.lastIndexOf('/'); | 249 int pos = _path.lastIndexOf('/'); |
235 if (pos < 0) return new Path(''); | 250 if (pos < 0) return new Path(''); |
236 while (pos > 0 && _path[pos - 1] == '/') --pos; | 251 while (pos > 0 && _path[pos - 1] == '/') --pos; |
237 return new Path((pos > 0) ? _path.substring(0, pos) : '/'); | 252 var dirPath = (pos > 0) ? _path.substring(0, pos) : '/'; |
| 253 return new _Path._internal(dirPath, isWindowsShare); |
238 } | 254 } |
239 | 255 |
240 String get filename { | 256 String get filename { |
241 int pos = _path.lastIndexOf('/'); | 257 int pos = _path.lastIndexOf('/'); |
242 return _path.substring(pos + 1); | 258 return _path.substring(pos + 1); |
243 } | 259 } |
244 } | 260 } |
OLD | NEW |