Chromium Code Reviews| Index: runtime/bin/path_impl.dart |
| diff --git a/runtime/bin/path_impl.dart b/runtime/bin/path_impl.dart |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..ee47aea2f325ff92ed760ee45afb446359e62890 |
| --- /dev/null |
| +++ b/runtime/bin/path_impl.dart |
| @@ -0,0 +1,139 @@ |
| +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| +// for details. All rights reserved. Use of this source code is governed by a |
| +// BSD-style license that can be found in the LICENSE file. |
| + |
| +class _PathImpl implements Path { |
| + final String path; |
| + _PathImpl(String source) : path = _clean(source); |
| + const _PathImpl.c(String source) : path = source; |
|
Mads Ager (google)
2012/05/29 07:36:02
const _PathImpl.c(String this.path);
?
Where do y
Bill Hesse
2012/05/31 15:55:10
Done.
|
| + |
| + static String _clean(String source) { |
| + switch (Platform.operatingSystem) { |
| + case 'windows': |
| + return _cleanWindows(source); |
| + default: |
| + return _cleanPosix(source); |
| + } |
| + } |
| + |
| + static String _cleanWindows(source) { |
| + // Change \ to /. |
| + var clean = source.replaceAll('\\', '/'); |
| + // Add / before intial [Drive letter]: |
| + if (const RegExp(@'^[a-zA-Z]:').hasMatch(clean)) { |
|
Søren Gjesse
2012/05/29 07:18:01
Just
if (clean.length > 1 && clean[1] = ":")
i
Bill Hesse
2012/05/31 15:55:10
Done.
|
| + clean = '/$clean'; |
| + } |
| + return _cleanPosix(clean); |
| + } |
| + |
| + static String _cleanPosix(source) { |
| + // Change //+ to / (remove all consecutive / marks). |
| + var clean = source.replaceAll(const RegExp('//+'), '/'); |
| + return clean; |
| + } |
| + |
| + bool isEmpty() => path == ''; |
|
Mads Ager (google)
2012/05/29 07:36:02
Add 'get' and either remove the blank line below o
Bill Hesse
2012/05/31 15:55:10
Done.
|
| + |
| + bool get isAbsolute() => path.startsWith('/'); |
| + bool get isDirectory() => path.endsWith('/') || isEmpty(); |
|
Bob Nystrom
2012/05/30 17:58:37
When you make isEmpty a getter, don't forget to re
Bill Hesse
2012/05/31 15:55:10
Removed this case from hasTrailingSlash.
|
| + |
| + String toString() => path; |
| + |
| + Path relativeTo(Path base) { |
| + // Throws exception if not doable. |
| + // Unimplemented |
| + if (base.isAbsolute && path.startsWith(base.path)) { |
| + if (path == base.path) return new Path('.'); |
| + if (path[base.path.length] == '/') { |
| + return new Path(path.substring(base.path.length + 1)); |
| + } |
| + } |
| + throw "Unimplemented case ofPath.relativeTo(base):" |
|
Bill Hesse
2012/05/25 13:14:38
Switch to throw PathException (or UnimplementedExc
Mads Ager (google)
2012/05/29 07:36:02
I would throw a PathException and be very clear ab
Bill Hesse
2012/05/31 15:55:10
The PathException class is removed. Throwing an U
|
| + "Path $path relative to ${base.path}"; |
| + } |
| + |
| + Path join(Path further) { |
| + if (further.isAbsolute) { |
|
Bill Hesse
2012/05/25 13:14:38
PathException.
Bob Nystrom
2012/05/30 17:58:37
Better: IllegalArgumentException.
Bill Hesse
2012/05/31 15:55:10
Done.
|
| + throw "Make a path exception class, and throw it: join with absolute"; |
| + } |
| + return new Path('$path/${further.path}'); |
| + // Canonicalize? |
|
Mads Ager (google)
2012/05/29 07:36:02
Add TODO(whesse):
Bill Hesse
2012/05/31 15:55:10
Done.
|
| + } |
| + |
| + Path safeJoin(Path further) => join(further); |
|
Mads Ager (google)
2012/05/29 07:36:02
This is not in the interface. What is it used for?
Bill Hesse
2012/05/31 15:55:10
Added to the interface. It joins two paths, check
|
| + |
| + Path canonicalize() { |
| + if (isCanonical) return this; |
| + return makeCanonical(); |
| + } |
| + |
| + bool get isCanonical() { |
| + // Contains no consecutive /s. |
| + // Contains no . components. |
| + // Absolute paths have no .. components. |
| + // All .. components of a relative path are initial. |
| + List components = path.split('/'); |
| + if (components[0] == '') { // Absolute path |
| + components.removeRange(0, 1); |
|
Mads Ager (google)
2012/05/29 07:36:02
I would use indices instead of copying 'components
Bill Hesse
2012/05/31 15:55:10
Yes, that would be better.
Bill Hesse
2012/05/31 15:55:10
Fixed using indices, but keeping the components.so
|
| + } else { // Relative path starting with .. components. |
| + while (!components.isEmpty() && components[0] == '..') { |
| + components.removeRange(0, 1); |
| + } |
| + } |
| + if (components.isEmpty()) return true; |
| + if (components.last() == '') components.removeLast(); // Path ends with /. |
| + // No remaining components can be ., .., or empty. |
| + return !components.some((c) => c == '..' || c == '.' || c == ''); |
| + } |
| + |
| + Path makeCanonical() { |
| + bool absolute = isAbsolute; |
| + // Unimplemented. |
| + throw "Unimplemented Path.makeCanonical()"; |
|
Mads Ager (google)
2012/05/29 07:36:02
NotImplementedException, but it doesn't really mat
Bill Hesse
2012/05/31 15:55:10
Done.
|
| + return this; |
| + } |
| + |
| + String toNativePath() { |
| + if (Platform.operatingSystem == 'windows') { |
| + String nativePath = path; |
| + if (const RegExp(@'^/[a-zA-z]:').hasMatch(nativePath)) { |
|
Mads Ager (google)
2012/05/29 07:36:02
I guess you could just check for '/' and maybe ':'
Bill Hesse
2012/05/31 15:55:10
Done.
Bill Hesse
2012/05/31 15:55:10
Done.
|
| + nativePath = nativePath = substring(1); |
| + } |
| + nativePath = nativePath.replace('/', '\\'); |
| + return nativePath; |
| + } |
| + return path; |
| + } |
| + |
| + String last() { |
|
Mads Ager (google)
2012/05/29 07:36:02
Make this private since it is not part of the inte
Bill Hesse
2012/05/31 15:55:10
removed.
|
| + int pos = path.lastIndexOf('/'); |
| + return path.substring(pos+1); |
|
Søren Gjesse
2012/05/29 07:18:01
Spaces on both sides of +.
Bill Hesse
2012/05/31 15:55:10
Done.
Bill Hesse
2012/05/31 15:55:10
Done.
|
| + } |
| + |
| + Path dropLast() { |
|
Mads Ager (google)
2012/05/29 07:36:02
Move the code to dirname which is the only user. I
Bill Hesse
2012/05/31 15:55:10
Done.
Bill Hesse
2012/05/31 15:55:10
Done.
|
| + int pos = path.lastIndexOf('/'); |
| + if (pos < 0) return new Path(''); |
| + // while (pos > 0 && path[pos - 1] == '/') --pos; |
|
Mads Ager (google)
2012/05/29 07:36:02
Code in comments.
Bill Hesse
2012/05/31 15:55:10
Uncommented, because we don't always clean consecu
|
| + return new Path((pos > 0) ? path.substring(0, pos) : '/'); |
| + } |
| + |
| + String basename() { |
| + var name = last(); |
| + int pos = name.lastIndexOf('.'); |
| + return (pos < 0) ? name : name.substring(0, pos); |
| + } |
| + |
| + String extension() { |
| + var name = last(); |
| + int pos = name.lastIndexOf('.'); |
| + return (pos < 0) ? '' : name.substring(pos + 1); |
| + } |
| + |
| + Path dirname() { |
| + return dropLast(); |
| + } |
| + |
| + String filename() { |
| + return last(); |
| + } |
| +} |