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; |
+ } |
} |