Commit 657ffd88 authored by yangguo@chromium.org's avatar yangguo@chromium.org

Use simple concat of substrings instead of ReplaceStringBuilder for non-global replacements.

BUG=
TEST=

Review URL: https://chromiumcodereview.appspot.com/10134057

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@11448 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 9e55943b
...@@ -277,47 +277,34 @@ function StringReplace(search, replace) { ...@@ -277,47 +277,34 @@ function StringReplace(search, replace) {
if (start < 0) return subject; if (start < 0) return subject;
var end = start + search.length; var end = start + search.length;
var builder = new ReplaceResultBuilder(subject); var result = SubString(subject, 0, start);
// prefix
builder.addSpecialSlice(0, start);
// Compute the string to replace with. // Compute the string to replace with.
if (IS_SPEC_FUNCTION(replace)) { if (IS_SPEC_FUNCTION(replace)) {
var receiver = %GetDefaultReceiver(replace); var receiver = %GetDefaultReceiver(replace);
builder.add(%_CallFunction(receiver, result += %_CallFunction(receiver, search, start, subject, replace);
search,
start,
subject,
replace));
} else { } else {
reusableMatchInfo[CAPTURE0] = start; reusableMatchInfo[CAPTURE0] = start;
reusableMatchInfo[CAPTURE1] = end; reusableMatchInfo[CAPTURE1] = end;
replace = TO_STRING_INLINE(replace); replace = TO_STRING_INLINE(replace);
ExpandReplacement(replace, subject, reusableMatchInfo, builder); result = ExpandReplacement(replace, subject, reusableMatchInfo, result);
} }
// suffix return result + SubString(subject, end, subject.length);
builder.addSpecialSlice(end, subject.length);
return builder.generate();
} }
// Expand the $-expressions in the string and return a new string with // Expand the $-expressions in the string and return a new string with
// the result. // the result.
function ExpandReplacement(string, subject, matchInfo, builder) { function ExpandReplacement(string, subject, matchInfo, result) {
var length = string.length; var length = string.length;
var builder_elements = builder.elements;
var next = %StringIndexOf(string, '$', 0); var next = %StringIndexOf(string, '$', 0);
if (next < 0) { if (next < 0) {
if (length > 0) builder_elements.push(string); if (length > 0) result += string;
return; return result;
} }
// Compute the number of captures; see ECMA-262, 15.5.4.11, p. 102. if (next > 0) result += SubString(string, 0, next);
var m = NUMBER_OF_CAPTURES(matchInfo) >> 1; // Includes the match.
if (next > 0) builder_elements.push(SubString(string, 0, next));
while (true) { while (true) {
var expansion = '$'; var expansion = '$';
...@@ -326,51 +313,21 @@ function ExpandReplacement(string, subject, matchInfo, builder) { ...@@ -326,51 +313,21 @@ function ExpandReplacement(string, subject, matchInfo, builder) {
var peek = %_StringCharCodeAt(string, position); var peek = %_StringCharCodeAt(string, position);
if (peek == 36) { // $$ if (peek == 36) { // $$
++position; ++position;
builder_elements.push('$'); result += '$';
} else if (peek == 38) { // $& - match } else if (peek == 38) { // $& - match
++position; ++position;
builder.addSpecialSlice(matchInfo[CAPTURE0], result += SubString(subject, matchInfo[CAPTURE0], matchInfo[CAPTURE1]);
matchInfo[CAPTURE1]);
} else if (peek == 96) { // $` - prefix } else if (peek == 96) { // $` - prefix
++position; ++position;
builder.addSpecialSlice(0, matchInfo[CAPTURE0]); result += SubString(subject, 0, matchInfo[CAPTURE0]);
} else if (peek == 39) { // $' - suffix } else if (peek == 39) { // $' - suffix
++position; ++position;
builder.addSpecialSlice(matchInfo[CAPTURE1], subject.length); result += SubString(subject, matchInfo[CAPTURE1], subject.length);
} else if (peek >= 48 && peek <= 57) { // $n, 0 <= n <= 9
++position;
var n = peek - 48;
if (position < length) {
peek = %_StringCharCodeAt(string, position);
// $nn, 01 <= nn <= 99
if (n != 0 && peek == 48 || peek >= 49 && peek <= 57) {
var nn = n * 10 + (peek - 48);
if (nn < m) {
// If the two digit capture reference is within range of
// the captures, we use it instead of the single digit
// one. Otherwise, we fall back to using the single
// digit reference. This matches the behavior of
// SpiderMonkey.
++position;
n = nn;
}
}
}
if (0 < n && n < m) {
addCaptureString(builder, matchInfo, n);
} else {
// Because of the captures range check in the parsing of two
// digit capture references, we can only enter here when a
// single digit capture reference is outside the range of
// captures.
builder_elements.push('$');
--position;
}
} else { } else {
builder_elements.push('$'); result += '$';
} }
} else { } else {
builder_elements.push('$'); result += '$';
} }
// Go the the next $ in the string. // Go the the next $ in the string.
...@@ -380,16 +337,17 @@ function ExpandReplacement(string, subject, matchInfo, builder) { ...@@ -380,16 +337,17 @@ function ExpandReplacement(string, subject, matchInfo, builder) {
// haven't reached the end, we need to append the suffix. // haven't reached the end, we need to append the suffix.
if (next < 0) { if (next < 0) {
if (position < length) { if (position < length) {
builder_elements.push(SubString(string, position, length)); result += SubString(string, position, length);
} }
return; return result;
} }
// Append substring between the previous and the next $ character. // Append substring between the previous and the next $ character.
if (next > position) { if (next > position) {
builder_elements.push(SubString(string, position, next)); result += SubString(string, position, next);
} }
} }
return result;
} }
...@@ -406,18 +364,6 @@ function CaptureString(string, lastCaptureInfo, index) { ...@@ -406,18 +364,6 @@ function CaptureString(string, lastCaptureInfo, index) {
} }
// Add the string of a given regular expression capture to the
// ReplaceResultBuilder
function addCaptureString(builder, matchInfo, index) {
// Scale the index.
var scaled = index << 1;
// Compute start and end.
var start = matchInfo[CAPTURE(scaled)];
if (start < 0) return;
var end = matchInfo[CAPTURE(scaled + 1)];
builder.addSpecialSlice(start, end);
}
// TODO(lrn): This array will survive indefinitely if replace is never // TODO(lrn): This array will survive indefinitely if replace is never
// called again. However, it will be empty, since the contents are cleared // called again. However, it will be empty, since the contents are cleared
// in the finally block. // in the finally block.
...@@ -506,9 +452,8 @@ function StringReplaceGlobalRegExpWithFunction(subject, regexp, replace) { ...@@ -506,9 +452,8 @@ function StringReplaceGlobalRegExpWithFunction(subject, regexp, replace) {
function StringReplaceNonGlobalRegExpWithFunction(subject, regexp, replace) { function StringReplaceNonGlobalRegExpWithFunction(subject, regexp, replace) {
var matchInfo = DoRegExpExec(regexp, subject, 0); var matchInfo = DoRegExpExec(regexp, subject, 0);
if (IS_NULL(matchInfo)) return subject; if (IS_NULL(matchInfo)) return subject;
var result = new ReplaceResultBuilder(subject);
var index = matchInfo[CAPTURE0]; var index = matchInfo[CAPTURE0];
result.addSpecialSlice(0, index); var result = SubString(subject, 0, index);
var endOfMatch = matchInfo[CAPTURE1]; var endOfMatch = matchInfo[CAPTURE1];
// Compute the parameter list consisting of the match, captures, index, // Compute the parameter list consisting of the match, captures, index,
// and subject for the replace function invocation. // and subject for the replace function invocation.
...@@ -532,11 +477,10 @@ function StringReplaceNonGlobalRegExpWithFunction(subject, regexp, replace) { ...@@ -532,11 +477,10 @@ function StringReplaceNonGlobalRegExpWithFunction(subject, regexp, replace) {
replacement = %Apply(replace, receiver, parameters, 0, j + 2); replacement = %Apply(replace, receiver, parameters, 0, j + 2);
} }
result.add(replacement); // The add method converts to string if necessary. result += replacement; // The add method converts to string if necessary.
// Can't use matchInfo any more from here, since the function could // Can't use matchInfo any more from here, since the function could
// overwrite it. // overwrite it.
result.addSpecialSlice(endOfMatch, subject.length); return result + SubString(subject, endOfMatch, subject.length);
return result.generate();
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment