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

Side by Side Diff: observatory_pub_packages/path/src/parsed_path.dart

Issue 816693004: Add observatory_pub_packages snapshot to third_party (Closed) Base URL: http://dart.googlecode.com/svn/third_party/
Patch Set: Created 6 years 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) 2013, 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 library path.parsed_path;
6
7 import 'internal_style.dart';
8 import 'style.dart';
9
10 class ParsedPath {
11 /// The [InternalStyle] that was used to parse this path.
12 InternalStyle style;
13
14 /// The absolute root portion of the path, or `null` if the path is relative.
15 /// On POSIX systems, this will be `null` or "/". On Windows, it can be
16 /// `null`, "//" for a UNC path, or something like "C:\" for paths with drive
17 /// letters.
18 String root;
19
20 /// Whether this path is root-relative.
21 ///
22 /// See [Context.isRootRelative].
23 bool isRootRelative;
24
25 /// The path-separated parts of the path. All but the last will be
26 /// directories.
27 List<String> parts;
28
29 /// The path separators preceding each part.
30 ///
31 /// The first one will be an empty string unless the root requires a separator
32 /// between it and the path. The last one will be an empty string unless the
33 /// path ends with a trailing separator.
34 List<String> separators;
35
36 /// The file extension of the last non-empty part, or "" if it doesn't have
37 /// one.
38 String get extension => _splitExtension()[1];
39
40 /// `true` if this is an absolute path.
41 bool get isAbsolute => root != null;
42
43 factory ParsedPath.parse(String path, InternalStyle style) {
44 var before = path;
45
46 // Remove the root prefix, if any.
47 var root = style.getRoot(path);
48 var isRootRelative = style.getRelativeRoot(path) != null;
49 if (root != null) path = path.substring(root.length);
50
51 // Split the parts on path separators.
52 var parts = [];
53 var separators = [];
54
55 var start = 0;
56
57 if (path.isNotEmpty && style.isSeparator(path.codeUnitAt(0))) {
58 separators.add(path[0]);
59 start = 1;
60 } else {
61 separators.add('');
62 }
63
64 for (var i = start; i < path.length; i++) {
65 if (style.isSeparator(path.codeUnitAt(i))) {
66 parts.add(path.substring(start, i));
67 separators.add(path[i]);
68 start = i + 1;
69 }
70 }
71
72 // Add the final part, if any.
73 if (start < path.length) {
74 parts.add(path.substring(start));
75 separators.add('');
76 }
77
78 return new ParsedPath._(style, root, isRootRelative, parts, separators);
79 }
80
81 ParsedPath._(this.style, this.root, this.isRootRelative, this.parts,
82 this.separators);
83
84 String get basename {
85 var copy = this.clone();
86 copy.removeTrailingSeparators();
87 if (copy.parts.isEmpty) return root == null ? '' : root;
88 return copy.parts.last;
89 }
90
91 String get basenameWithoutExtension => _splitExtension()[0];
92
93 bool get hasTrailingSeparator =>
94 !parts.isEmpty && (parts.last == '' || separators.last != '');
95
96 void removeTrailingSeparators() {
97 while (!parts.isEmpty && parts.last == '') {
98 parts.removeLast();
99 separators.removeLast();
100 }
101 if (separators.length > 0) separators[separators.length - 1] = '';
102 }
103
104 void normalize() {
105 // Handle '.', '..', and empty parts.
106 var leadingDoubles = 0;
107 var newParts = [];
108 for (var part in parts) {
109 if (part == '.' || part == '') {
110 // Do nothing. Ignore it.
111 } else if (part == '..') {
112 // Pop the last part off.
113 if (newParts.length > 0) {
114 newParts.removeLast();
115 } else {
116 // Backed out past the beginning, so preserve the "..".
117 leadingDoubles++;
118 }
119 } else {
120 newParts.add(part);
121 }
122 }
123
124 // A relative path can back out from the start directory.
125 if (!isAbsolute) {
126 newParts.insertAll(0, new List.filled(leadingDoubles, '..'));
127 }
128
129 // If we collapsed down to nothing, do ".".
130 if (newParts.length == 0 && !isAbsolute) {
131 newParts.add('.');
132 }
133
134 // Canonicalize separators.
135 var newSeparators = new List.generate(
136 newParts.length, (_) => style.separator, growable: true);
137 newSeparators.insert(0,
138 isAbsolute && newParts.length > 0 && style.needsSeparator(root) ?
139 style.separator : '');
140
141 parts = newParts;
142 separators = newSeparators;
143
144 // Normalize the Windows root if needed.
145 if (root != null && style == Style.windows) {
146 root = root.replaceAll('/', '\\');
147 }
148 removeTrailingSeparators();
149 }
150
151 String toString() {
152 var builder = new StringBuffer();
153 if (root != null) builder.write(root);
154 for (var i = 0; i < parts.length; i++) {
155 builder.write(separators[i]);
156 builder.write(parts[i]);
157 }
158 builder.write(separators.last);
159
160 return builder.toString();
161 }
162
163 /// Splits the last non-empty part of the path into a `[basename, extension`]
164 /// pair.
165 ///
166 /// Returns a two-element list. The first is the name of the file without any
167 /// extension. The second is the extension or "" if it has none.
168 List<String> _splitExtension() {
169 var file = parts.lastWhere((p) => p != '', orElse: () => null);
170
171 if (file == null) return ['', ''];
172 if (file == '..') return ['..', ''];
173
174 var lastDot = file.lastIndexOf('.');
175
176 // If there is no dot, or it's the first character, like '.bashrc', it
177 // doesn't count.
178 if (lastDot <= 0) return [file, ''];
179
180 return [file.substring(0, lastDot), file.substring(lastDot)];
181 }
182
183 ParsedPath clone() => new ParsedPath._(
184 style, root, isRootRelative,
185 new List.from(parts), new List.from(separators));
186 }
187
OLDNEW
« no previous file with comments | « observatory_pub_packages/path/src/internal_style.dart ('k') | observatory_pub_packages/path/src/path_exception.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698