Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(71)

Side by Side Diff: src/objects.cc

Issue 2776123002: [string] Refactor String::GetSubstitution (Closed)
Patch Set: Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/objects.h" 5 #include "src/objects.h"
6 6
7 #include <cmath> 7 #include <cmath>
8 #include <iomanip> 8 #include <iomanip>
9 #include <memory> 9 #include <memory>
10 #include <sstream> 10 #include <sstream>
(...skipping 11393 matching lines...) Expand 10 before | Expand all | Expand 10 after
11404 Handle<String> replacement) { 11404 Handle<String> replacement) {
11405 Factory* factory = isolate->factory(); 11405 Factory* factory = isolate->factory();
11406 11406
11407 const int replacement_length = replacement->length(); 11407 const int replacement_length = replacement->length();
11408 const int captures_length = match->CaptureCount(); 11408 const int captures_length = match->CaptureCount();
11409 11409
11410 replacement = String::Flatten(replacement); 11410 replacement = String::Flatten(replacement);
11411 11411
11412 Handle<String> dollar_string = 11412 Handle<String> dollar_string =
11413 factory->LookupSingleCharacterStringFromCode('$'); 11413 factory->LookupSingleCharacterStringFromCode('$');
11414 int next = String::IndexOf(isolate, replacement, dollar_string, 0); 11414 int next_dollar_ix = String::IndexOf(isolate, replacement, dollar_string, 0);
11415 if (next < 0) { 11415 if (next_dollar_ix < 0) {
11416 return replacement; 11416 return replacement;
11417 } 11417 }
11418 11418
11419 IncrementalStringBuilder builder(isolate); 11419 IncrementalStringBuilder builder(isolate);
11420 11420
11421 if (next > 0) { 11421 if (next_dollar_ix > 0) {
11422 builder.AppendString(factory->NewSubString(replacement, 0, next)); 11422 builder.AppendString(factory->NewSubString(replacement, 0, next_dollar_ix));
11423 } 11423 }
11424 11424
11425 while (true) { 11425 while (true) {
11426 int pos = next + 1; 11426 const int peek_ix = next_dollar_ix + 1;
11427 if (pos < replacement_length) { 11427 if (peek_ix >= replacement_length) {
11428 const uint16_t peek = replacement->Get(pos); 11428 builder.AppendCharacter('$');
11429 if (peek == '$') { // $$ 11429 return builder.Finish();
11430 pos++; 11430 }
11431
11432 int continue_from_ix = -1;
11433 const uint16_t peek = replacement->Get(peek_ix);
11434 switch (peek) {
11435 case '$': // $$
11436 continue_from_ix = peek_ix + 1;
11431 builder.AppendCharacter('$'); 11437 builder.AppendCharacter('$');
11432 } else if (peek == '&') { // $& - match 11438 break;
11433 pos++; 11439 case '&': // $& - match
11440 continue_from_ix = peek_ix + 1;
11434 builder.AppendString(match->GetMatch()); 11441 builder.AppendString(match->GetMatch());
11435 } else if (peek == '`') { // $` - prefix 11442 break;
11436 pos++; 11443 case '`': // $` - prefix
11444 continue_from_ix = peek_ix + 1;
11437 builder.AppendString(match->GetPrefix()); 11445 builder.AppendString(match->GetPrefix());
11438 } else if (peek == '\'') { // $' - suffix 11446 break;
11439 pos++; 11447 case '\'': // $' - suffix
11448 continue_from_ix = peek_ix + 1;
11440 builder.AppendString(match->GetSuffix()); 11449 builder.AppendString(match->GetSuffix());
11441 } else if (peek >= '0' && peek <= '9') { 11450 break;
11451 case '0':
11452 case '1':
11453 case '2':
11454 case '3':
11455 case '4':
11456 case '5':
11457 case '6':
11458 case '7':
11459 case '8':
11460 case '9': {
11442 // Valid indices are $1 .. $9, $01 .. $09 and $10 .. $99 11461 // Valid indices are $1 .. $9, $01 .. $09 and $10 .. $99
11443 int scaled_index = (peek - '0'); 11462 int scaled_index = (peek - '0');
11444 int advance = 1; 11463 int advance = 1;
11445 11464
11446 if (pos + 1 < replacement_length) { 11465 if (peek_ix + 1 < replacement_length) {
11447 const uint16_t next_peek = replacement->Get(pos + 1); 11466 const uint16_t next_peek = replacement->Get(peek_ix + 1);
11448 if (next_peek >= '0' && next_peek <= '9') { 11467 if (next_peek >= '0' && next_peek <= '9') {
11449 const int new_scaled_index = scaled_index * 10 + (next_peek - '0'); 11468 const int new_scaled_index = scaled_index * 10 + (next_peek - '0');
11450 if (new_scaled_index < captures_length) { 11469 if (new_scaled_index < captures_length) {
11451 scaled_index = new_scaled_index; 11470 scaled_index = new_scaled_index;
11452 advance = 2; 11471 advance = 2;
11453 } 11472 }
11454 } 11473 }
11455 } 11474 }
11456 11475
11457 if (scaled_index != 0 && scaled_index < captures_length) { 11476 if (scaled_index == 0 || scaled_index >= captures_length) {
11458 bool capture_exists;
11459 Handle<String> capture;
11460 ASSIGN_RETURN_ON_EXCEPTION(
11461 isolate, capture,
11462 match->GetCapture(scaled_index, &capture_exists), String);
11463 if (capture_exists) builder.AppendString(capture);
11464 pos += advance;
11465 } else {
11466 builder.AppendCharacter('$'); 11477 builder.AppendCharacter('$');
jgruber 2017/03/27 10:47:30 The if-pattern forces deep nesting that's confusin
11478 break;
11467 } 11479 }
11468 } else { 11480
11481 bool capture_exists;
11482 Handle<String> capture;
11483 ASSIGN_RETURN_ON_EXCEPTION(
11484 isolate, capture, match->GetCapture(scaled_index, &capture_exists),
11485 String);
11486 if (capture_exists) builder.AppendString(capture);
11487 continue_from_ix = peek_ix + advance;
11488 break;
11489 }
11490 default:
11469 builder.AppendCharacter('$'); 11491 builder.AppendCharacter('$');
11470 } 11492 continue_from_ix = peek_ix;
11471 } else { 11493 break;
11472 builder.AppendCharacter('$');
11473 } 11494 }
11474 11495
11475 // Go the the next $ in the replacement. 11496 // Go the the next $ in the replacement.
11476 next = String::IndexOf(isolate, replacement, dollar_string, pos); 11497 // TODO(jgruber): Single-char lookups could be much more efficient.
11498 next_dollar_ix =
11499 String::IndexOf(isolate, replacement, dollar_string, continue_from_ix);
11477 11500
11478 // Return if there are no more $ characters in the replacement. If we 11501 // Return if there are no more $ characters in the replacement. If we
11479 // haven't reached the end, we need to append the suffix. 11502 // haven't reached the end, we need to append the suffix.
11480 if (next < 0) { 11503 if (next_dollar_ix < 0) {
11481 if (pos < replacement_length) { 11504 if (continue_from_ix < replacement_length) {
11482 builder.AppendString( 11505 builder.AppendString(factory->NewSubString(
11483 factory->NewSubString(replacement, pos, replacement_length)); 11506 replacement, continue_from_ix, replacement_length));
11484 } 11507 }
11485 return builder.Finish(); 11508 return builder.Finish();
11486 } 11509 }
11487 11510
11488 // Append substring between the previous and the next $ character. 11511 // Append substring between the previous and the next $ character.
11489 if (next > pos) { 11512 if (next_dollar_ix > continue_from_ix) {
11490 builder.AppendString(factory->NewSubString(replacement, pos, next)); 11513 builder.AppendString(
11514 factory->NewSubString(replacement, continue_from_ix, next_dollar_ix));
11491 } 11515 }
11492 } 11516 }
11493 11517
11494 UNREACHABLE(); 11518 UNREACHABLE();
11495 return MaybeHandle<String>(); 11519 return MaybeHandle<String>();
11496 } 11520 }
11497 11521
11498 namespace { // for String.Prototype.lastIndexOf 11522 namespace { // for String.Prototype.lastIndexOf
11499 11523
11500 template <typename schar, typename pchar> 11524 template <typename schar, typename pchar>
(...skipping 8798 matching lines...) Expand 10 before | Expand all | Expand 10 after
20299 // depend on this. 20323 // depend on this.
20300 return DICTIONARY_ELEMENTS; 20324 return DICTIONARY_ELEMENTS;
20301 } 20325 }
20302 DCHECK_LE(kind, LAST_ELEMENTS_KIND); 20326 DCHECK_LE(kind, LAST_ELEMENTS_KIND);
20303 return kind; 20327 return kind;
20304 } 20328 }
20305 } 20329 }
20306 20330
20307 } // namespace internal 20331 } // namespace internal
20308 } // namespace v8 20332 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698