Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(455)

Unified Diff: runtime/bin/path_impl.dart

Issue 10417053: Add Path class to dart:io, and add unit tests for it. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Add unit tests for Path, remove test_suite changes. Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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();
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698