| 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 | 7 |
| 8 const _Path(String source) : path = source; | 8 const _Path(String source) : _path = source; |
| 9 _Path.fromNative(String source) : path = _clean(source); | 9 _Path.fromNative(String source) : _path = _clean(source); |
| 10 | 10 |
| 11 static String _clean(String source) { | 11 static String _clean(String source) { |
| 12 switch (Platform.operatingSystem) { | 12 switch (Platform.operatingSystem) { |
| 13 case 'windows': | 13 case 'windows': |
| 14 return _cleanWindows(source); | 14 return _cleanWindows(source); |
| 15 default: | 15 default: |
| 16 return source; | 16 return source; |
| 17 } | 17 } |
| 18 } | 18 } |
| 19 | 19 |
| 20 static String _cleanWindows(source) { | 20 static String _cleanWindows(source) { |
| 21 // Change \ to /. | 21 // Change \ to /. |
| 22 var clean = source.replaceAll('\\', '/'); | 22 var clean = source.replaceAll('\\', '/'); |
| 23 // Add / before intial [Drive letter]: | 23 // Add / before intial [Drive letter]: |
| 24 if (clean.length >= 2 && clean[1] == ':') { | 24 if (clean.length >= 2 && clean[1] == ':') { |
| 25 clean = '/$clean'; | 25 clean = '/$clean'; |
| 26 } | 26 } |
| 27 return clean; | 27 return clean; |
| 28 } | 28 } |
| 29 | 29 |
| 30 bool get isEmpty() => path.isEmpty(); | 30 bool get isEmpty() => _path.isEmpty(); |
| 31 bool get isAbsolute() => path.startsWith('/'); | 31 bool get isAbsolute() => _path.startsWith('/'); |
| 32 bool get hasTrailingSeparator() => path.endsWith('/'); | 32 bool get hasTrailingSeparator() => _path.endsWith('/'); |
| 33 | 33 |
| 34 String toString() => path; | 34 String toString() => _path; |
| 35 | 35 |
| 36 Path relativeTo(Path base) { | 36 Path relativeTo(Path base) { |
| 37 // Throws exception if an unimplemented or impossible case is reached. | 37 // Throws exception if an unimplemented or impossible case is reached. |
| 38 // Returns a path "relative" such that | 38 // Returns a path "relative" such that |
| 39 // base.join(relative) == this.canonlicalize. | 39 // base.join(relative) == this.canonicalize. |
| 40 // Throws an exception if no such path exists, or the case is not | 40 // Throws an exception if no such path exists, or the case is not |
| 41 // implemented yet. | 41 // implemented yet. |
| 42 if (base.isAbsolute && path.startsWith(base.path)) { | 42 if (base.isAbsolute && _path.startsWith(base._path)) { |
| 43 if (path == base.path) return new Path('.'); | 43 if (_path == base._path) return new Path('.'); |
| 44 if (path[base.path.length] == '/') { | 44 if (base.hasTrailingSeparator) { |
| 45 return new Path(path.substring(base.path.length + 1)); | 45 return new Path(_path.substring(base._path.length)); |
| 46 } |
| 47 if (_path[base._path.length] == '/') { |
| 48 return new Path(_path.substring(base._path.length + 1)); |
| 46 } | 49 } |
| 47 } | 50 } |
| 48 throw new NotImplementedException( | 51 throw new NotImplementedException( |
| 49 "Unimplemented case of Path.relativeTo(base):\n" | 52 "Unimplemented case of Path.relativeTo(base):\n" |
| 50 " Only absolute paths with strict containment are handled at present.\n" | 53 " Only absolute paths with strict containment are handled at present.\n" |
| 51 " Arguments: $path.relativeTo($base)"); | 54 " Arguments: $_path.relativeTo($base)"); |
| 52 } | 55 } |
| 53 | 56 |
| 54 Path join(Path further) { | 57 Path join(Path further) { |
| 55 if (further.isAbsolute) { | 58 if (further.isAbsolute) { |
| 56 throw new IllegalArgumentException( | 59 throw new IllegalArgumentException( |
| 57 "Path.join called with absolute Path as argument."); | 60 "Path.join called with absolute Path as argument."); |
| 58 } | 61 } |
| 59 if (isEmpty) { | 62 if (isEmpty) { |
| 60 return further.canonicalize(); | 63 return further.canonicalize(); |
| 61 } | 64 } |
| 62 if (hasTrailingSeparator) { | 65 if (hasTrailingSeparator) { |
| 63 return new Path('$path${further.path}').canonicalize(); | 66 return new Path('$_path${further._path}').canonicalize(); |
| 64 } | 67 } |
| 65 return new Path('$path/${further.path}').canonicalize(); | 68 return new Path('$_path/${further._path}').canonicalize(); |
| 66 } | 69 } |
| 67 | 70 |
| 68 // Note: The URI RFC names for these operations are normalize, resolve, and | 71 // Note: The URI RFC names for these operations are normalize, resolve, and |
| 69 // relativize. | 72 // relativize. |
| 70 Path canonicalize() { | 73 Path canonicalize() { |
| 71 if (isCanonical) return this; | 74 if (isCanonical) return this; |
| 72 return makeCanonical(); | 75 return makeCanonical(); |
| 73 } | 76 } |
| 74 | 77 |
| 75 bool get isCanonical() { | 78 bool get isCanonical() { |
| 76 // Contains no consecutive path separators. | 79 // Contains no consecutive path separators. |
| 77 // Contains no segments that are '.'. | 80 // Contains no segments that are '.'. |
| 78 // Absolute paths have no segments that are '..'. | 81 // Absolute paths have no segments that are '..'. |
| 79 // All '..' segments of a relative path are at the beginning. | 82 // All '..' segments of a relative path are at the beginning. |
| 80 if (isEmpty) return false; // The canonical form of '' is '.'. | 83 if (isEmpty) return false; // The canonical form of '' is '.'. |
| 81 if (path == '.') return true; | 84 if (_path == '.') return true; |
| 82 List segs = path.split('/'); // Don't mask the getter 'segments'. | 85 List segs = _path.split('/'); // Don't mask the getter 'segments'. |
| 83 if (segs[0] == '') { // Absolute path | 86 if (segs[0] == '') { // Absolute path |
| 84 segs[0] = null; // Faster than removeRange(). | 87 segs[0] = null; // Faster than removeRange(). |
| 85 } else { // A canonical relative path may start with .. segments. | 88 } else { // A canonical relative path may start with .. segments. |
| 86 for (int pos = 0; | 89 for (int pos = 0; |
| 87 pos < segs.length && segs[pos] == '..'; | 90 pos < segs.length && segs[pos] == '..'; |
| 88 ++pos) { | 91 ++pos) { |
| 89 segs[pos] = null; | 92 segs[pos] = null; |
| 90 } | 93 } |
| 91 } | 94 } |
| 92 if (segs.last() == '') segs.removeLast(); // Path ends with /. | 95 if (segs.last() == '') segs.removeLast(); // Path ends with /. |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 148 } | 151 } |
| 149 } else { | 152 } else { |
| 150 segmentsToJoin.addAll(newSegs); | 153 segmentsToJoin.addAll(newSegs); |
| 151 if (hasTrailingSeparator) { | 154 if (hasTrailingSeparator) { |
| 152 segmentsToJoin.add(''); | 155 segmentsToJoin.add(''); |
| 153 } | 156 } |
| 154 } | 157 } |
| 155 return new Path(Strings.join(segmentsToJoin, '/')); | 158 return new Path(Strings.join(segmentsToJoin, '/')); |
| 156 } | 159 } |
| 157 | 160 |
| 158 | |
| 159 String toNativePath() { | 161 String toNativePath() { |
| 160 if (Platform.operatingSystem == 'windows') { | 162 if (Platform.operatingSystem == 'windows') { |
| 161 String nativePath = path; | 163 String nativePath = _path; |
| 162 // Drop '/' before a drive letter. | 164 // Drop '/' before a drive letter. |
| 163 if (nativePath.startsWith('/') && nativePath[2] == ':') { | 165 if (nativePath.startsWith('/') && nativePath[2] == ':') { |
| 164 nativePath = nativePath.substring(1); | 166 nativePath = nativePath.substring(1); |
| 165 } | 167 } |
| 166 nativePath = nativePath.replaceAll('/', '\\'); | 168 nativePath = nativePath.replaceAll('/', '\\'); |
| 167 return nativePath; | 169 return nativePath; |
| 168 } | 170 } |
| 169 return path; | 171 return _path; |
| 170 } | 172 } |
| 171 | 173 |
| 172 List<String> segments() { | 174 List<String> segments() { |
| 173 List result = path.split('/'); | 175 List result = _path.split('/'); |
| 174 if (isAbsolute) result.removeRange(0, 1); | 176 if (isAbsolute) result.removeRange(0, 1); |
| 175 if (hasTrailingSeparator) result.removeLast(); | 177 if (hasTrailingSeparator) result.removeLast(); |
| 176 return result; | 178 return result; |
| 177 } | 179 } |
| 178 | 180 |
| 181 Path append(String finalSegment) { |
| 182 if (hasTrailingSeparator) { |
| 183 return new Path('$_path$finalSegment'); |
| 184 } else { |
| 185 return new Path('$_path/$finalSegment'); |
| 186 } |
| 187 } |
| 188 |
| 179 String get filenameWithoutExtension() { | 189 String get filenameWithoutExtension() { |
| 180 var name = filename; | 190 var name = filename; |
| 191 if (name == '.' || name == '..') return name; |
| 181 int pos = name.lastIndexOf('.'); | 192 int pos = name.lastIndexOf('.'); |
| 182 return (pos < 0) ? name : name.substring(0, pos); | 193 return (pos < 0) ? name : name.substring(0, pos); |
| 183 } | 194 } |
| 184 | 195 |
| 196 String get pathWithoutExtension() { |
| 197 int slashPos = _path.lastIndexOf('/'); |
| 198 int dotPos = _path.lastIndexOf('.'); |
| 199 if (dotPos > slashPos) { // Includes check for > -1. |
| 200 var name = filename; |
| 201 if (name == '.' || name == '..') return this; |
| 202 return new Path(_path.substring(0, dotPos)); |
| 203 } else { |
| 204 return this; |
| 205 } |
| 206 } |
| 207 |
| 185 String get extension() { | 208 String get extension() { |
| 186 var name = filename; | 209 var name = filename; |
| 187 int pos = name.lastIndexOf('.'); | 210 int pos = name.lastIndexOf('.'); |
| 188 return (pos < 0) ? '' : name.substring(pos + 1); | 211 return (pos < 0) ? '' : name.substring(pos + 1); |
| 189 } | 212 } |
| 190 | 213 |
| 191 Path get directoryPath() { | 214 Path get directoryPath() { |
| 192 int pos = path.lastIndexOf('/'); | 215 int pos = _path.lastIndexOf('/'); |
| 193 if (pos < 0) return new Path(''); | 216 if (pos < 0) return new Path(''); |
| 194 while (pos > 0 && path[pos - 1] == '/') --pos; | 217 while (pos > 0 && _path[pos - 1] == '/') --pos; |
| 195 return new Path((pos > 0) ? path.substring(0, pos) : '/'); | 218 return new Path((pos > 0) ? _path.substring(0, pos) : '/'); |
| 196 } | 219 } |
| 197 | 220 |
| 198 String get filename() { | 221 String get filename() { |
| 199 int pos = path.lastIndexOf('/'); | 222 int pos = _path.lastIndexOf('/'); |
| 200 return path.substring(pos + 1); | 223 return _path.substring(pos + 1); |
| 201 } | 224 } |
| 202 } | 225 } |
| OLD | NEW |