Chromium Code Reviews| 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 patch class String { | 5 patch class String { |
| 6 /* patch */ factory String.fromCharCodes(Iterable<int> charCodes) { | 6 /* patch */ factory String.fromCharCodes(Iterable<int> charCodes) { |
| 7 return _StringBase.createFromCharCodes(charCodes); | 7 return _StringBase.createFromCharCodes(charCodes); |
| 8 } | 8 } |
| 9 } | 9 } |
| 10 | 10 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 77 String operator +(String other) native "String_concat"; | 77 String operator +(String other) native "String_concat"; |
| 78 | 78 |
| 79 String toString() { | 79 String toString() { |
| 80 return this; | 80 return this; |
| 81 } | 81 } |
| 82 | 82 |
| 83 bool operator ==(Object other) { | 83 bool operator ==(Object other) { |
| 84 if (identical(this, other)) { | 84 if (identical(this, other)) { |
| 85 return true; | 85 return true; |
| 86 } | 86 } |
| 87 if ((other is !String) || | 87 // TODO(5413632): Compare hash codes when both are present. |
|
Ivan Posva
2013/10/28 23:35:09
I don't think comparing hash codes is effective, a
srdjan
2013/10/29 17:02:29
Done.
| |
| 88 if ((other is! String) || | |
| 88 (this.length != other.length)) { | 89 (this.length != other.length)) { |
| 89 // TODO(5413632): Compare hash codes when both are present. | |
| 90 return false; | 90 return false; |
| 91 } | 91 } |
| 92 final len = this.length; | 92 final int len = this.length; |
|
Ivan Posva
2013/10/28 23:35:09
?
srdjan
2013/10/29 17:02:29
Removed type.
| |
| 93 for (int i = 0; i < len; i++) { | 93 for (int i = 0; i < len; i++) { |
| 94 if (this.codeUnitAt(i) != other.codeUnitAt(i)) { | 94 if (this.codeUnitAt(i) != other.codeUnitAt(i)) { |
| 95 return false; | 95 return false; |
| 96 } | 96 } |
| 97 } | 97 } |
| 98 return true; | 98 return true; |
| 99 } | 99 } |
| 100 | 100 |
| 101 | 101 |
| 102 int compareTo(String other) { | 102 int compareTo(String other) { |
| (...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 417 isOneByteString = false; | 417 isOneByteString = false; |
| 418 if (s is! String) { | 418 if (s is! String) { |
| 419 throw new ArgumentError(s); | 419 throw new ArgumentError(s); |
| 420 } | 420 } |
| 421 } | 421 } |
| 422 stringList[i] = s; | 422 stringList[i] = s; |
| 423 } | 423 } |
| 424 if (isOneByteString) { | 424 if (isOneByteString) { |
| 425 return _OneByteString._concatAll(stringList, totalLength); | 425 return _OneByteString._concatAll(stringList, totalLength); |
| 426 } | 426 } |
| 427 return _concatAllNative(stringList, 0, stringList.length); | 427 return _concatRangeNative(stringList, 0, stringList.length); |
| 428 } | 428 } |
| 429 | 429 |
| 430 Iterable<Match> allMatches(String str) { | 430 Iterable<Match> allMatches(String str) { |
| 431 List<Match> result = new List<Match>(); | 431 List<Match> result = new List<Match>(); |
| 432 int length = str.length; | 432 int length = str.length; |
| 433 int patternLength = this.length; | 433 int patternLength = this.length; |
| 434 int startIndex = 0; | 434 int startIndex = 0; |
| 435 while (true) { | 435 while (true) { |
| 436 int position = str.indexOf(this, startIndex); | 436 int position = str.indexOf(this, startIndex); |
| 437 if (position == -1) { | 437 if (position == -1) { |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 502 } | 502 } |
| 503 | 503 |
| 504 List<int> get codeUnits => new _CodeUnits(this); | 504 List<int> get codeUnits => new _CodeUnits(this); |
| 505 | 505 |
| 506 Runes get runes => new Runes(this); | 506 Runes get runes => new Runes(this); |
| 507 | 507 |
| 508 String toUpperCase() native "String_toUpperCase"; | 508 String toUpperCase() native "String_toUpperCase"; |
| 509 | 509 |
| 510 String toLowerCase() native "String_toLowerCase"; | 510 String toLowerCase() native "String_toLowerCase"; |
| 511 | 511 |
| 512 // Concatenate ['start', 'end'[ elements of 'strings'. 'strings' must contain | |
| 513 // String elements. Optimized for OneByteStrings. | |
| 514 static String _concatRange(List<String> strings, int start, int end) { | |
| 515 if ((end - start) == 1) { | |
| 516 return strings[start]; | |
| 517 } | |
| 518 final int numValues = strings.length; | |
| 519 if (start == 0 && (end == numValues)) { | |
|
Ivan Posva
2013/10/28 23:35:09
(start == 0)
srdjan
2013/10/29 17:02:29
Done.
| |
| 520 int totalLength = 0; | |
| 521 for (int i = 0; i < numValues; i++) { | |
| 522 String s = strings[i]; | |
| 523 if (s._cid != _OneByteString._classId) { | |
| 524 return _concatRangeNative(strings, start, end); | |
| 525 } | |
| 526 totalLength += s.length; | |
| 527 } | |
| 528 return _OneByteString._concatAll(strings, totalLength); | |
| 529 } | |
| 530 return _concatRangeNative(strings, start, end); | |
| 531 } | |
| 532 | |
| 512 // Call this method if not all list elements are known to be OneByteString(s). | 533 // Call this method if not all list elements are known to be OneByteString(s). |
| 513 // 'strings' must be an _List or _GrowableList. | 534 // 'strings' must be an _List or _GrowableList. |
| 514 static String _concatAllNative(List<String> strings, int start, int end) | 535 static String _concatRangeNative(List<String> strings, int start, int end) |
| 515 native "Strings_concatAll"; | 536 native "String_concatRange"; |
| 516 } | 537 } |
| 517 | 538 |
| 518 | 539 |
| 519 class _OneByteString extends _StringBase implements String { | 540 class _OneByteString extends _StringBase implements String { |
| 520 static final int _classId = "A"._cid; | 541 static final int _classId = "A"._cid; |
| 521 | 542 |
| 522 factory _OneByteString._uninstantiable() { | 543 factory _OneByteString._uninstantiable() { |
| 523 throw new UnsupportedError( | 544 throw new UnsupportedError( |
| 524 "_OneByteString can only be allocated by the VM"); | 545 "_OneByteString can only be allocated by the VM"); |
| 525 } | 546 } |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 541 native "OneByteString_splitWithCharCode"; | 562 native "OneByteString_splitWithCharCode"; |
| 542 | 563 |
| 543 List<String> split(Pattern pattern) { | 564 List<String> split(Pattern pattern) { |
| 544 if ((pattern._cid == _OneByteString._classId) && (pattern.length == 1)) { | 565 if ((pattern._cid == _OneByteString._classId) && (pattern.length == 1)) { |
| 545 return _splitWithCharCode(pattern.codeUnitAt(0)); | 566 return _splitWithCharCode(pattern.codeUnitAt(0)); |
| 546 } | 567 } |
| 547 return super.split(pattern); | 568 return super.split(pattern); |
| 548 } | 569 } |
| 549 | 570 |
| 550 // All element of 'strings' must be OneByteStrings. | 571 // All element of 'strings' must be OneByteStrings. |
| 551 static _concatAll(_List<String> strings, int totalLength) { | 572 static _concatAll(List<String> strings, int totalLength) { |
| 552 // TODO(srdjan): Improve code below and raise or eliminate the limit. | 573 // TODO(srdjan): Improve code below and raise or eliminate the limit. |
| 553 if (totalLength > 128) { | 574 if (totalLength > 128) { |
| 554 // Native is quicker. | 575 // Native is quicker. |
| 555 return _StringBase._concatAllNative(strings, 0, strings.length); | 576 return _StringBase._concatRangeNative(strings, 0, strings.length); |
| 556 } | 577 } |
| 557 var res = _OneByteString._allocate(totalLength); | 578 var res = _OneByteString._allocate(totalLength); |
| 558 final stringsLength = strings.length; | 579 final stringsLength = strings.length; |
| 559 int rIx = 0; | 580 int rIx = 0; |
| 560 for (int i = 0; i < stringsLength; i++) { | 581 for (int i = 0; i < stringsLength; i++) { |
| 561 _OneByteString e = strings[i]; | 582 _OneByteString e = strings[i]; |
| 562 final eLength = e.length; | 583 final eLength = e.length; |
| 563 for (int s = 0; s < eLength; s++) { | 584 for (int s = 0; s < eLength; s++) { |
| 564 res._setAt(rIx++, e.codeUnitAt(s)); | 585 res._setAt(rIx++, e.codeUnitAt(s)); |
| 565 } | 586 } |
| 566 } | 587 } |
| 567 return res; | 588 return res; |
| 568 } | 589 } |
| 569 | 590 |
| 591 int indexOf(Pattern pattern, [int start = 0]) { | |
| 592 final int len = this.length; | |
|
Ivan Posva
2013/10/28 23:35:09
Not sure whether we should be using this. or not.
srdjan
2013/10/29 17:02:29
The name' length' is too generic, therefore I feel
| |
| 593 // Specialize for single character pattern. | |
| 594 if ((pattern._cid == _OneByteString._classId) && | |
|
Ivan Posva
2013/10/28 23:35:09
What about an ExternalOneByteString?
srdjan
2013/10/29 17:02:29
Added: TODO. The inner loop should stay monomorphi
| |
| 595 (pattern.length == 1) && | |
| 596 (start >= 0) && (start < len)) { | |
| 597 final int patternCu0 = pattern.codeUnitAt(0); | |
|
Ivan Posva
2013/10/28 23:35:09
Another quick test you could do: If the pattern is
srdjan
2013/10/29 17:02:29
Good idea, once I allow two byte strings.
| |
| 598 for (int i = start; i < len; i++) { | |
| 599 if (this.codeUnitAt(i) == patternCu0) { | |
| 600 return i; | |
| 601 } | |
| 602 } | |
| 603 return -1; | |
| 604 } | |
| 605 return super.indexOf(pattern, start); | |
| 606 } | |
| 607 | |
| 570 // Allocates a string of given length, expecting its content to be | 608 // Allocates a string of given length, expecting its content to be |
| 571 // set using _setAt. | 609 // set using _setAt. |
| 572 static _OneByteString _allocate(int length) native "OneByteString_allocate"; | 610 static _OneByteString _allocate(int length) native "OneByteString_allocate"; |
| 573 | 611 |
| 574 // This is internal helper method. Code point value must be a valid | 612 // This is internal helper method. Code point value must be a valid |
| 575 // Latin1 value (0..0xFF), index must be valid. | 613 // Latin1 value (0..0xFF), index must be valid. |
| 576 void _setAt(int index, int codePoint) native "OneByteString_setAt"; | 614 void _setAt(int index, int codePoint) native "OneByteString_setAt"; |
| 577 } | 615 } |
| 578 | 616 |
| 579 | 617 |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 660 class _CodeUnits extends Object with ListMixin<int>, | 698 class _CodeUnits extends Object with ListMixin<int>, |
| 661 UnmodifiableListMixin<int> { | 699 UnmodifiableListMixin<int> { |
| 662 /** The string that this is the code units of. */ | 700 /** The string that this is the code units of. */ |
| 663 String _string; | 701 String _string; |
| 664 | 702 |
| 665 _CodeUnits(this._string); | 703 _CodeUnits(this._string); |
| 666 | 704 |
| 667 int get length => _string.length; | 705 int get length => _string.length; |
| 668 int operator[](int i) => _string.codeUnitAt(i); | 706 int operator[](int i) => _string.codeUnitAt(i); |
| 669 } | 707 } |
| OLD | NEW |