| 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 if ((other is! String) || |
| 88 (this.length != other.length)) { | 88 (this.length != other.length)) { |
| 89 // TODO(5413632): Compare hash codes when both are present. | |
| 90 return false; | 89 return false; |
| 91 } | 90 } |
| 92 final len = this.length; | 91 final len = this.length; |
| 93 for (int i = 0; i < len; i++) { | 92 for (int i = 0; i < len; i++) { |
| 94 if (this.codeUnitAt(i) != other.codeUnitAt(i)) { | 93 if (this.codeUnitAt(i) != other.codeUnitAt(i)) { |
| 95 return false; | 94 return false; |
| 96 } | 95 } |
| 97 } | 96 } |
| 98 return true; | 97 return true; |
| 99 } | 98 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 113 return 1; | 112 return 1; |
| 114 } | 113 } |
| 115 } | 114 } |
| 116 if (thisLength < otherLength) return -1; | 115 if (thisLength < otherLength) return -1; |
| 117 if (thisLength > otherLength) return 1; | 116 if (thisLength > otherLength) return 1; |
| 118 return 0; | 117 return 0; |
| 119 } | 118 } |
| 120 | 119 |
| 121 bool _substringMatches(int start, String other) { | 120 bool _substringMatches(int start, String other) { |
| 122 if (other.isEmpty) return true; | 121 if (other.isEmpty) return true; |
| 123 final int len = other.length; | 122 final len = other.length; |
| 124 if ((start < 0) || (start + len > this.length)) { | 123 if ((start < 0) || (start + len > this.length)) { |
| 125 return false; | 124 return false; |
| 126 } | 125 } |
| 127 for (int i = 0; i < len; i++) { | 126 for (int i = 0; i < len; i++) { |
| 128 if (this.codeUnitAt(i + start) != other.codeUnitAt(i)) { | 127 if (this.codeUnitAt(i + start) != other.codeUnitAt(i)) { |
| 129 return false; | 128 return false; |
| 130 } | 129 } |
| 131 } | 130 } |
| 132 return true; | 131 return true; |
| 133 } | 132 } |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 258 ((0x2000 <= codePoint) && (codePoint <= 0x200A)) || | 257 ((0x2000 <= codePoint) && (codePoint <= 0x200A)) || |
| 259 (codePoint == 0x2028) || | 258 (codePoint == 0x2028) || |
| 260 (codePoint == 0x2029) || | 259 (codePoint == 0x2029) || |
| 261 (codePoint == 0x202F) || | 260 (codePoint == 0x202F) || |
| 262 (codePoint == 0x205F) || | 261 (codePoint == 0x205F) || |
| 263 (codePoint == 0x3000) || | 262 (codePoint == 0x3000) || |
| 264 (codePoint == 0xFEFF); | 263 (codePoint == 0xFEFF); |
| 265 } | 264 } |
| 266 | 265 |
| 267 String trim() { | 266 String trim() { |
| 268 final int len = this.length; | 267 final len = this.length; |
| 269 int first = 0; | 268 int first = 0; |
| 270 for (; first < len; first++) { | 269 for (; first < len; first++) { |
| 271 if (!_isWhitespace(this.codeUnitAt(first))) { | 270 if (!_isWhitespace(this.codeUnitAt(first))) { |
| 272 break; | 271 break; |
| 273 } | 272 } |
| 274 } | 273 } |
| 275 if (len == first) { | 274 if (len == first) { |
| 276 // String contains only whitespaces. | 275 // String contains only whitespaces. |
| 277 return ""; | 276 return ""; |
| 278 } | 277 } |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 398 buffer.write(onNonMatch(this.substring(startIndex))); | 397 buffer.write(onNonMatch(this.substring(startIndex))); |
| 399 return buffer.toString(); | 398 return buffer.toString(); |
| 400 } | 399 } |
| 401 | 400 |
| 402 | 401 |
| 403 /** | 402 /** |
| 404 * Convert all objects in [values] to strings and concat them | 403 * Convert all objects in [values] to strings and concat them |
| 405 * into a result string. | 404 * into a result string. |
| 406 */ | 405 */ |
| 407 static String _interpolate(List<String> values) { | 406 static String _interpolate(List<String> values) { |
| 408 final int numValues = values.length; | 407 final numValues = values.length; |
| 409 _List stringList = new List<String>(numValues); | 408 _List stringList = new List<String>(numValues); |
| 410 bool isOneByteString = true; | 409 bool isOneByteString = true; |
| 411 int totalLength = 0; | 410 int totalLength = 0; |
| 412 for (int i = 0; i < numValues; i++) { | 411 for (int i = 0; i < numValues; i++) { |
| 413 var s = values[i].toString(); | 412 var s = values[i].toString(); |
| 414 if (isOneByteString && (s._cid == _OneByteString._classId)) { | 413 if (isOneByteString && (s._cid == _OneByteString._classId)) { |
| 415 totalLength += s.length; | 414 totalLength += s.length; |
| 416 } else { | 415 } else { |
| 417 isOneByteString = false; | 416 isOneByteString = false; |
| 418 if (s is! String) { | 417 if (s is! String) { |
| 419 throw new ArgumentError(s); | 418 throw new ArgumentError(s); |
| 420 } | 419 } |
| 421 } | 420 } |
| 422 stringList[i] = s; | 421 stringList[i] = s; |
| 423 } | 422 } |
| 424 if (isOneByteString) { | 423 if (isOneByteString) { |
| 425 return _OneByteString._concatAll(stringList, totalLength); | 424 return _OneByteString._concatAll(stringList, totalLength); |
| 426 } | 425 } |
| 427 return _concatAllNative(stringList, 0, stringList.length); | 426 return _concatRangeNative(stringList, 0, stringList.length); |
| 428 } | 427 } |
| 429 | 428 |
| 430 Iterable<Match> allMatches(String str) { | 429 Iterable<Match> allMatches(String str) { |
| 431 List<Match> result = new List<Match>(); | 430 List<Match> result = new List<Match>(); |
| 432 int length = str.length; | 431 int length = str.length; |
| 433 int patternLength = this.length; | 432 int patternLength = this.length; |
| 434 int startIndex = 0; | 433 int startIndex = 0; |
| 435 while (true) { | 434 while (true) { |
| 436 int position = str.indexOf(this, startIndex); | 435 int position = str.indexOf(this, startIndex); |
| 437 if (position == -1) { | 436 if (position == -1) { |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 502 } | 501 } |
| 503 | 502 |
| 504 List<int> get codeUnits => new _CodeUnits(this); | 503 List<int> get codeUnits => new _CodeUnits(this); |
| 505 | 504 |
| 506 Runes get runes => new Runes(this); | 505 Runes get runes => new Runes(this); |
| 507 | 506 |
| 508 String toUpperCase() native "String_toUpperCase"; | 507 String toUpperCase() native "String_toUpperCase"; |
| 509 | 508 |
| 510 String toLowerCase() native "String_toLowerCase"; | 509 String toLowerCase() native "String_toLowerCase"; |
| 511 | 510 |
| 511 // Concatenate ['start', 'end'[ elements of 'strings'. 'strings' must contain |
| 512 // String elements. Optimized for OneByteStrings. |
| 513 static String _concatRange(List<String> strings, int start, int end) { |
| 514 if ((end - start) == 1) { |
| 515 return strings[start]; |
| 516 } |
| 517 final numValues = strings.length; |
| 518 if ((start == 0) && (end == numValues)) { |
| 519 int totalLength = 0; |
| 520 for (int i = 0; i < numValues; i++) { |
| 521 String s = strings[i]; |
| 522 if (s._cid != _OneByteString._classId) { |
| 523 return _concatRangeNative(strings, start, end); |
| 524 } |
| 525 totalLength += s.length; |
| 526 } |
| 527 return _OneByteString._concatAll(strings, totalLength); |
| 528 } |
| 529 return _concatRangeNative(strings, start, end); |
| 530 } |
| 531 |
| 512 // Call this method if not all list elements are known to be OneByteString(s). | 532 // Call this method if not all list elements are known to be OneByteString(s). |
| 513 // 'strings' must be an _List or _GrowableList. | 533 // 'strings' must be an _List or _GrowableList. |
| 514 static String _concatAllNative(List<String> strings, int start, int end) | 534 static String _concatRangeNative(List<String> strings, int start, int end) |
| 515 native "Strings_concatAll"; | 535 native "String_concatRange"; |
| 516 } | 536 } |
| 517 | 537 |
| 518 | 538 |
| 519 class _OneByteString extends _StringBase implements String { | 539 class _OneByteString extends _StringBase implements String { |
| 520 static final int _classId = "A"._cid; | 540 static final int _classId = "A"._cid; |
| 521 | 541 |
| 522 factory _OneByteString._uninstantiable() { | 542 factory _OneByteString._uninstantiable() { |
| 523 throw new UnsupportedError( | 543 throw new UnsupportedError( |
| 524 "_OneByteString can only be allocated by the VM"); | 544 "_OneByteString can only be allocated by the VM"); |
| 525 } | 545 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 541 native "OneByteString_splitWithCharCode"; | 561 native "OneByteString_splitWithCharCode"; |
| 542 | 562 |
| 543 List<String> split(Pattern pattern) { | 563 List<String> split(Pattern pattern) { |
| 544 if ((pattern._cid == _OneByteString._classId) && (pattern.length == 1)) { | 564 if ((pattern._cid == _OneByteString._classId) && (pattern.length == 1)) { |
| 545 return _splitWithCharCode(pattern.codeUnitAt(0)); | 565 return _splitWithCharCode(pattern.codeUnitAt(0)); |
| 546 } | 566 } |
| 547 return super.split(pattern); | 567 return super.split(pattern); |
| 548 } | 568 } |
| 549 | 569 |
| 550 // All element of 'strings' must be OneByteStrings. | 570 // All element of 'strings' must be OneByteStrings. |
| 551 static _concatAll(_List<String> strings, int totalLength) { | 571 static _concatAll(List<String> strings, int totalLength) { |
| 552 // TODO(srdjan): Improve code below and raise or eliminate the limit. | 572 // TODO(srdjan): Improve code below and raise or eliminate the limit. |
| 553 if (totalLength > 128) { | 573 if (totalLength > 128) { |
| 554 // Native is quicker. | 574 // Native is quicker. |
| 555 return _StringBase._concatAllNative(strings, 0, strings.length); | 575 return _StringBase._concatRangeNative(strings, 0, strings.length); |
| 556 } | 576 } |
| 557 var res = _OneByteString._allocate(totalLength); | 577 var res = _OneByteString._allocate(totalLength); |
| 558 final stringsLength = strings.length; | 578 final stringsLength = strings.length; |
| 559 int rIx = 0; | 579 int rIx = 0; |
| 560 for (int i = 0; i < stringsLength; i++) { | 580 for (int i = 0; i < stringsLength; i++) { |
| 561 _OneByteString e = strings[i]; | 581 _OneByteString e = strings[i]; |
| 562 final eLength = e.length; | 582 final eLength = e.length; |
| 563 for (int s = 0; s < eLength; s++) { | 583 for (int s = 0; s < eLength; s++) { |
| 564 res._setAt(rIx++, e.codeUnitAt(s)); | 584 res._setAt(rIx++, e.codeUnitAt(s)); |
| 565 } | 585 } |
| 566 } | 586 } |
| 567 return res; | 587 return res; |
| 568 } | 588 } |
| 569 | 589 |
| 590 int indexOf(Pattern pattern, [int start = 0]) { |
| 591 final len = this.length; |
| 592 // Specialize for single character pattern. |
| 593 // TODO(srdjan): Implement for other string classes. |
| 594 if ((pattern._cid == _OneByteString._classId) && |
| 595 (pattern.length == 1) && |
| 596 (start >= 0) && (start < len)) { |
| 597 final patternCu0 = pattern.codeUnitAt(0); |
| 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 |