Make String.allMatches lazy.
R=floitsch@google.com, iposva@google.com Review URL: https://codereview.chromium.org//1273713003 .
This commit is contained in:
+2
-1
@@ -2,7 +2,8 @@
|
||||
|
||||
* `dart:core`
|
||||
* `Uri` added `removeFragment` method.
|
||||
|
||||
* `String.allMatches` (implementing `Pattern.allMatches`) is now lazy,
|
||||
as all `allMatches` implementations are intended to be.
|
||||
* `dart:io`
|
||||
* `HttpClient` no longer sends URI fragments in the requeust. This is not
|
||||
allowed by the HTTP protocol.
|
||||
|
||||
@@ -312,7 +312,7 @@ class _StringBase {
|
||||
|
||||
int indexOf(Pattern pattern, [int start = 0]) {
|
||||
if ((start < 0) || (start > this.length)) {
|
||||
throw new RangeError.range(start, 0, this.length);
|
||||
throw new RangeError.range(start, 0, this.length, "start");
|
||||
}
|
||||
if (pattern is String) {
|
||||
String other = pattern;
|
||||
@@ -844,26 +844,10 @@ class _StringBase {
|
||||
}
|
||||
|
||||
Iterable<Match> allMatches(String string, [int start = 0]) {
|
||||
List<Match> result = new List<Match>();
|
||||
int length = string.length;
|
||||
int patternLength = this.length;
|
||||
int startIndex = start;
|
||||
while (true) {
|
||||
int position = string.indexOf(this, startIndex);
|
||||
if (position == -1) {
|
||||
break;
|
||||
}
|
||||
result.add(new _StringMatch(position, string, this));
|
||||
int endIndex = position + patternLength;
|
||||
if (endIndex == length) {
|
||||
break;
|
||||
} else if (position == endIndex) {
|
||||
++startIndex; // empty match, advance and restart
|
||||
} else {
|
||||
startIndex = endIndex;
|
||||
}
|
||||
if (start < 0 || start > string.length) {
|
||||
throw new RangeError.range(start, 0, string.length, "start");
|
||||
}
|
||||
return result;
|
||||
return new _StringAllMatchesIterable(string, this, start);
|
||||
}
|
||||
|
||||
Match matchAsPrefix(String string, [int start = 0]) {
|
||||
@@ -1323,3 +1307,53 @@ class _StringMatch implements Match {
|
||||
final String input;
|
||||
final String pattern;
|
||||
}
|
||||
|
||||
|
||||
class _StringAllMatchesIterable extends Iterable<Match> {
|
||||
final String _input;
|
||||
final String _pattern;
|
||||
final int _index;
|
||||
|
||||
_StringAllMatchesIterable(this._input, this._pattern, this._index);
|
||||
|
||||
Iterator<Match> get iterator =>
|
||||
new _StringAllMatchesIterator(_input, _pattern, _index);
|
||||
|
||||
Match get first {
|
||||
int index = _input.indexOf(_pattern, _index);
|
||||
if (index >= 0) {
|
||||
return new _StringMatch(index, _input, _pattern);
|
||||
}
|
||||
throw IterableElementError.noElement();
|
||||
}
|
||||
}
|
||||
|
||||
class _StringAllMatchesIterator implements Iterator<Match> {
|
||||
final String _input;
|
||||
final String _pattern;
|
||||
int _index;
|
||||
Match _current;
|
||||
|
||||
_StringAllMatchesIterator(this._input, this._pattern, this._index);
|
||||
|
||||
bool moveNext() {
|
||||
if (_index + _pattern.length > _input.length) {
|
||||
_current = null;
|
||||
return false;
|
||||
}
|
||||
var index = _input.indexOf(_pattern, _index);
|
||||
if (index < 0) {
|
||||
_index = _input.length + 1;
|
||||
_current = null;
|
||||
return false;
|
||||
}
|
||||
int end = index + _pattern.length;
|
||||
_current = new _StringMatch(index, _input, _pattern);
|
||||
// Empty match, don't start at same location again.
|
||||
if (end == _index) end++;
|
||||
_index = end;
|
||||
return true;
|
||||
}
|
||||
|
||||
Match get current => _current;
|
||||
}
|
||||
|
||||
@@ -57,7 +57,10 @@ import 'dart:_foreign_helper' show
|
||||
|
||||
import 'dart:_interceptors';
|
||||
import 'dart:_internal' as _symbol_dev;
|
||||
import 'dart:_internal' show EfficientLength, MappedIterable;
|
||||
import 'dart:_internal' show
|
||||
EfficientLength,
|
||||
MappedIterable,
|
||||
IterableElementError;
|
||||
|
||||
import 'dart:_native_typed_data';
|
||||
|
||||
@@ -148,7 +151,7 @@ bool builtinIsSubtype(type, String other) {
|
||||
@ForceInline()
|
||||
bool isDartFunctionTypeRti(Object type) {
|
||||
return JS_BUILTIN('returns:bool;effects:none;depends:none',
|
||||
JsBuiltin.isGivenTypeRti,
|
||||
JsBuiltin.isGivenTypeRti,
|
||||
type,
|
||||
JS_GET_NAME(JsGetName.FUNCTION_CLASS_TYPE_NAME));
|
||||
}
|
||||
@@ -158,7 +161,7 @@ bool isDartFunctionTypeRti(Object type) {
|
||||
@ForceInline()
|
||||
bool isDartObjectTypeRti(type) {
|
||||
return JS_BUILTIN('returns:bool;effects:none;depends:none',
|
||||
JsBuiltin.isGivenTypeRti,
|
||||
JsBuiltin.isGivenTypeRti,
|
||||
type,
|
||||
JS_GET_NAME(JsGetName.OBJECT_CLASS_TYPE_NAME));
|
||||
}
|
||||
@@ -168,7 +171,7 @@ bool isDartObjectTypeRti(type) {
|
||||
@ForceInline()
|
||||
bool isNullTypeRti(type) {
|
||||
return JS_BUILTIN('returns:bool;effects:none;depends:none',
|
||||
JsBuiltin.isGivenTypeRti,
|
||||
JsBuiltin.isGivenTypeRti,
|
||||
type,
|
||||
JS_GET_NAME(JsGetName.NULL_CLASS_TYPE_NAME));
|
||||
}
|
||||
|
||||
@@ -49,29 +49,58 @@ class StringMatch implements Match {
|
||||
final String pattern;
|
||||
}
|
||||
|
||||
List<Match> allMatchesInStringUnchecked(String pattern, String string,
|
||||
int startIndex) {
|
||||
// Copied from StringBase.allMatches in
|
||||
// /runtime/lib/string_base.dart
|
||||
List<Match> result = new List<Match>();
|
||||
int length = string.length;
|
||||
int patternLength = pattern.length;
|
||||
while (true) {
|
||||
int position = stringIndexOfStringUnchecked(string, pattern, startIndex);
|
||||
if (position == -1) {
|
||||
break;
|
||||
}
|
||||
result.add(new StringMatch(position, string, pattern));
|
||||
int endIndex = position + patternLength;
|
||||
if (endIndex == length) {
|
||||
break;
|
||||
} else if (position == endIndex) {
|
||||
++startIndex; // empty match, advance and restart
|
||||
} else {
|
||||
startIndex = endIndex;
|
||||
Iterable<Match> allMatchesInStringUnchecked(String pattern, String string,
|
||||
int startIndex) {
|
||||
return new _StringAllMatchesIterable(string, pattern, startIndex);
|
||||
}
|
||||
|
||||
class _StringAllMatchesIterable extends Iterable<Match> {
|
||||
final String _input;
|
||||
final String _pattern;
|
||||
final int _index;
|
||||
|
||||
_StringAllMatchesIterable(this._input, this._pattern, this._index);
|
||||
|
||||
Iterator<Match> get iterator =>
|
||||
new _StringAllMatchesIterator(_input, _pattern, _index);
|
||||
|
||||
Match get first {
|
||||
int index = stringIndexOfStringUnchecked(_input, _pattern, _index);
|
||||
if (index >= 0) {
|
||||
return new StringMatch(index, _input, _pattern);
|
||||
}
|
||||
throw IterableElementError.noElement();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
class _StringAllMatchesIterator implements Iterator<Match> {
|
||||
final String _input;
|
||||
final String _pattern;
|
||||
int _index;
|
||||
Match _current;
|
||||
|
||||
_StringAllMatchesIterator(this._input, this._pattern, this._index);
|
||||
|
||||
bool moveNext() {
|
||||
if (_index + _pattern.length > _input.length) {
|
||||
_current = null;
|
||||
return false;
|
||||
}
|
||||
var index = stringIndexOfStringUnchecked(_input, _pattern, _index);
|
||||
if (index < 0) {
|
||||
_index = _input.length + 1;
|
||||
_current = null;
|
||||
return false;
|
||||
}
|
||||
int end = index + _pattern.length;
|
||||
_current = new StringMatch(index, _input, _pattern);
|
||||
// Empty match, don't start at same location again.
|
||||
if (end == _index) end++;
|
||||
_index = end;
|
||||
return true;
|
||||
}
|
||||
|
||||
Match get current => _current;
|
||||
}
|
||||
|
||||
stringContainsUnchecked(receiver, other, startIndex) {
|
||||
|
||||
Reference in New Issue
Block a user