Add Uri.isScheme test function.

Allows checking the scheme of a URI against a known value.
Example: `uri.isScheme("http")`.
Has two advantages over `uri.scheme == "http"`:
* It's case insensitive, so you can do `uri.isScheme("HTTP")` as well, and
* for simple URIs, it doesn't need to allocate a new string.

R=floitsch@google.com

Review-Url: https://codereview.chromium.org/2664453003 .
This commit is contained in:
Lasse R.H. Nielsen 2017-01-30 13:26:39 +01:00
parent b291f479bd
commit dd561d513b
3 changed files with 86 additions and 4 deletions

View file

@ -1,3 +1,9 @@
## 1.23.0
### Core library changes
* `dart:core`: Add `Uri.isScheme` function to check the scheme of a URI.
Example: `uri.isScheme("http")`. Ignores case when comparing.
## 1.22.0
### Language

View file

@ -512,6 +512,21 @@ abstract class Uri {
*/
String get origin;
/// Whether the scheme of this [Uri] is [scheme].
///
/// The [scheme] should be the same as the one returned by [Uri.scheme],
/// but doesn't have to be case-normalized to lower-case characters.
///
/// Example:
/// ```dart
/// var uri = Uri.parse("http://example.com/");
/// print(uri.isScheme("HTTP")); // Prints true.
/// ```
///
/// A `null` or empty [scheme] string matches a URI with no scheme
/// (one where [hasScheme] returns false).
bool isScheme(String scheme);
/**
* Returns the file path from a file URI.
*
@ -1532,6 +1547,44 @@ class _Uri implements Uri {
String get fragment => _fragment ?? "";
bool isScheme(String scheme) {
String thisScheme = this.scheme;
if (scheme == null) return thisScheme.isEmpty;
if (scheme.length != thisScheme.length) return false;
return _compareScheme(scheme, thisScheme);
}
/// Compares scheme characters in [scheme] and at the start of [uri].
///
/// Returns `true` if [scheme] represents the same scheme as the start of
/// [uri]. That means having the same characters, but possibly different case
/// for letters.
///
/// This function doesn't check that the characters are valid URI scheme
/// characters. The [uri] is assumed to be valid, so if [scheme] matches
/// it, it has to be valid too.
///
/// The length should be tested before calling this function,
/// so the scheme part of [uri] is known to have the same length as [scheme].
static bool _compareScheme(String scheme, String uri) {
for (int i = 0; i < scheme.length; i++) {
int schemeChar = scheme.codeUnitAt(i);
int uriChar = uri.codeUnitAt(i);
int delta = schemeChar ^ uriChar;
if (delta != 0) {
if (delta == 0x20) {
// Might be a case difference.
int lowerChar = uriChar | delta;
if (0x61 /*a*/ <= lowerChar && lowerChar <= 0x7a /*z*/) {
continue;
}
}
return false;
}
}
return true;
}
// Report a parse failure.
static void _fail(String uri, int index, String message) {
throw new FormatException(message, uri, index);
@ -4071,6 +4124,7 @@ class _SimpleUri implements Uri {
bool get _isHttp => _schemeEnd == 4 && _uri.startsWith("http");
bool get _isHttps => _schemeEnd == 5 && _uri.startsWith("https");
bool get _isPackage => _schemeEnd == 7 && _uri.startsWith("package");
/// Like [isScheme] but expects argument to be case normalized.
bool _isScheme(String scheme) =>
_schemeEnd == scheme.length && _uri.startsWith(scheme);
@ -4079,6 +4133,12 @@ class _SimpleUri implements Uri {
bool get isAbsolute => hasScheme && !hasFragment;
bool isScheme(String scheme) {
if (scheme == null || scheme.isEmpty) return _schemeEnd < 0;
if (scheme.length != _schemeEnd) return false;
return _Uri._compareScheme(scheme, _uri);
}
String get scheme {
if (_schemeEnd <= 0) return "";
if (_schemeCache != null) return _schemeCache;

View file

@ -33,10 +33,21 @@ testUri(String uriText, bool isAbsolute) {
Uri.parse(uriText + "#fragment").removeFragment());
}
// Test uri.replace on uri with fragment
uri = Uri.parse('http://hello.com/fake#fragment');
uri = uri.replace(path: "D/E/E");
Expect.stringEquals('http://hello.com/D/E/E#fragment', uri.toString());
Expect.isTrue(uri.isScheme(uri.scheme));
Expect.isTrue(uri.isScheme(uri.scheme.toLowerCase()));
Expect.isTrue(uri.isScheme(uri.scheme.toUpperCase()));
if (uri.hasScheme) {
// Capitalize
Expect.isTrue(uri.isScheme(
uri.scheme[0].toUpperCase()+uri.scheme.substring(1)));
Expect.isFalse(uri.isScheme(
uri.scheme.substring(0, uri.scheme.length - 1)));
Expect.isFalse(uri.isScheme(uri.scheme + ":"));
Expect.isFalse(uri.isScheme(uri.scheme + "\x00"));
} else {
Expect.isTrue(uri.isScheme(null));
Expect.isFalse(uri.isScheme(":"));
}
}
testEncodeDecode(String orig, String encoded) {
@ -753,6 +764,11 @@ void testReplace() {
Expect.equals("s://a:1/b/c?#e", uri.replace(query: "").toString());
Expect.equals("s://a:1?d#e", uri.replace(path: "").toString());
Expect.equals("s://:1/b/c?d#e", uri.replace(host: "").toString());
// Test uri.replace on uri with fragment
uri = Uri.parse('http://hello.com/fake#fragment');
uri = uri.replace(path: "D/E/E");
Expect.stringEquals('http://hello.com/D/E/E#fragment', uri.toString());
}
void testRegression28359() {