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

Side by Side Diff: runtime/bin/path_impl.dart

Issue 11337019: Use patching for dart:io. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comments Created 8 years, 1 month 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 class _Path implements Path {
6 final String _path;
7
8 _Path(String source) : _path = source;
9 _Path.fromNative(String source) : _path = _clean(source);
10
11 int get hashCode => _path.hashCode;
12
13 static String _clean(String source) {
14 switch (Platform.operatingSystem) {
15 case 'windows':
16 return _cleanWindows(source);
17 default:
18 return source;
19 }
20 }
21
22 static String _cleanWindows(source) {
23 // Change \ to /.
24 var clean = source.replaceAll('\\', '/');
25 // Add / before intial [Drive letter]:
26 if (clean.length >= 2 && clean[1] == ':') {
27 clean = '/$clean';
28 }
29 return clean;
30 }
31
32 bool get isEmpty => _path.isEmpty;
33 bool get isAbsolute => _path.startsWith('/');
34 bool get hasTrailingSeparator => _path.endsWith('/');
35
36 String toString() => _path;
37
38 Path relativeTo(Path base) {
39 // Throws exception if an unimplemented or impossible case is reached.
40 // Returns a path "relative" such that
41 // base.join(relative) == this.canonicalize.
42 // Throws an exception if no such path exists, or the case is not
43 // implemented yet.
44 var basePath = base.toString();
45 if (base.isAbsolute && _path.startsWith(basePath)) {
46 if (_path == basePath) return new Path('.');
47 if (base.hasTrailingSeparator) {
48 return new Path(_path.substring(basePath.length));
49 }
50 if (_path[basePath.length] == '/') {
51 return new Path(_path.substring(basePath.length + 1));
52 }
53 } else if (base.isAbsolute && isAbsolute) {
54 List<String> baseSegments = base.canonicalize().segments();
55 List<String> pathSegments = canonicalize().segments();
56 int common = 0;
57 int length = min(pathSegments.length, baseSegments.length);
58 while (common < length && pathSegments[common] == baseSegments[common]) {
59 common++;
60 }
61 final sb = new StringBuffer();
62
63 for (int i = common + 1; i < baseSegments.length; i++) {
64 sb.add('../');
65 }
66 if (base.hasTrailingSeparator) {
67 sb.add('../');
68 }
69 for (int i = common; i < pathSegments.length - 1; i++) {
70 sb.add('${pathSegments[i]}/');
71 }
72 sb.add('${pathSegments.last}');
73 if (hasTrailingSeparator) {
74 sb.add('/');
75 }
76 return new Path(sb.toString());
77 }
78 throw new NotImplementedException(
79 "Unimplemented case of Path.relativeTo(base):\n"
80 " Only absolute paths are handled at present.\n"
81 " Arguments: $_path.relativeTo($base)");
82 }
83
84 Path join(Path further) {
85 if (further.isAbsolute) {
86 throw new ArgumentError(
87 "Path.join called with absolute Path as argument.");
88 }
89 if (isEmpty) {
90 return further.canonicalize();
91 }
92 if (hasTrailingSeparator) {
93 return new Path('$_path${further}').canonicalize();
94 }
95 return new Path('$_path/${further}').canonicalize();
96 }
97
98 // Note: The URI RFC names for these operations are normalize, resolve, and
99 // relativize.
100 Path canonicalize() {
101 if (isCanonical) return this;
102 return makeCanonical();
103 }
104
105 bool get isCanonical {
106 // Contains no consecutive path separators.
107 // Contains no segments that are '.'.
108 // Absolute paths have no segments that are '..'.
109 // All '..' segments of a relative path are at the beginning.
110 if (isEmpty) return false; // The canonical form of '' is '.'.
111 if (_path == '.') return true;
112 List segs = _path.split('/'); // Don't mask the getter 'segments'.
113 if (segs[0] == '') { // Absolute path
114 segs[0] = null; // Faster than removeRange().
115 } else { // A canonical relative path may start with .. segments.
116 for (int pos = 0;
117 pos < segs.length && segs[pos] == '..';
118 ++pos) {
119 segs[pos] = null;
120 }
121 }
122 if (segs.last == '') segs.removeLast(); // Path ends with /.
123 // No remaining segments can be ., .., or empty.
124 return !segs.some((s) => s == '' || s == '.' || s == '..');
125 }
126
127 Path makeCanonical() {
128 bool isAbs = isAbsolute;
129 List segs = segments();
130 String drive;
131 if (isAbs &&
132 !segs.isEmpty &&
133 segs[0].length == 2 &&
134 segs[0][1] == ':') {
135 drive = segs[0];
136 segs.removeRange(0, 1);
137 }
138 List newSegs = [];
139 for (String segment in segs) {
140 switch (segment) {
141 case '..':
142 // Absolute paths drop leading .. markers, including after a drive.
143 if (newSegs.isEmpty) {
144 if (isAbs) {
145 // Do nothing: drop the segment.
146 } else {
147 newSegs.add('..');
148 }
149 } else if (newSegs.last == '..') {
150 newSegs.add('..');
151 } else {
152 newSegs.removeLast();
153 }
154 break;
155 case '.':
156 case '':
157 // Do nothing - drop the segment.
158 break;
159 default:
160 newSegs.add(segment);
161 break;
162 }
163 }
164
165 List segmentsToJoin = [];
166 if (isAbs) {
167 segmentsToJoin.add('');
168 if (drive != null) {
169 segmentsToJoin.add(drive);
170 }
171 }
172
173 if (newSegs.isEmpty) {
174 if (isAbs) {
175 segmentsToJoin.add('');
176 } else {
177 segmentsToJoin.add('.');
178 }
179 } else {
180 segmentsToJoin.addAll(newSegs);
181 if (hasTrailingSeparator) {
182 segmentsToJoin.add('');
183 }
184 }
185 return new Path(Strings.join(segmentsToJoin, '/'));
186 }
187
188 String toNativePath() {
189 if (Platform.operatingSystem == 'windows') {
190 String nativePath = _path;
191 // Drop '/' before a drive letter.
192 if (nativePath.length > 3 &&
193 nativePath.startsWith('/') &&
194 nativePath[2] == ':') {
195 nativePath = nativePath.substring(1);
196 }
197 nativePath = nativePath.replaceAll('/', '\\');
198 return nativePath;
199 }
200 return _path;
201 }
202
203 List<String> segments() {
204 List result = _path.split('/');
205 if (isAbsolute) result.removeRange(0, 1);
206 if (hasTrailingSeparator) result.removeLast();
207 return result;
208 }
209
210 Path append(String finalSegment) {
211 if (isEmpty) {
212 return new Path(finalSegment);
213 } else if (hasTrailingSeparator) {
214 return new Path('$_path$finalSegment');
215 } else {
216 return new Path('$_path/$finalSegment');
217 }
218 }
219
220 String get filenameWithoutExtension {
221 var name = filename;
222 if (name == '.' || name == '..') return name;
223 int pos = name.lastIndexOf('.');
224 return (pos < 0) ? name : name.substring(0, pos);
225 }
226
227 String get extension {
228 var name = filename;
229 int pos = name.lastIndexOf('.');
230 return (pos < 0) ? '' : name.substring(pos + 1);
231 }
232
233 Path get directoryPath {
234 int pos = _path.lastIndexOf('/');
235 if (pos < 0) return new Path('');
236 while (pos > 0 && _path[pos - 1] == '/') --pos;
237 return new Path((pos > 0) ? _path.substring(0, pos) : '/');
238 }
239
240 String get filename {
241 int pos = _path.lastIndexOf('/');
242 return _path.substring(pos + 1);
243 }
244 }
OLDNEW
« runtime/bin/io.dart ('K') | « runtime/bin/path.dart ('k') | runtime/bin/platform.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698