| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |