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

Side by Side Diff: dart/lib/uri/helpers.dart

Issue 10392043: Copy URI top-level helpers to separate file. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/
Patch Set: 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 #library('uri');
6
7 /**
8 * A parsed URI, inspired by Closure's [URI][] class. Implements [RFC-3986][].
9 * [uri]: http://closure-library.googlecode.com/svn/docs/class_goog_Uri.html
10 * [RFC-3986]: http://tools.ietf.org/html/rfc3986#section-4.3)
11 */
12 class Uri {
13 final String scheme;
14 final String userInfo;
15 final String domain;
16 final int port;
17 final String path;
18 final String query;
19 final String fragment;
20
21 Uri.fromString(String uri) : this._fromMatch(_splitRe.firstMatch(uri));
22
23 Uri._fromMatch(Match m) : this(_emptyIfNull(m[_COMPONENT_SCHEME]),
24 _emptyIfNull(m[_COMPONENT_USER_INFO]),
25 _emptyIfNull(m[_COMPONENT_DOMAIN]),
26 _parseIntOrZero(m[_COMPONENT_PORT]),
27 _emptyIfNull(m[_COMPONENT_PATH]),
28 _emptyIfNull(m[_COMPONENT_QUERY_DATA]),
29 _emptyIfNull(m[_COMPONENT_FRAGMENT]));
30
31 const Uri([String this.scheme = "", String this.userInfo ="",
32 String this.domain = "", int this.port = 0,
33 String this.path = "", String this.query = "",
34 String this.fragment = ""]);
35
36 static String _emptyIfNull(String val) => val != null ? val : '';
37
38 static int _parseIntOrZero(String val) {
39 if (val !== null && val != '') {
40 return Math.parseInt(val);
41 } else {
42 return 0;
43 }
44 }
45
46 // NOTE: This code was ported from: closure-library/closure/goog/uri/utils.js
47 static final RegExp _splitRe = const RegExp(
48 '^'
49 '(?:'
50 '([^:/?#.]+)' // scheme - ignore special characters
51 // used by other URL parts such as :,
52 // ?, /, #, and .
53 ':)?'
54 '(?://'
55 '(?:([^/?#]*)@)?' // userInfo
56 '([\\w\\d\\-\\u0100-\\uffff.%]*)'
57 // domain - restrict to letters,
58 // digits, dashes, dots, percent
59 // escapes, and unicode characters.
60 '(?::([0-9]+))?' // port
61 ')?'
62 '([^?#]+)?' // path
63 '(?:\\?([^#]*))?' // query
64 '(?:#(.*))?' // fragment
65 '\$');
66
67 static final _COMPONENT_SCHEME = 1;
68 static final _COMPONENT_USER_INFO = 2;
69 static final _COMPONENT_DOMAIN = 3;
70 static final _COMPONENT_PORT = 4;
71 static final _COMPONENT_PATH = 5;
72 static final _COMPONENT_QUERY_DATA = 6;
73 static final _COMPONENT_FRAGMENT = 7;
74
75 /**
76 * Returns `true` if the URI is absolute.
77 */
78 bool isAbsolute() {
79 if ("" == scheme) return false;
80 if ("" != fragment) return false;
81 return true;
82
83 /* absolute-URI = scheme ":" hier-part [ "?" query ]
84 * hier-part = "//" authority path-abempty
85 * / path-absolute
86 * / path-rootless
87 * / path-empty
88 *
89 * path = path-abempty ; begins with "/" or is empty
90 * / path-absolute ; begins with "/" but not "//"
91 * / path-noscheme ; begins with a non-colon segment
92 * / path-rootless ; begins with a segment
93 * / path-empty ; zero characters
94 *
95 * path-abempty = *( "/" segment )
96 * path-absolute = "/" [ segment-nz *( "/" segment ) ]
97 * path-noscheme = segment-nz-nc *( "/" segment )
98 * path-rootless = segment-nz *( "/" segment )
99 * path-empty = 0<pchar>
100 * segment = *pchar
101 * segment-nz = 1*pchar
102 * segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )
103 * ; non-zero-length segment without any colon ":"
104 *
105 * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
106 */
107 }
108
109 Uri resolve(String uri) {
110 return resolveUri(new Uri.fromString(uri));
111 }
112
113 Uri resolveUri(Uri reference) {
114 // From RFC 3986.
115 String targetScheme;
116 String targetUserInfo;
117 String targetDomain;
118 int targetPort;
119 String targetPath;
120 String targetQuery;
121 if (reference.scheme != "") {
122 targetScheme = reference.scheme;
123 targetUserInfo = reference.userInfo;
124 targetDomain = reference.domain;
125 targetPort = reference.port;
126 targetPath = removeDotSegments(reference.path);
127 targetQuery = reference.query;
128 } else {
129 if (reference.hasAuthority()) {
130 targetUserInfo = reference.userInfo;
131 targetDomain = reference.domain;
132 targetPort = reference.port;
133 targetPath = removeDotSegments(reference.path);
134 targetQuery = reference.query;
135 } else {
136 if (reference.path == "") {
137 targetPath = this.path;
138 if (reference.query != "") {
139 targetQuery = reference.query;
140 } else {
141 targetQuery = this.query;
142 }
143 } else {
144 if (reference.path.startsWith("/")) {
145 targetPath = removeDotSegments(reference.path);
146 } else {
147 targetPath = removeDotSegments(merge(this.path, reference.path));
148 }
149 targetQuery = reference.query;
150 }
151 targetUserInfo = this.userInfo;
152 targetDomain = this.domain;
153 targetPort = this.port;
154 }
155 targetScheme = this.scheme;
156 }
157 return new Uri(targetScheme, targetUserInfo, targetDomain, targetPort,
158 targetPath, targetQuery, reference.fragment);
159 }
160
161 bool hasAuthority() {
162 return (userInfo != "") || (domain != "") || (port != 0);
163 }
164
165 String toString() {
166 StringBuffer sb = new StringBuffer();
167 _addIfNonEmpty(sb, scheme, scheme, ':');
168 if (hasAuthority() || (scheme == "file")) {
169 sb.add("//");
170 _addIfNonEmpty(sb, userInfo, userInfo, "@");
171 sb.add(domain === null ? "null" : domain);
172 if (port != 0) {
173 sb.add(":");
174 sb.add(port.toString());
175 }
176 }
177 sb.add(path === null ? "null" : path);
178 _addIfNonEmpty(sb, query, "?", query);
179 _addIfNonEmpty(sb, fragment, "#", fragment);
180 return sb.toString();
181 }
182
183 static void _addIfNonEmpty(StringBuffer sb, String test,
184 String first, String second) {
185 if ("" != test) {
186 sb.add(first === null ? "null" : first);
187 sb.add(second === null ? "null" : second);
188 }
189 }
190 }
191
192 String merge(String base, String reference) { 5 String merge(String base, String reference) {
193 if (base == "") return "/$reference"; 6 if (base == "") return "/$reference";
194 return "${base.substring(0, base.lastIndexOf("/") + 1)}$reference"; 7 return "${base.substring(0, base.lastIndexOf("/") + 1)}$reference";
195 } 8 }
196 9
197 String removeDotSegments(String path) { 10 String removeDotSegments(String path) {
198 List<String> output = []; 11 List<String> output = [];
199 bool appendSlash = false; 12 bool appendSlash = false;
200 for (String segment in path.split("/")) { 13 for (String segment in path.split("/")) {
201 appendSlash = false; 14 appendSlash = false;
202 if (segment == "..") { 15 if (segment == "..") {
203 if (!output.isEmpty() && 16 if (!output.isEmpty() &&
204 ((output.length != 1) || (output[0] != ""))) output.removeLast(); 17 ((output.length != 1) || (output[0] != ""))) output.removeLast();
205 appendSlash = true; 18 appendSlash = true;
206 } else if ("." == segment) { 19 } else if ("." == segment) {
207 appendSlash = true; 20 appendSlash = true;
208 } else { 21 } else {
209 output.add(segment); 22 output.add(segment);
210 } 23 }
211 } 24 }
212 if (appendSlash) output.add(""); 25 if (appendSlash) output.add("");
213 return Strings.join(output, "/"); 26 return Strings.join(output, "/");
214 } 27 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698