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 /** | 5 /** |
6 * [_StringBase] contains common methods used by concrete String | 6 * [_StringBase] contains common methods used by concrete String |
7 * implementations, e.g., _OneByteString. | 7 * implementations, e.g., _OneByteString. |
8 */ | 8 */ |
9 class _StringBase { | 9 class _StringBase { |
10 | 10 |
(...skipping 20 matching lines...) Expand all Loading... |
31 } | 31 } |
32 } | 32 } |
33 return _createFromCodePoints(objectArray); | 33 return _createFromCodePoints(objectArray); |
34 } | 34 } |
35 | 35 |
36 static String _createFromCodePoints(List<int> codePoints) | 36 static String _createFromCodePoints(List<int> codePoints) |
37 native "StringBase_createFromCodePoints"; | 37 native "StringBase_createFromCodePoints"; |
38 | 38 |
39 String operator [](int index) native "String_charAt"; | 39 String operator [](int index) native "String_charAt"; |
40 | 40 |
41 int charCodeAt(int index) native "String_charCodeAt"; | 41 int codeUnitAt(int index) native "String_codeUnitAt"; |
42 | |
43 int codeUnitAt(int index) { | |
44 return charCodeAt(index); | |
45 } | |
46 | 42 |
47 int get length native "String_getLength"; | 43 int get length native "String_getLength"; |
48 | 44 |
49 bool get isEmpty { | 45 bool get isEmpty { |
50 return this.length == 0; | 46 return this.length == 0; |
51 } | 47 } |
52 | 48 |
53 String concat(String other) native "String_concat"; | 49 String concat(String other) native "String_concat"; |
54 | 50 |
55 String toString() { | 51 String toString() { |
(...skipping 10 matching lines...) Expand all Loading... |
66 return false; | 62 return false; |
67 } | 63 } |
68 return this.compareTo(other) == 0; | 64 return this.compareTo(other) == 0; |
69 } | 65 } |
70 | 66 |
71 int compareTo(String other) { | 67 int compareTo(String other) { |
72 int thisLength = this.length; | 68 int thisLength = this.length; |
73 int otherLength = other.length; | 69 int otherLength = other.length; |
74 int len = (thisLength < otherLength) ? thisLength : otherLength; | 70 int len = (thisLength < otherLength) ? thisLength : otherLength; |
75 for (int i = 0; i < len; i++) { | 71 for (int i = 0; i < len; i++) { |
76 int thisCodePoint = this.charCodeAt(i); | 72 int thisCodePoint = this.codeUnitAt(i); |
77 int otherCodePoint = other.charCodeAt(i); | 73 int otherCodePoint = other.codeUnitAt(i); |
78 if (thisCodePoint < otherCodePoint) { | 74 if (thisCodePoint < otherCodePoint) { |
79 return -1; | 75 return -1; |
80 } | 76 } |
81 if (thisCodePoint > otherCodePoint) { | 77 if (thisCodePoint > otherCodePoint) { |
82 return 1; | 78 return 1; |
83 } | 79 } |
84 } | 80 } |
85 if (thisLength < otherLength) return -1; | 81 if (thisLength < otherLength) return -1; |
86 if (thisLength > otherLength) return 1; | 82 if (thisLength > otherLength) return 1; |
87 return 0; | 83 return 0; |
88 } | 84 } |
89 | 85 |
90 bool _substringMatches(int start, String other) { | 86 bool _substringMatches(int start, String other) { |
91 if (other.isEmpty) return true; | 87 if (other.isEmpty) return true; |
92 if ((start < 0) || (start >= this.length)) { | 88 if ((start < 0) || (start >= this.length)) { |
93 return false; | 89 return false; |
94 } | 90 } |
95 final int len = other.length; | 91 final int len = other.length; |
96 if ((start + len) > this.length) { | 92 if ((start + len) > this.length) { |
97 return false; | 93 return false; |
98 } | 94 } |
99 for (int i = 0; i < len; i++) { | 95 for (int i = 0; i < len; i++) { |
100 if (this.charCodeAt(i + start) != other.charCodeAt(i)) { | 96 if (this.codeUnitAt(i + start) != other.codeUnitAt(i)) { |
101 return false; | 97 return false; |
102 } | 98 } |
103 } | 99 } |
104 return true; | 100 return true; |
105 } | 101 } |
106 | 102 |
107 bool endsWith(String other) { | 103 bool endsWith(String other) { |
108 return _substringMatches(this.length - other.length, other); | 104 return _substringMatches(this.length - other.length, other); |
109 } | 105 } |
110 | 106 |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
209 return _substringUncheckedNative(startIndex, endIndex); | 205 return _substringUncheckedNative(startIndex, endIndex); |
210 } | 206 } |
211 | 207 |
212 String _substringUncheckedNative(int startIndex, int endIndex) | 208 String _substringUncheckedNative(int startIndex, int endIndex) |
213 native "StringBase_substringUnchecked"; | 209 native "StringBase_substringUnchecked"; |
214 | 210 |
215 String trim() { | 211 String trim() { |
216 final int len = this.length; | 212 final int len = this.length; |
217 int first = 0; | 213 int first = 0; |
218 for (; first < len; first++) { | 214 for (; first < len; first++) { |
219 if (!_isWhitespace(this.charCodeAt(first))) { | 215 if (!_isWhitespace(this.codeUnitAt(first))) { |
220 break; | 216 break; |
221 } | 217 } |
222 } | 218 } |
223 if (len == first) { | 219 if (len == first) { |
224 // String contains only whitespaces. | 220 // String contains only whitespaces. |
225 return ""; | 221 return ""; |
226 } | 222 } |
227 int last = len - 1; | 223 int last = len - 1; |
228 for (; last >= first; last--) { | 224 for (; last >= first; last--) { |
229 if (!_isWhitespace(this.charCodeAt(last))) { | 225 if (!_isWhitespace(this.codeUnitAt(last))) { |
230 break; | 226 break; |
231 } | 227 } |
232 } | 228 } |
233 if ((first == 0) && (last == (len - 1))) { | 229 if ((first == 0) && (last == (len - 1))) { |
234 // Returns this string if it does not have leading or trailing | 230 // Returns this string if it does not have leading or trailing |
235 // whitespaces. | 231 // whitespaces. |
236 return this; | 232 return this; |
237 } else { | 233 } else { |
238 return _substringUnchecked(first, last + 1); | 234 return _substringUnchecked(first, last + 1); |
239 } | 235 } |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
293 String _splitMapJoinEmptyString(String onMatch(Match match), | 289 String _splitMapJoinEmptyString(String onMatch(Match match), |
294 String onNonMatch(String nonMatch)) { | 290 String onNonMatch(String nonMatch)) { |
295 // Pattern is the empty string. | 291 // Pattern is the empty string. |
296 StringBuffer buffer = new StringBuffer(); | 292 StringBuffer buffer = new StringBuffer(); |
297 int length = this.length; | 293 int length = this.length; |
298 int i = 0; | 294 int i = 0; |
299 buffer.add(onNonMatch("")); | 295 buffer.add(onNonMatch("")); |
300 while (i < length) { | 296 while (i < length) { |
301 buffer.add(onMatch(new _StringMatch(i, this, ""))); | 297 buffer.add(onMatch(new _StringMatch(i, this, ""))); |
302 // Special case to avoid splitting a surrogate pair. | 298 // Special case to avoid splitting a surrogate pair. |
303 int code = this.charCodeAt(i); | 299 int code = this.codeUnitAt(i); |
304 if ((code & ~0x3FF) == 0xD800 && length > i + 1) { | 300 if ((code & ~0x3FF) == 0xD800 && length > i + 1) { |
305 // Leading surrogate; | 301 // Leading surrogate; |
306 code = this.charCodeAt(i + 1); | 302 code = this.codeUnitAt(i + 1); |
307 if ((code & ~0x3FF) == 0xDC00) { | 303 if ((code & ~0x3FF) == 0xDC00) { |
308 // Matching trailing surrogate. | 304 // Matching trailing surrogate. |
309 buffer.add(onNonMatch(this.substring(i, i + 2))); | 305 buffer.add(onNonMatch(this.substring(i, i + 2))); |
310 i += 2; | 306 i += 2; |
311 continue; | 307 continue; |
312 } | 308 } |
313 } | 309 } |
314 buffer.add(onNonMatch(this[i])); | 310 buffer.add(onNonMatch(this[i])); |
315 i++; | 311 i++; |
316 } | 312 } |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
376 ++startIndex; // empty match, advance and restart | 372 ++startIndex; // empty match, advance and restart |
377 } else { | 373 } else { |
378 startIndex = endIndex; | 374 startIndex = endIndex; |
379 } | 375 } |
380 } | 376 } |
381 return result; | 377 return result; |
382 } | 378 } |
383 | 379 |
384 List<String> split(Pattern pattern) { | 380 List<String> split(Pattern pattern) { |
385 if ((pattern is String) && pattern.isEmpty) { | 381 if ((pattern is String) && pattern.isEmpty) { |
386 return splitChars(); | 382 List<String> result = new List<String>(length); |
| 383 for (int i = 0; i < length; i++) { |
| 384 result[i] = this[i]; |
| 385 } |
| 386 return result; |
387 } | 387 } |
388 int length = this.length; | 388 int length = this.length; |
389 Iterator iterator = pattern.allMatches(this).iterator; | 389 Iterator iterator = pattern.allMatches(this).iterator; |
390 if (length == 0 && iterator.moveNext()) { | 390 if (length == 0 && iterator.moveNext()) { |
391 // A matched empty string input returns the empty list. | 391 // A matched empty string input returns the empty list. |
392 return <String>[]; | 392 return <String>[]; |
393 } | 393 } |
394 List<String> result = new List<String>(); | 394 List<String> result = new List<String>(); |
395 int startIndex = 0; | 395 int startIndex = 0; |
396 int previousIndex = 0; | 396 int previousIndex = 0; |
(...skipping 11 matching lines...) Expand all Loading... |
408 if (startIndex == endIndex && endIndex == previousIndex) { | 408 if (startIndex == endIndex && endIndex == previousIndex) { |
409 ++startIndex; // empty match, advance and restart | 409 ++startIndex; // empty match, advance and restart |
410 continue; | 410 continue; |
411 } | 411 } |
412 result.add(this._substringUnchecked(previousIndex, match.start)); | 412 result.add(this._substringUnchecked(previousIndex, match.start)); |
413 startIndex = previousIndex = endIndex; | 413 startIndex = previousIndex = endIndex; |
414 } | 414 } |
415 return result; | 415 return result; |
416 } | 416 } |
417 | 417 |
418 List<String> splitChars() { | 418 List<int> get codeUnits => new CodeUnits(this); |
419 int len = this.length; | |
420 final result = new List<String>.fixedLength(len); | |
421 for (int i = 0; i < len; i++) { | |
422 result[i] = this[i]; | |
423 } | |
424 return result; | |
425 } | |
426 | |
427 List<int> get charCodes { | |
428 int len = this.length; | |
429 final result = new List<int>.fixedLength(len); | |
430 for (int i = 0; i < len; i++) { | |
431 result[i] = this.charCodeAt(i); | |
432 } | |
433 return result; | |
434 } | |
435 | |
436 Iterable<int> get codeUnits => new CodeUnits(this); | |
437 | 419 |
438 Runes get runes => new Runes(this); | 420 Runes get runes => new Runes(this); |
439 | 421 |
440 String toUpperCase() native "String_toUpperCase"; | 422 String toUpperCase() native "String_toUpperCase"; |
441 | 423 |
442 String toLowerCase() native "String_toLowerCase"; | 424 String toLowerCase() native "String_toLowerCase"; |
443 | 425 |
444 // Implementations of Strings methods follow below. | 426 // Implementations of Strings methods follow below. |
445 static String join(Iterable<String> strings, String separator) { | 427 static String join(Iterable<String> strings, String separator) { |
446 bool first = true; | 428 bool first = true; |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
500 } | 482 } |
501 | 483 |
502 String _substringUncheckedNative(int startIndex, int endIndex) | 484 String _substringUncheckedNative(int startIndex, int endIndex) |
503 native "OneByteString_substringUnchecked"; | 485 native "OneByteString_substringUnchecked"; |
504 | 486 |
505 List<String> _splitWithCharCode(int charCode) | 487 List<String> _splitWithCharCode(int charCode) |
506 native "OneByteString_splitWithCharCode"; | 488 native "OneByteString_splitWithCharCode"; |
507 | 489 |
508 List<String> split(Pattern pattern) { | 490 List<String> split(Pattern pattern) { |
509 if ((pattern is _OneByteString) && (pattern.length == 1)) { | 491 if ((pattern is _OneByteString) && (pattern.length == 1)) { |
510 return _splitWithCharCode(pattern.charCodeAt(0)); | 492 return _splitWithCharCode(pattern.codeUnitAt(0)); |
511 } | 493 } |
512 return super.split(pattern); | 494 return super.split(pattern); |
513 } | 495 } |
514 } | 496 } |
515 | 497 |
516 | 498 |
517 class _TwoByteString extends _StringBase implements String { | 499 class _TwoByteString extends _StringBase implements String { |
518 factory _TwoByteString._uninstantiable() { | 500 factory _TwoByteString._uninstantiable() { |
519 throw new UnsupportedError( | 501 throw new UnsupportedError( |
520 "_TwoByteString can only be allocated by the VM"); | 502 "_TwoByteString can only be allocated by the VM"); |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
620 for (int g in groups) { | 602 for (int g in groups) { |
621 result.add(group(g)); | 603 result.add(group(g)); |
622 } | 604 } |
623 return result; | 605 return result; |
624 } | 606 } |
625 | 607 |
626 final int start; | 608 final int start; |
627 final String str; | 609 final String str; |
628 final String pattern; | 610 final String pattern; |
629 } | 611 } |
OLD | NEW |