Make String.allMatches lazy.

R=floitsch@google.com, iposva@google.com

Review URL: https://codereview.chromium.org//1273713003 .
This commit is contained in:
Lasse R.H. Nielsen
2015-08-12 11:01:21 +02:00
parent b19d518ede
commit edff0face7
4 changed files with 113 additions and 46 deletions
+2 -1
View File
@@ -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.
+54 -20
View File
@@ -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) {