Index: sdk/lib/core/uri.dart |
diff --git a/sdk/lib/core/uri.dart b/sdk/lib/core/uri.dart |
index 06bb3ca3b9cfe118e5d31be55e1ad8b6b65fd366..ab56acdbc4dcc5bb84d3b290ce1656d2c61add28 100644 |
--- a/sdk/lib/core/uri.dart |
+++ b/sdk/lib/core/uri.dart |
@@ -146,11 +146,14 @@ class Uri { |
/** |
* Creates a new `Uri` object by parsing a URI string. |
* |
+ * If [start] and [end] are provided, only the substring from `start` |
+ * to `end` is parsed as a URI. |
+ * |
* If the string is not valid as a URI or URI reference, |
* invalid characters will be percent escaped where possible. |
* The resulting `Uri` will represent a valid URI or URI reference. |
*/ |
- static Uri parse(String uri) { |
+ static Uri parse(String uri, [int start = 0, int end]) { |
// This parsing will not validate percent-encoding, IPv6, etc. When done |
// it will call `new Uri(...)` which will perform these validations. |
// This is purely splitting up the URI string into components. |
@@ -216,14 +219,15 @@ class Uri { |
String path = null; |
String query = null; |
String fragment = null; |
+ if (end == null) end = uri.length; |
- int index = 0; |
- int pathStart = 0; |
+ int index = start; |
+ int pathStart = start; |
// End of input-marker. |
int char = EOI; |
void parseAuth() { |
- if (index == uri.length) { |
+ if (index == end) { |
char = EOI; |
return; |
} |
@@ -231,7 +235,7 @@ class Uri { |
int lastColon = -1; |
int lastAt = -1; |
char = uri.codeUnitAt(index); |
- while (index < uri.length) { |
+ while (index < end) { |
char = uri.codeUnitAt(index); |
if (char == _SLASH || char == _QUESTION || char == _NUMBER_SIGN) { |
break; |
@@ -245,7 +249,7 @@ class Uri { |
lastColon = -1; |
int endBracket = uri.indexOf(']', index + 1); |
if (endBracket == -1) { |
- index = uri.length; |
+ index = end; |
char = EOI; |
break; |
} else { |
@@ -277,7 +281,7 @@ class Uri { |
hostEnd = lastColon; |
} |
host = _makeHost(uri, hostStart, hostEnd, true); |
- if (index < uri.length) { |
+ if (index < end) { |
char = uri.codeUnitAt(index); |
} |
} |
@@ -298,22 +302,22 @@ class Uri { |
// All other breaks set their own state. |
int state = NOT_IN_PATH; |
int i = index; // Temporary alias for index to avoid bug 19550 in dart2js. |
- while (i < uri.length) { |
+ while (i < end) { |
char = uri.codeUnitAt(i); |
if (char == _QUESTION || char == _NUMBER_SIGN) { |
state = NOT_IN_PATH; |
break; |
} |
if (char == _SLASH) { |
- state = (i == 0) ? ALLOW_AUTH : IN_PATH; |
+ state = (i == start) ? ALLOW_AUTH : IN_PATH; |
break; |
} |
if (char == _COLON) { |
- if (i == 0) _fail(uri, 0, "Invalid empty scheme"); |
- scheme = _makeScheme(uri, i); |
+ if (i == start) _fail(uri, start, "Invalid empty scheme"); |
+ scheme = _makeScheme(uri, start, i); |
i++; |
pathStart = i; |
- if (i == uri.length) { |
+ if (i == end) { |
char = EOI; |
state = NOT_IN_PATH; |
} else { |
@@ -338,7 +342,7 @@ class Uri { |
// Have seen one slash either at start or right after scheme. |
// If two slashes, it's an authority, otherwise it's just the path. |
index++; |
- if (index == uri.length) { |
+ if (index == end) { |
char = EOI; |
state = NOT_IN_PATH; |
} else { |
@@ -360,7 +364,7 @@ class Uri { |
if (state == IN_PATH) { |
// Characters from pathStart to index (inclusive) are known |
// to be part of the path. |
- while (++index < uri.length) { |
+ while (++index < end) { |
char = uri.codeUnitAt(index); |
if (char == _QUESTION || char == _NUMBER_SIGN) { |
break; |
@@ -376,15 +380,21 @@ class Uri { |
path = _makePath(uri, pathStart, index, null, ensureLeadingSlash, isFile); |
if (char == _QUESTION) { |
- int numberSignIndex = uri.indexOf('#', index + 1); |
Søren Gjesse
2015/04/09 07:04:42
We could add an optional end to indexOf as well...
Lasse Reichstein Nielsen
2015/04/09 07:52:03
I actually thought about that, but it doesn't work
|
+ int numberSignIndex = -1; |
+ for (int i = index + 1; i < end; i++) { |
+ if (uri.codeUnitAt(i) == _NUMBER_SIGN) { |
+ numberSignIndex = i; |
+ break; |
+ } |
+ } |
if (numberSignIndex < 0) { |
- query = _makeQuery(uri, index + 1, uri.length, null); |
+ query = _makeQuery(uri, index + 1, end, null); |
} else { |
query = _makeQuery(uri, index + 1, numberSignIndex, null); |
- fragment = _makeFragment(uri, numberSignIndex + 1, uri.length); |
+ fragment = _makeFragment(uri, numberSignIndex + 1, end); |
} |
} else if (char == _NUMBER_SIGN) { |
- fragment = _makeFragment(uri, index + 1, uri.length); |
+ fragment = _makeFragment(uri, index + 1, end); |
} |
return new Uri._internal(scheme, |
userinfo, |
@@ -482,7 +492,7 @@ class Uri { |
String query, |
Map<String, String> queryParameters, |
String fragment}) { |
- scheme = _makeScheme(scheme, _stringOrNullLength(scheme)); |
+ scheme = _makeScheme(scheme, 0, _stringOrNullLength(scheme)); |
userInfo = _makeUserInfo(userInfo, 0, _stringOrNullLength(userInfo)); |
host = _makeHost(host, 0, _stringOrNullLength(host), false); |
// Special case this constructor for backwards compatibility. |
@@ -568,7 +578,7 @@ class Uri { |
for (int i = 0; i < authority.length; i++) { |
if (authority.codeUnitAt(i) == _AT_SIGN) { |
hasUserInfo = true; |
- userInfo = authority.substring(0, i); |
+ userInfo = authority.substring(start, i); |
hostStart = i + 1; |
break; |
} |
@@ -872,7 +882,7 @@ class Uri { |
// to check even the existing port. |
bool schemeChanged = false; |
if (scheme != null) { |
- scheme = _makeScheme(scheme, scheme.length); |
+ scheme = _makeScheme(scheme, 0, scheme.length); |
schemeChanged = true; |
} else { |
scheme = this.scheme; |
@@ -1100,14 +1110,14 @@ class Uri { |
* |
* Schemes are converted to lower case. They cannot contain escapes. |
*/ |
- static String _makeScheme(String scheme, int end) { |
- if (end == 0) return ""; |
- final int firstCodeUnit = scheme.codeUnitAt(0); |
+ static String _makeScheme(String scheme, int start, int end) { |
+ if (start == end) return ""; |
+ final int firstCodeUnit = scheme.codeUnitAt(start); |
if (!_isAlphabeticCharacter(firstCodeUnit)) { |
- _fail(scheme, 0, "Scheme not starting with alphabetic character"); |
+ _fail(scheme, start, "Scheme not starting with alphabetic character"); |
} |
bool allLowercase = firstCodeUnit >= _LOWER_CASE_A; |
- for (int i = 0; i < end; i++) { |
+ for (int i = start; i < end; i++) { |
final int codeUnit = scheme.codeUnitAt(i); |
if (!_isSchemeCharacter(codeUnit)) { |
_fail(scheme, i, "Illegal scheme character"); |
@@ -1116,7 +1126,7 @@ class Uri { |
allLowercase = false; |
} |
} |
- scheme = scheme.substring(0, end); |
+ scheme = scheme.substring(start, end); |
if (!allLowercase) scheme = scheme.toLowerCase(); |
return scheme; |
} |