| Index: runtime/lib/string_patch.dart
|
| diff --git a/runtime/lib/string_patch.dart b/runtime/lib/string_patch.dart
|
| index bef6a18113b220038e2586435dffdef5f0c2617f..e3f5c68d923d8b28cad4dcb9425b7ed91fa37f0a 100644
|
| --- a/runtime/lib/string_patch.dart
|
| +++ b/runtime/lib/string_patch.dart
|
| @@ -572,11 +572,30 @@ class _StringBase {
|
| : pattern.allMatches(this, startIndex).iterator;
|
| if (!iterator.moveNext()) return this;
|
| Match match = iterator.current;
|
| - return "${this.substring(0, match.start)}"
|
| - "$replacement"
|
| - "${this.substring(match.end)}";
|
| + return replaceRange(match.start, match.end, replacement);
|
| }
|
|
|
| + String replaceRange(int start, int end, String replacement) {
|
| + int length = this.length;
|
| + end = RangeError.checkValidRange(start, end, length);
|
| + bool replacementIsOneByte = replacement._isOneByte;
|
| + int replacementLength = replacement.length;
|
| + int totalLength = start + (length - end) + replacementLength;
|
| + if (replacementIsOneByte && this._isOneByte) {
|
| + var result = _OneByteString._allocate(totalLength);
|
| + int index = 0;
|
| + index = result._setRange(index, this, 0, start);
|
| + index = result._setRange(start, replacement, 0, replacementLength);
|
| + result._setRange(index, this, end, length);
|
| + return result;
|
| + }
|
| + List slices = [];
|
| + _addReplaceSlice(slices, 0, start);
|
| + if (replacement.length > 0) slices.add(replacement);
|
| + _addReplaceSlice(slices, end, length);
|
| + return _joinReplaceAllResult(this, slices, totalLength,
|
| + replacementIsOneByte);
|
| + }
|
|
|
| static int _addReplaceSlice(List matches, int start, int end) {
|
| int length = end - start;
|
| @@ -719,23 +738,7 @@ class _StringBase {
|
| if (!matches.moveNext()) return this;
|
| var match = matches.current;
|
| var replacement = "${replace(match)}";
|
| - var slices = [];
|
| - int length = 0;
|
| - if (match.start > 0) {
|
| - length += _addReplaceSlice(slices, 0, match.start);
|
| - }
|
| - slices.add(replacement);
|
| - length += replacement.length;
|
| - if (match.end < this.length) {
|
| - length += _addReplaceSlice(slices, match.end, this.length);
|
| - }
|
| - bool replacementIsOneByte = replacement._isOneByte;
|
| - if (replacementIsOneByte &&
|
| - length < _maxJoinReplaceOneByteStringLength &&
|
| - this._isOneByte) {
|
| - return _joinReplaceAllOneByteResult(this, slices, length);
|
| - }
|
| - return _joinReplaceAllResult(this, slices, length, replacementIsOneByte);
|
| + return replaceRange(match.start, match.end, replacement);
|
| }
|
|
|
| static String _matchString(Match match) => match[0];
|
| @@ -1216,6 +1219,23 @@ class _OneByteString extends _StringBase implements String {
|
| // This is internal helper method. Code point value must be a valid
|
| // Latin1 value (0..0xFF), index must be valid.
|
| void _setAt(int index, int codePoint) native "OneByteString_setAt";
|
| +
|
| + // Should be optimizable to a memory move.
|
| + // Accepts both _OneByteString and _ExternalOneByteString as argument.
|
| + // Returns index after last character written.
|
| + int _setRange(int index, String oneByteString, int start, int end) {
|
| + assert(oneByteString._isOneByte);
|
| + assert(0 <= start);
|
| + assert(start <= end);
|
| + assert(end <= oneByteString.length);
|
| + assert(0 <= index);
|
| + assert(index + (end - start) <= length);
|
| + for (int i = start; i < end; i++) {
|
| + _setAt(index, oneByteString.codeUnitAt(i));
|
| + index += 1;
|
| + }
|
| + return index;
|
| + }
|
| }
|
|
|
|
|
|
|