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

Side by Side Diff: runtime/lib/string_patch.dart

Issue 920453002: Add String.replaceFirstMapped. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: With change to _interpolate methods. Created 5 years, 10 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 const int _maxAscii = 0x7f; 5 const int _maxAscii = 0x7f;
6 const int _maxLatin1 = 0xff; 6 const int _maxLatin1 = 0xff;
7 const int _maxUtf16 = 0xffff; 7 const int _maxUtf16 = 0xffff;
8 const int _maxUnicode = 0x10ffff; 8 const int _maxUnicode = 0x10ffff;
9 9
10 patch class String { 10 patch class String {
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
80 80
81 factory _StringBase._uninstantiable() { 81 factory _StringBase._uninstantiable() {
82 throw new UnsupportedError( 82 throw new UnsupportedError(
83 "_StringBase can't be instaniated"); 83 "_StringBase can't be instaniated");
84 } 84 }
85 85
86 Type get runtimeType => String; 86 Type get runtimeType => String;
87 87
88 int get hashCode native "String_getHashCode"; 88 int get hashCode native "String_getHashCode";
89 89
90 bool get _isOneByte {
91 // Alternatively return false and override it on one-byte string classes.
92 int id = ClassID.getID(this);
93 return id == ClassID.cidOneByteString ||
94 id == ClassID.cidExternalOneByteString;
95 }
96
90 /** 97 /**
91 * Create the most efficient string representation for specified 98 * Create the most efficient string representation for specified
92 * [charCodes]. 99 * [charCodes].
93 * 100 *
94 * Only uses the character codes betwen index [start] and index [end] of 101 * Only uses the character codes betwen index [start] and index [end] of
95 * `charCodes`. They must satisfy `0 <= start <= end <= charCodes.length`. 102 * `charCodes`. They must satisfy `0 <= start <= end <= charCodes.length`.
96 * 103 *
97 * The [limit] is an upper limit on the character codes in the iterable. 104 * The [limit] is an upper limit on the character codes in the iterable.
98 * It's `null` if unknown. 105 * It's `null` if unknown.
99 */ 106 */
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after
552 [int startIndex = 0]) { 559 [int startIndex = 0]) {
553 if (pattern is! Pattern) { 560 if (pattern is! Pattern) {
554 throw new ArgumentError("${pattern} is not a Pattern"); 561 throw new ArgumentError("${pattern} is not a Pattern");
555 } 562 }
556 if (replacement is! String) { 563 if (replacement is! String) {
557 throw new ArgumentError("${replacement} is not a String"); 564 throw new ArgumentError("${replacement} is not a String");
558 } 565 }
559 if (startIndex is! int) { 566 if (startIndex is! int) {
560 throw new ArgumentError("${startIndex} is not an int"); 567 throw new ArgumentError("${startIndex} is not an int");
561 } 568 }
562 if ((startIndex < 0) || (startIndex > this.length)) { 569 RangeError.checkValueInInterval(startIndex, 0, this.length, "startIndex");
563 throw new RangeError.range(startIndex, 0, this.length);
564 }
565 Iterator iterator = 570 Iterator iterator =
566 startIndex == 0 ? pattern.allMatches(this).iterator 571 startIndex == 0 ? pattern.allMatches(this).iterator
567 : pattern.allMatches(this, startIndex).iterator; 572 : pattern.allMatches(this, startIndex).iterator;
568 if (!iterator.moveNext()) return this; 573 if (!iterator.moveNext()) return this;
569 Match match = iterator.current; 574 Match match = iterator.current;
570 return "${this.substring(0, match.start)}" 575 return "${this.substring(0, match.start)}"
571 "$replacement" 576 "$replacement"
572 "${this.substring(match.end)}"; 577 "${this.substring(match.end)}";
573 } 578 }
574 579
(...skipping 26 matching lines...) Expand all
601 } 606 }
602 } else { 607 } else {
603 for (Match match in pattern.allMatches(this)) { 608 for (Match match in pattern.allMatches(this)) {
604 length += _addReplaceSlice(matches, startIndex, match.start); 609 length += _addReplaceSlice(matches, startIndex, match.start);
605 matches.add(replacement); 610 matches.add(replacement);
606 length += replacementLength; 611 length += replacementLength;
607 startIndex = match.end; 612 startIndex = match.end;
608 } 613 }
609 } 614 }
610 length += _addReplaceSlice(matches, startIndex, this.length); 615 length += _addReplaceSlice(matches, startIndex, this.length);
611 bool replacementIsOneByte = (replacement is _OneByteString) || 616 bool replacementIsOneByte = replacement._isOneByte;
612 (replacement is _ExternalOneByteString); 617 if (replacementIsOneByte &&
613 if (replacementIsOneByte && length < _maxJoinReplaceOneByteStringLength) { 618 length < _maxJoinReplaceOneByteStringLength &&
619 this._isOneByte) {
614 // TODO(lrn): Is there a cut-off point, or is runtime always faster? 620 // TODO(lrn): Is there a cut-off point, or is runtime always faster?
615 bool thisIsOneByte = (this is _OneByteString) || 621 return _joinReplaceAllOneByteResult(this, matches, length);
616 (this is _ExternalOneByteString);
617 if (replacementIsOneByte && thisIsOneByte) {
618 return _joinReplaceAllOneByteResult(this, matches, length);
619 }
620 } 622 }
621 return _joinReplaceAllResult(this, matches, length, 623 return _joinReplaceAllResult(this, matches, length,
622 replacementIsOneByte); 624 replacementIsOneByte);
623 } 625 }
624 626
625 /** 627 /**
626 * As [_joinReplaceAllResult], but knowing that the result 628 * As [_joinReplaceAllResult], but knowing that the result
627 * is always a [_OneByteString]. 629 * is always a [_OneByteString].
628 */ 630 */
629 static String _joinReplaceAllOneByteResult(String base, 631 static String _joinReplaceAllOneByteResult(String base,
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
681 683
682 String replaceAllMapped(Pattern pattern, String replace(Match match)) { 684 String replaceAllMapped(Pattern pattern, String replace(Match match)) {
683 if (pattern == null) throw new ArgumentError.notNull("pattern"); 685 if (pattern == null) throw new ArgumentError.notNull("pattern");
684 if (replace == null) throw new ArgumentError.notNull("replace"); 686 if (replace == null) throw new ArgumentError.notNull("replace");
685 List matches = []; 687 List matches = [];
686 int length = 0; 688 int length = 0;
687 int startIndex = 0; 689 int startIndex = 0;
688 bool replacementStringsAreOneByte = true; 690 bool replacementStringsAreOneByte = true;
689 for (Match match in pattern.allMatches(this)) { 691 for (Match match in pattern.allMatches(this)) {
690 length += _addReplaceSlice(matches, startIndex, match.start); 692 length += _addReplaceSlice(matches, startIndex, match.start);
691 String replacement = replace(match).toString(); 693 var replacement = "${replace(match)}";
692 matches.add(replacement); 694 matches.add(replacement);
693 length += replacement.length; 695 length += replacement.length;
694 replacementStringsAreOneByte = replacementStringsAreOneByte && 696 replacementStringsAreOneByte =
695 (replacement is _OneByteString || 697 replacementStringsAreOneByte && replacement._isOneByte;
696 replacement is _ExternalOneByteString);
697 startIndex = match.end; 698 startIndex = match.end;
698 } 699 }
700 if (matches.isEmpty) return this;
699 length += _addReplaceSlice(matches, startIndex, this.length); 701 length += _addReplaceSlice(matches, startIndex, this.length);
700 if (replacementStringsAreOneByte && 702 if (replacementStringsAreOneByte &&
701 length < _maxJoinReplaceOneByteStringLength) { 703 length < _maxJoinReplaceOneByteStringLength &&
702 bool thisIsOneByte = (this is _OneByteString) || 704 this._isOneByte) {
703 (this is _ExternalOneByteString); 705 return _joinReplaceAllOneByteResult(this, matches, length);
704 if (thisIsOneByte) {
705 return _joinReplaceAllOneByteResult(this, matches, length);
706 }
707 } 706 }
708 return _joinReplaceAllResult(this, matches, length, 707 return _joinReplaceAllResult(this, matches, length,
709 replacementStringsAreOneByte); 708 replacementStringsAreOneByte);
710 } 709 }
711 710
711 String replaceFirstMapped(Pattern pattern, String replace(Match match),
712 [int startIndex = 0]) {
713 if (pattern == null) throw new ArgumentError.notNull("pattern");
714 if (replace == null) throw new ArgumentError.notNull("replace");
715 if (startIndex == null) throw new ArgumentError.notNull("startIndex");
716 RangeError.checkValueInInterval(startIndex, 0, this.length, "startIndex");
717
718 var matches = pattern.allMatches(this, startIndex).iterator;
719 if (!matches.moveNext()) return this;
720 var match = matches.current;
721 var replacement = "${replace(match)}";
722 var slices = [];
723 int length = 0;
724 if (match.start > 0) {
725 length += _addReplaceSlice(slices, 0, match.start);
726 }
727 slices.add(replacement);
728 length += replacement.length;
729 if (match.end < this.length) {
730 length += _addReplaceSlice(slices, match.end, this.length);
731 }
732 bool replacementIsOneByte = _replacement._isOneByte;
733 if (replacementIsOneByte &&
734 length < _maxJoinReplaceOneByteStringLength &&
735 this._isOneByte) {
736 return _joinReplaceAllOneByteResult(this, matches, length);
737 }
738 return _joinReplaceAllResult(this, slices, length, replacementIsOneByte);
739 }
740
712 static String _matchString(Match match) => match[0]; 741 static String _matchString(Match match) => match[0];
713 static String _stringIdentity(String string) => string; 742 static String _stringIdentity(String string) => string;
714 743
715 String _splitMapJoinEmptyString(String onMatch(Match match), 744 String _splitMapJoinEmptyString(String onMatch(Match match),
716 String onNonMatch(String nonMatch)) { 745 String onNonMatch(String nonMatch)) {
717 // Pattern is the empty string. 746 // Pattern is the empty string.
718 StringBuffer buffer = new StringBuffer(); 747 StringBuffer buffer = new StringBuffer();
719 int length = this.length; 748 int length = this.length;
720 int i = 0; 749 int i = 0;
721 buffer.write(onNonMatch("")); 750 buffer.write(onNonMatch(""));
(...skipping 542 matching lines...) Expand 10 before | Expand all | Expand 10 after
1264 for (int g in groups) { 1293 for (int g in groups) {
1265 result.add(group(g)); 1294 result.add(group(g));
1266 } 1295 }
1267 return result; 1296 return result;
1268 } 1297 }
1269 1298
1270 final int start; 1299 final int start;
1271 final String input; 1300 final String input;
1272 final String pattern; 1301 final String pattern;
1273 } 1302 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698