| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 part of dart.core; | |
| 6 | |
| 7 /** | |
| 8 * A sequence of characters. | |
| 9 * | |
| 10 * A string can be either single or multiline. Single line strings are | |
| 11 * written using matching single or double quotes, and multiline strings are | |
| 12 * written using triple quotes. The following are all valid Dart strings: | |
| 13 * | |
| 14 * 'Single quotes'; | |
| 15 * "Double quotes"; | |
| 16 * 'Double quotes in "single" quotes'; | |
| 17 * "Single quotes in 'double' quotes"; | |
| 18 * | |
| 19 * '''A | |
| 20 * multiline | |
| 21 * string'''; | |
| 22 * | |
| 23 * """ | |
| 24 * Another | |
| 25 * multiline | |
| 26 * string"""; | |
| 27 * | |
| 28 * Strings are immutable. Although you cannot change a string, you can perform | |
| 29 * an operation on a string and assign the result to a new string: | |
| 30 * | |
| 31 * var string = 'Dart is fun'; | |
| 32 * var newString = string.substring(0, 5); | |
| 33 * | |
| 34 * You can use the plus (`+`) operator to concatenate strings: | |
| 35 * | |
| 36 * 'Dart ' + 'is ' + 'fun!'; // 'Dart is fun!' | |
| 37 * | |
| 38 * You can also use adjacent string literals for concatenation: | |
| 39 * | |
| 40 * 'Dart ' 'is ' 'fun!'; // 'Dart is fun!' | |
| 41 * | |
| 42 * You can use `${}` to interpolate the value of Dart expressions | |
| 43 * within strings. The curly braces can be omitted when evaluating identifiers: | |
| 44 * | |
| 45 * string = 'dartlang'; | |
| 46 * '$string has ${string.length} letters'; // 'dartlang has 8 letters' | |
| 47 * | |
| 48 * A string is represented by a sequence of Unicode UTF-16 code units | |
| 49 * accessible through the [codeUnitAt] or the [codeUnits] members: | |
| 50 * | |
| 51 * string = 'Dart'; | |
| 52 * string.codeUnitAt(0); // 68 | |
| 53 * string.codeUnits; // [68, 97, 114, 116] | |
| 54 * | |
| 55 * The string representation of code units is accessible through the index | |
| 56 * operator: | |
| 57 * | |
| 58 * string[0]; // 'D' | |
| 59 * | |
| 60 * The characters of a string are encoded in UTF-16. Decoding UTF-16, which | |
| 61 * combines surrogate pairs, yields Unicode code points. Following a similar | |
| 62 * terminology to Go, we use the name 'rune' for an integer representing a | |
| 63 * Unicode code point. Use the [runes] property to get the runes of a string: | |
| 64 * | |
| 65 * string.runes.toList(); // [68, 97, 114, 116] | |
| 66 * | |
| 67 * For a character outside the Basic Multilingual Plane (plane 0) that is | |
| 68 * composed of a surrogate pair, [runes] combines the pair and returns a | |
| 69 * single integer. For example, the Unicode character for a | |
| 70 * musical G-clef ('𝄞') with rune value 0x1D11E consists of a UTF-16 surrogate | |
| 71 * pair: `0xD834` and `0xDD1E`. Using [codeUnits] returns the surrogate pair, | |
| 72 * and using `runes` returns their combined value: | |
| 73 * | |
| 74 * var clef = '\u{1D11E}'; | |
| 75 * clef.codeUnits; // [0xD834, 0xDD1E] | |
| 76 * clef.runes.toList(); // [0x1D11E] | |
| 77 * | |
| 78 * The String class can not be extended or implemented. Attempting to do so | |
| 79 * yields a compile-time error. | |
| 80 * | |
| 81 * ## Other resources | |
| 82 * | |
| 83 * See [StringBuffer] to efficiently build a string incrementally. See | |
| 84 * [RegExp] to work with regular expressions. | |
| 85 * | |
| 86 * Also see: | |
| 87 | |
| 88 * * [Dart Cookbook](https://www.dartlang.org/docs/cookbook/#strings) | |
| 89 * for String examples and recipes. | |
| 90 * * [Dart Up and Running] | |
| 91 * (https://www.dartlang.org/docs/dart-up-and-running/contents/ch03.html#ch03-st
rings-and-regular-expressions) | |
| 92 */ | |
| 93 abstract class String implements Comparable<String>, Pattern { | |
| 94 /** | |
| 95 * Allocates a new String for the specified [charCodes]. | |
| 96 * | |
| 97 * The [charCodes] can be UTF-16 code units or runes. If a char-code value is | |
| 98 * 16-bit, it is copied verbatim: | |
| 99 * | |
| 100 * new String.fromCharCodes([68]); // 'D' | |
| 101 * | |
| 102 * If a char-code value is greater than 16-bits, it is decomposed into a | |
| 103 * surrogate pair: | |
| 104 * | |
| 105 * var clef = new String.fromCharCodes([0x1D11E]); | |
| 106 * clef.codeUnitAt(0); // 0xD834 | |
| 107 * clef.codeUnitAt(1); // 0xDD1E | |
| 108 * | |
| 109 * If [start] and [end] is provided, only the values of [charCodes] | |
| 110 * at positions from `start` to, but not including, `end`, are used. | |
| 111 * The `start` and `end` values must satisfy | |
| 112 * `0 <= start <= end <= charCodes.length`. | |
| 113 */ | |
| 114 factory String.fromCharCodes(Iterable<int> charCodes, | |
| 115 [int start = 0, int end]) { | |
| 116 // If possible, recognize typed lists too. | |
| 117 if (charCodes is! JSArray) { | |
| 118 return _stringFromIterable(charCodes, start, end); | |
| 119 } | |
| 120 | |
| 121 List list = charCodes; | |
| 122 int len = list.length; | |
| 123 if (start < 0 || start > len) { | |
| 124 throw new RangeError.range(start, 0, len); | |
| 125 } | |
| 126 if (end == null) { | |
| 127 end = len; | |
| 128 } else if (end < start || end > len) { | |
| 129 throw new RangeError.range(end, start, len); | |
| 130 } | |
| 131 | |
| 132 if (start > 0 || end < len) { | |
| 133 list = list.sublist(start, end); | |
| 134 } | |
| 135 return Primitives.stringFromCharCodes(list); | |
| 136 } | |
| 137 | |
| 138 /** | |
| 139 * Allocates a new String for the specified [charCode]. | |
| 140 * | |
| 141 * If the [charCode] can be represented by a single UTF-16 code unit, the new | |
| 142 * string contains a single code unit. Otherwise, the [length] is 2 and | |
| 143 * the code units form a surrogate pair. See documentation for | |
| 144 * [fromCharCodes]. | |
| 145 * | |
| 146 * Creating a String with half of a surrogate pair is allowed. | |
| 147 */ | |
| 148 factory String.fromCharCode(int charCode) { | |
| 149 return Primitives.stringFromCharCode(charCode); | |
| 150 } | |
| 151 | |
| 152 /** | |
| 153 * Returns the string value of the environment declaration [name]. | |
| 154 * | |
| 155 * Environment declarations are provided by the surrounding system compiling | |
| 156 * or running the Dart program. Declarations map a string key to a string | |
| 157 * value. | |
| 158 * | |
| 159 * If [name] is not declared in the environment, the result is instead | |
| 160 * [defaultValue]. | |
| 161 * | |
| 162 * Example of getting a value: | |
| 163 * | |
| 164 * const String.fromEnvironment("defaultFloo", defaultValue: "no floo") | |
| 165 * | |
| 166 * Example of checking whether a declaration is there at all: | |
| 167 * | |
| 168 * var isDeclared = const String.fromEnvironment("maybeDeclared") != null; | |
| 169 */ | |
| 170 factory String.fromEnvironment(String name, {String defaultValue}) { | |
| 171 throw new UnsupportedError( | |
| 172 'String.fromEnvironment can only be used as a const constructor'); | |
| 173 } | |
| 174 | |
| 175 /** | |
| 176 * Gets the character (as a single-code-unit [String]) at the given [index]. | |
| 177 * | |
| 178 * The returned string represents exactly one UTF-16 code unit, which may be | |
| 179 * half of a surrogate pair. A single member of a surrogate pair is an | |
| 180 * invalid UTF-16 string: | |
| 181 * | |
| 182 * var clef = '\u{1D11E}'; | |
| 183 * // These represent invalid UTF-16 strings. | |
| 184 * clef[0].codeUnits; // [0xD834] | |
| 185 * clef[1].codeUnits; // [0xDD1E] | |
| 186 * | |
| 187 * This method is equivalent to | |
| 188 * `new String.fromCharCode(this.codeUnitAt(index))`. | |
| 189 */ | |
| 190 String operator [](int index); | |
| 191 | |
| 192 /** | |
| 193 * Returns the 16-bit UTF-16 code unit at the given [index]. | |
| 194 */ | |
| 195 int codeUnitAt(int index); | |
| 196 | |
| 197 /** | |
| 198 * The length of the string. | |
| 199 * | |
| 200 * Returns the number of UTF-16 code units in this string. The number | |
| 201 * of [runes] might be fewer, if the string contains characters outside | |
| 202 * the Basic Multilingual Plane (plane 0): | |
| 203 * | |
| 204 * 'Dart'.length; // 4 | |
| 205 * 'Dart'.runes.length; // 4 | |
| 206 * | |
| 207 * var clef = '\u{1D11E}'; | |
| 208 * clef.length; // 2 | |
| 209 * clef.runes.length; // 1 | |
| 210 */ | |
| 211 int get length; | |
| 212 | |
| 213 /** | |
| 214 * Returns a hash code derived from the code units of the string. | |
| 215 * | |
| 216 * This is compatible with [operator==]. Strings with the same sequence | |
| 217 * of code units have the same hash code. | |
| 218 */ | |
| 219 int get hashCode; | |
| 220 | |
| 221 /** | |
| 222 * Returns true if other is a `String` with the same sequence of code units. | |
| 223 * | |
| 224 * This method compares each individual code unit of the strings. | |
| 225 * It does not check for Unicode equivalence. | |
| 226 * For example, both the following strings represent the string 'Amélie', | |
| 227 * but due to their different encoding, are not equal: | |
| 228 * | |
| 229 * 'Am\xe9lie' == 'Ame\u{301}lie'; // false | |
| 230 * | |
| 231 * The first string encodes 'é' as a single unicode code unit (also | |
| 232 * a single rune), whereas the second string encodes it as 'e' with the | |
| 233 * combining accent character '◌́'. | |
| 234 */ | |
| 235 bool operator ==(Object other); | |
| 236 | |
| 237 /** | |
| 238 * Returns true if this string ends with [other]. For example: | |
| 239 * | |
| 240 * 'Dart'.endsWith('t'); // true | |
| 241 */ | |
| 242 bool endsWith(String other); | |
| 243 | |
| 244 /** | |
| 245 * Returns true if this string starts with a match of [pattern]. | |
| 246 * | |
| 247 * var string = 'Dart'; | |
| 248 * string.startsWith('D'); // true | |
| 249 * string.startsWith(new RegExp(r'[A-Z][a-z]')); // true | |
| 250 * | |
| 251 * If [index] is provided, this method checks if the substring starting | |
| 252 * at that index starts with a match of [pattern]: | |
| 253 * | |
| 254 * string.startsWith('art', 1); // true | |
| 255 * string.startsWith(new RegExp(r'\w{3}')); // true | |
| 256 * | |
| 257 * [index] must not be negative or greater than [length]. | |
| 258 * | |
| 259 * A [RegExp] containing '^' does not match if the [index] is greater than | |
| 260 * zero. The pattern works on the string as a whole, and does not extract | |
| 261 * a substring starting at [index] first: | |
| 262 * | |
| 263 * string.startsWith(new RegExp(r'^art'), 1); // false | |
| 264 * string.startsWith(new RegExp(r'art'), 1); // true | |
| 265 */ | |
| 266 bool startsWith(Pattern pattern, [int index = 0]); | |
| 267 | |
| 268 /** | |
| 269 * Returns the position of the first match of [pattern] in this string, | |
| 270 * starting at [start], inclusive: | |
| 271 * | |
| 272 * var string = 'Dartisans'; | |
| 273 * string.indexOf('art'); // 1 | |
| 274 * string.indexOf(new RegExp(r'[A-Z][a-z]')); // 0 | |
| 275 * | |
| 276 * Returns -1 if no match is found: | |
| 277 * | |
| 278 * string.indexOf(new RegExp(r'dart')); // -1 | |
| 279 * | |
| 280 * [start] must not be negative or greater than [length]. | |
| 281 */ | |
| 282 int indexOf(Pattern pattern, [int start]); | |
| 283 | |
| 284 /** | |
| 285 * Returns the position of the last match [pattern] in this string, searching | |
| 286 * backward starting at [start], inclusive: | |
| 287 * | |
| 288 * var string = 'Dartisans'; | |
| 289 * string.lastIndexOf('a'); // 6 | |
| 290 * string.lastIndexOf(new RegExp(r'a(r|n)')); // 6 | |
| 291 * | |
| 292 * Returns -1 if [other] could not be found. | |
| 293 * | |
| 294 * string.lastIndexOf(new RegExp(r'DART')); // -1 | |
| 295 * | |
| 296 * [start] must not be negative or greater than [length]. | |
| 297 */ | |
| 298 int lastIndexOf(Pattern pattern, [int start]); | |
| 299 | |
| 300 /** | |
| 301 * Returns true if this string is empty. | |
| 302 */ | |
| 303 bool get isEmpty; | |
| 304 | |
| 305 /** | |
| 306 * Returns true if this string is not empty. | |
| 307 */ | |
| 308 bool get isNotEmpty; | |
| 309 | |
| 310 /** | |
| 311 * Creates a new string by concatenating this string with [other]. | |
| 312 * | |
| 313 * 'dart' + 'lang'; // 'dartlang' | |
| 314 */ | |
| 315 String operator +(String other); | |
| 316 | |
| 317 /** | |
| 318 * Returns the substring of this string that extends from [startIndex], | |
| 319 * inclusive, to [endIndex], exclusive. | |
| 320 * | |
| 321 * var string = 'dartlang'; | |
| 322 * string.substring(1); // 'artlang' | |
| 323 * string.substring(1, 4); // 'art' | |
| 324 */ | |
| 325 String substring(int startIndex, [int endIndex]); | |
| 326 | |
| 327 /** | |
| 328 * Returns the string without any leading and trailing whitespace. | |
| 329 * | |
| 330 * If the string contains leading or trailing whitespace, a new string with no | |
| 331 * leading and no trailing whitespace is returned: | |
| 332 * | |
| 333 * '\tDart is fun\n'.trim(); // 'Dart is fun' | |
| 334 * | |
| 335 * Otherwise, the original string itself is returned: | |
| 336 * | |
| 337 * var str1 = 'Dart'; | |
| 338 * var str2 = str1.trim(); | |
| 339 * identical(str1, str2); // true | |
| 340 * | |
| 341 * Whitespace is defined by the Unicode White_Space property (as defined in | |
| 342 * version 6.2 or later) and the BOM character, 0xFEFF. | |
| 343 * | |
| 344 * Here is the list of trimmed characters (following version 6.2): | |
| 345 * | |
| 346 * 0009..000D ; White_Space # Cc <control-0009>..<control-000D> | |
| 347 * 0020 ; White_Space # Zs SPACE | |
| 348 * 0085 ; White_Space # Cc <control-0085> | |
| 349 * 00A0 ; White_Space # Zs NO-BREAK SPACE | |
| 350 * 1680 ; White_Space # Zs OGHAM SPACE MARK | |
| 351 * 180E ; White_Space # Zs MONGOLIAN VOWEL SEPARATOR | |
| 352 * 2000..200A ; White_Space # Zs EN QUAD..HAIR SPACE | |
| 353 * 2028 ; White_Space # Zl LINE SEPARATOR | |
| 354 * 2029 ; White_Space # Zp PARAGRAPH SEPARATOR | |
| 355 * 202F ; White_Space # Zs NARROW NO-BREAK SPACE | |
| 356 * 205F ; White_Space # Zs MEDIUM MATHEMATICAL SPACE | |
| 357 * 3000 ; White_Space # Zs IDEOGRAPHIC SPACE | |
| 358 * | |
| 359 * FEFF ; BOM ZERO WIDTH NO_BREAK SPACE | |
| 360 */ | |
| 361 String trim(); | |
| 362 | |
| 363 /** | |
| 364 * Returns the string without any leading whitespace. | |
| 365 * | |
| 366 * As [trim], but only removes leading whitespace. | |
| 367 */ | |
| 368 String trimLeft(); | |
| 369 | |
| 370 /** | |
| 371 * Returns the string without any trailing whitespace. | |
| 372 * | |
| 373 * As [trim], but only removes trailing whitespace. | |
| 374 */ | |
| 375 String trimRight(); | |
| 376 | |
| 377 /** | |
| 378 * Creates a new string by concatenating this string with itself a number | |
| 379 * of times. | |
| 380 * | |
| 381 * The result of `str * n` is equivalent to | |
| 382 * `str + str + ...`(n times)`... + str`. | |
| 383 * | |
| 384 * Returns an empty string if [times] is zero or negative. | |
| 385 */ | |
| 386 String operator *(int times); | |
| 387 | |
| 388 /** | |
| 389 * Pads this string on the left if it is shorther than [width]. | |
| 390 * | |
| 391 * Return a new string that prepends [padding] onto this string | |
| 392 * one time for each position the length is less than [width]. | |
| 393 * | |
| 394 * If [width] is already smaller than or equal to `this.length`, | |
| 395 * no padding is added. A negative `width` is treated as zero. | |
| 396 * | |
| 397 * If [padding] has length different from 1, the result will not | |
| 398 * have length `width`. This may be useful for cases where the | |
| 399 * padding is a longer string representing a single character, like | |
| 400 * `" "` or `"\u{10002}`". | |
| 401 * In that case, the user should make sure that `this.length` is | |
| 402 * the correct measure of the strings length. | |
| 403 */ | |
| 404 String padLeft(int width, [String padding = ' ']); | |
| 405 | |
| 406 /** | |
| 407 * Pads this string on the right if it is shorther than [width]. | |
| 408 * | |
| 409 * Return a new string that appends [padding] after this string | |
| 410 * one time for each position the length is less than [width]. | |
| 411 * | |
| 412 * If [width] is already smaller than or equal to `this.length`, | |
| 413 * no padding is added. A negative `width` is treated as zero. | |
| 414 * | |
| 415 * If [padding] has length different from 1, the result will not | |
| 416 * have length `width`. This may be useful for cases where the | |
| 417 * padding is a longer string representing a single character, like | |
| 418 * `" "` or `"\u{10002}`". | |
| 419 * In that case, the user should make sure that `this.length` is | |
| 420 * the correct measure of the strings length. | |
| 421 */ | |
| 422 String padRight(int width, [String padding = ' ']); | |
| 423 | |
| 424 /** | |
| 425 * Returns true if this string contains a match of [other]: | |
| 426 * | |
| 427 * var string = 'Dart strings'; | |
| 428 * string.contains('D'); // true | |
| 429 * string.contains(new RegExp(r'[A-Z]')); // true | |
| 430 * | |
| 431 * If [startIndex] is provided, this method matches only at or after that | |
| 432 * index: | |
| 433 * | |
| 434 * string.contains('X', 1); // false | |
| 435 * string.contains(new RegExp(r'[A-Z]'), 1); // false | |
| 436 * | |
| 437 * [startIndex] must not be negative or greater than [length]. | |
| 438 */ | |
| 439 bool contains(Pattern other, [int startIndex = 0]); | |
| 440 | |
| 441 /** | |
| 442 * Returns a new string in which the first occurence of [from] in this string | |
| 443 * is replaced with [to], starting from [startIndex]: | |
| 444 * | |
| 445 * '0.0001'.replaceFirst(new RegExp(r'0'), ''); // '.0001' | |
| 446 * '0.0001'.replaceFirst(new RegExp(r'0'), '7', 1); // '0.7001' | |
| 447 */ | |
| 448 String replaceFirst(Pattern from, String to, [int startIndex = 0]); | |
| 449 | |
| 450 /** | |
| 451 * Replaces all substrings that match [from] with [replace]. | |
| 452 * | |
| 453 * Returns a new string in which the non-overlapping substrings matching | |
| 454 * [from] (the ones iterated by `from.allMatches(thisString)`) are replaced | |
| 455 * by the literal string [replace]. | |
| 456 * | |
| 457 * 'resume'.replaceAll(new RegExp(r'e'), 'é'); // 'résumé' | |
| 458 * | |
| 459 * Notice that the [replace] string is not interpreted. If the replacement | |
| 460 * depends on the match (for example on a [RegExp]'s capture groups), use | |
| 461 * the [replaceAllMapped] method instead. | |
| 462 */ | |
| 463 String replaceAll(Pattern from, String replace); | |
| 464 | |
| 465 /** | |
| 466 * Replace all substrings that match [from] by a string computed from the | |
| 467 * match. | |
| 468 * | |
| 469 * Returns a new string in which the non-overlapping substrings that match | |
| 470 * [from] (the ones iterated by `from.allMatches(thisString)`) are replaced | |
| 471 * by the result of calling [replace] on the corresponding [Match] object. | |
| 472 * | |
| 473 * This can be used to replace matches with new content that depends on the | |
| 474 * match, unlike [replaceAll] where the replacement string is always the same. | |
| 475 * | |
| 476 * The [replace] function is called with the [Match] generated | |
| 477 * by the pattern, and its result is used as replacement. | |
| 478 * | |
| 479 * The function defined below converts each word in a string to simplified | |
| 480 * 'pig latin' using [replaceAllMapped]: | |
| 481 * | |
| 482 * pigLatin(String words) => words.replaceAllMapped( | |
| 483 * new RegExp(r'\b(\w*?)([aeiou]\w*)', caseSensitive: false), | |
| 484 * (Match m) => "${m[2]}${m[1]}${m[1].isEmpty ? 'way' : 'ay'}"); | |
| 485 * | |
| 486 * pigLatin('I have a secret now!'); // 'Iway avehay away ecretsay ownay!' | |
| 487 */ | |
| 488 String replaceAllMapped(Pattern from, String replace(Match match)); | |
| 489 | |
| 490 /** | |
| 491 * Splits the string at matches of [pattern] and returns a list of substrings. | |
| 492 * | |
| 493 * Finds all the matches of `pattern` in this string, | |
| 494 * and returns the list of the substrings between the matches. | |
| 495 * | |
| 496 * var string = "Hello world!"; | |
| 497 * string.split(" "); // ['Hello', 'world!']; | |
| 498 * | |
| 499 * Empty matches at the beginning and end of the strings are ignored, | |
| 500 * and so are empty matches right after another match. | |
| 501 * | |
| 502 * var string = "abba"; | |
| 503 * string.split(new RegExp(r"b*")); // ['a', 'a'] | |
| 504 * // not ['', 'a', 'a', ''] | |
| 505 * | |
| 506 * If this string is empty, the result is an empty list if `pattern` matches | |
| 507 * the empty string, and it is `[""]` if the pattern doesn't match. | |
| 508 * | |
| 509 * var string = ''; | |
| 510 * string.split(''); // [] | |
| 511 * string.split("a"); // [''] | |
| 512 * | |
| 513 * Splitting with an empty pattern splits the string into single-code unit | |
| 514 * strings. | |
| 515 * | |
| 516 * var string = 'Pub'; | |
| 517 * string.split(''); // ['P', 'u', 'b'] | |
| 518 * | |
| 519 * string.codeUnits.map((unit) { | |
| 520 * return new String.fromCharCode(unit); | |
| 521 * }).toList(); // ['P', 'u', 'b'] | |
| 522 * | |
| 523 * Splitting happens at UTF-16 code unit boundaries, | |
| 524 * and not at rune boundaries: | |
| 525 * | |
| 526 * // String made up of two code units, but one rune. | |
| 527 * string = '\u{1D11E}'; | |
| 528 * string.split('').length; // 2 surrogate values | |
| 529 * | |
| 530 * To get a list of strings containing the individual runes of a string, | |
| 531 * you should not use split. You can instead map each rune to a string | |
| 532 * as follows: | |
| 533 * | |
| 534 * string.runes.map((rune) => new String.fromCharCode(rune)).toList(); | |
| 535 */ | |
| 536 List<String> split(Pattern pattern); | |
| 537 | |
| 538 /** | |
| 539 * Splits the string, converts its parts, and combines them into a new | |
| 540 * string. | |
| 541 * | |
| 542 * [pattern] is used to split the string into parts and separating matches. | |
| 543 * | |
| 544 * Each match is converted to a string by calling [onMatch]. If [onMatch] | |
| 545 * is omitted, the matched string is used. | |
| 546 * | |
| 547 * Each non-matched part is converted by a call to [onNonMatch]. If | |
| 548 * [onNonMatch] is omitted, the non-matching part is used. | |
| 549 * | |
| 550 * Then all the converted parts are combined into the resulting string. | |
| 551 * | |
| 552 * 'Eats shoots leaves'.splitMapJoin((new RegExp(r'shoots')), | |
| 553 * onMatch: (m) => '${m.group(0)}', | |
| 554 * onNonMatch: (n) => '*'); // *shoots* | |
| 555 */ | |
| 556 String splitMapJoin(Pattern pattern, | |
| 557 {String onMatch(Match match), | |
| 558 String onNonMatch(String nonMatch)}); | |
| 559 | |
| 560 /** | |
| 561 * Returns an unmodifiable list of the UTF-16 code units of this string. | |
| 562 */ | |
| 563 List<int> get codeUnits; | |
| 564 | |
| 565 /** | |
| 566 * Returns an [Iterable] of Unicode code-points of this string. | |
| 567 * | |
| 568 * If the string contains surrogate pairs, they are combined and returned | |
| 569 * as one integer by this iterator. Unmatched surrogate halves are treated | |
| 570 * like valid 16-bit code-units. | |
| 571 */ | |
| 572 Runes get runes; | |
| 573 | |
| 574 /** | |
| 575 * Converts all characters in this string to lower case. | |
| 576 * If the string is already in all lower case, this method returns [:this:]. | |
| 577 * | |
| 578 * 'ALPHABET'.toLowerCase(); // 'alphabet' | |
| 579 * 'abc'.toLowerCase(); // 'abc' | |
| 580 * | |
| 581 * This function uses the language independent Unicode mapping and thus only | |
| 582 * works in some languages. | |
| 583 */ | |
| 584 // TODO(floitsch): document better. (See EcmaScript for description). | |
| 585 String toLowerCase(); | |
| 586 | |
| 587 /** | |
| 588 * Converts all characters in this string to upper case. | |
| 589 * If the string is already in all upper case, this method returns [:this:]. | |
| 590 * | |
| 591 * 'alphabet'.toUpperCase(); // 'ALPHABET' | |
| 592 * 'ABC'.toUpperCase(); // 'ABC' | |
| 593 * | |
| 594 * This function uses the language independent Unicode mapping and thus only | |
| 595 * works in some languages. | |
| 596 */ | |
| 597 // TODO(floitsch): document better. (See EcmaScript for description). | |
| 598 String toUpperCase(); | |
| 599 | |
| 600 static String _stringFromIterable(Iterable<int> charCodes, | |
| 601 int start, int end) { | |
| 602 if (start < 0) throw new RangeError.range(start, 0, charCodes.length); | |
| 603 if (end != null && end < start) { | |
| 604 throw new RangeError.range(end, start, charCodes.length); | |
| 605 } | |
| 606 var it = charCodes.iterator; | |
| 607 for (int i = 0; i < start; i++) { | |
| 608 if (!it.moveNext()) { | |
| 609 throw new RangeError.range(start, 0, i); | |
| 610 } | |
| 611 } | |
| 612 var list = []; | |
| 613 if (end == null) { | |
| 614 while (it.moveNext()) list.add(it.current); | |
| 615 } else { | |
| 616 for (int i = start; i < end; i++) { | |
| 617 if (!it.moveNext()) { | |
| 618 throw new RangeError.range(end, start, i); | |
| 619 } | |
| 620 list.add(it.current); | |
| 621 } | |
| 622 } | |
| 623 return Primitives.stringFromCharCodes(list); | |
| 624 } | |
| 625 } | |
| 626 | |
| 627 /** | |
| 628 * The runes (integer Unicode code points) of a [String]. | |
| 629 */ | |
| 630 class Runes extends IterableBase<int> { | |
| 631 final String string; | |
| 632 Runes(this.string); | |
| 633 | |
| 634 RuneIterator get iterator => new RuneIterator(string); | |
| 635 | |
| 636 int get last { | |
| 637 if (string.length == 0) { | |
| 638 throw new StateError('No elements.'); | |
| 639 } | |
| 640 int length = string.length; | |
| 641 int code = string.codeUnitAt(length - 1); | |
| 642 if (_isTrailSurrogate(code) && string.length > 1) { | |
| 643 int previousCode = string.codeUnitAt(length - 2); | |
| 644 if (_isLeadSurrogate(previousCode)) { | |
| 645 return _combineSurrogatePair(previousCode, code); | |
| 646 } | |
| 647 } | |
| 648 return code; | |
| 649 } | |
| 650 | |
| 651 } | |
| 652 | |
| 653 // Is then code (a 16-bit unsigned integer) a UTF-16 lead surrogate. | |
| 654 bool _isLeadSurrogate(int code) => (code & 0xFC00) == 0xD800; | |
| 655 | |
| 656 // Is then code (a 16-bit unsigned integer) a UTF-16 trail surrogate. | |
| 657 bool _isTrailSurrogate(int code) => (code & 0xFC00) == 0xDC00; | |
| 658 | |
| 659 // Combine a lead and a trail surrogate value into a single code point. | |
| 660 int _combineSurrogatePair(int start, int end) { | |
| 661 return 0x10000 + ((start & 0x3FF) << 10) + (end & 0x3FF); | |
| 662 } | |
| 663 | |
| 664 /** [Iterator] for reading runes (integer Unicode code points) out of a Dart | |
| 665 * string. | |
| 666 */ | |
| 667 class RuneIterator implements BidirectionalIterator<int> { | |
| 668 /** String being iterated. */ | |
| 669 final String string; | |
| 670 /** Position before the current code point. */ | |
| 671 int _position; | |
| 672 /** Position after the current code point. */ | |
| 673 int _nextPosition; | |
| 674 /** | |
| 675 * Current code point. | |
| 676 * | |
| 677 * If the iterator has hit either end, the [_currentCodePoint] is null | |
| 678 * and [: _position == _nextPosition :]. | |
| 679 */ | |
| 680 num _currentCodePoint; | |
| 681 | |
| 682 /** Create an iterator positioned at the beginning of the string. */ | |
| 683 RuneIterator(String string) | |
| 684 : this.string = string, _position = 0, _nextPosition = 0; | |
| 685 | |
| 686 /** | |
| 687 * Create an iterator positioned before the [index]th code unit of the string. | |
| 688 * | |
| 689 * When created, there is no [current] value. | |
| 690 * A [moveNext] will use the rune starting at [index] the current value, | |
| 691 * and a [movePrevious] will use the rune ending just before [index] as the | |
| 692 * the current value. | |
| 693 * | |
| 694 * The [index] position must not be in the middle of a surrogate pair. | |
| 695 */ | |
| 696 RuneIterator.at(String string, int index) | |
| 697 : string = string, _position = index, _nextPosition = index { | |
| 698 RangeError.checkValueInInterval(index, 0, string.length); | |
| 699 _checkSplitSurrogate(index); | |
| 700 } | |
| 701 | |
| 702 /** Throw an error if the index is in the middle of a surrogate pair. */ | |
| 703 void _checkSplitSurrogate(int index) { | |
| 704 if (index > 0 && index < string.length && | |
| 705 _isLeadSurrogate(string.codeUnitAt(index - 1)) && | |
| 706 _isTrailSurrogate(string.codeUnitAt(index))) { | |
| 707 throw new ArgumentError('Index inside surrogate pair: $index'); | |
| 708 } | |
| 709 } | |
| 710 | |
| 711 /** | |
| 712 * Returns the starting position of the current rune in the string. | |
| 713 * | |
| 714 * Returns null if the [current] rune is null. | |
| 715 */ | |
| 716 int get rawIndex => (_position != _nextPosition) ? _position : null; | |
| 717 | |
| 718 /** | |
| 719 * Resets the iterator to the rune at the specified index of the string. | |
| 720 * | |
| 721 * Setting a negative [rawIndex], or one greater than or equal to | |
| 722 * [:string.length:], | |
| 723 * is an error. So is setting it in the middle of a surrogate pair. | |
| 724 * | |
| 725 * Setting the position to the end of then string will set [current] to null. | |
| 726 */ | |
| 727 void set rawIndex(int rawIndex) { | |
| 728 RangeError.checkValidIndex(rawIndex, string, "rawIndex"); | |
| 729 reset(rawIndex); | |
| 730 moveNext(); | |
| 731 } | |
| 732 | |
| 733 /** | |
| 734 * Resets the iterator to the given index into the string. | |
| 735 * | |
| 736 * After this the [current] value is unset. | |
| 737 * You must call [moveNext] make the rune at the position current, | |
| 738 * or [movePrevious] for the last rune before the position. | |
| 739 * | |
| 740 * Setting a negative [rawIndex], or one greater than [:string.length:], | |
| 741 * is an error. So is setting it in the middle of a surrogate pair. | |
| 742 */ | |
| 743 void reset([int rawIndex = 0]) { | |
| 744 RangeError.checkValueInInterval(rawIndex, 0, string.length, "rawIndex"); | |
| 745 _checkSplitSurrogate(rawIndex); | |
| 746 _position = _nextPosition = rawIndex; | |
| 747 _currentCodePoint = null; | |
| 748 } | |
| 749 | |
| 750 /** The rune (integer Unicode code point) starting at the current position in | |
| 751 * the string. | |
| 752 */ | |
| 753 int get current => _currentCodePoint; | |
| 754 | |
| 755 /** | |
| 756 * The number of code units comprising the current rune. | |
| 757 * | |
| 758 * Returns zero if there is no current rune ([current] is null). | |
| 759 */ | |
| 760 int get currentSize => _nextPosition - _position; | |
| 761 | |
| 762 /** | |
| 763 * A string containing the current rune. | |
| 764 * | |
| 765 * For runes outside the basic multilingual plane, this will be | |
| 766 * a String of length 2, containing two code units. | |
| 767 * | |
| 768 * Returns null if [current] is null. | |
| 769 */ | |
| 770 String get currentAsString { | |
| 771 if (_position == _nextPosition) return null; | |
| 772 if (_position + 1 == _nextPosition) return string[_position]; | |
| 773 return string.substring(_position, _nextPosition); | |
| 774 } | |
| 775 | |
| 776 bool moveNext() { | |
| 777 _position = _nextPosition; | |
| 778 if (_position == string.length) { | |
| 779 _currentCodePoint = null; | |
| 780 return false; | |
| 781 } | |
| 782 int codeUnit = string.codeUnitAt(_position); | |
| 783 int nextPosition = _position + 1; | |
| 784 if (_isLeadSurrogate(codeUnit) && nextPosition < string.length) { | |
| 785 int nextCodeUnit = string.codeUnitAt(nextPosition); | |
| 786 if (_isTrailSurrogate(nextCodeUnit)) { | |
| 787 _nextPosition = nextPosition + 1; | |
| 788 _currentCodePoint = _combineSurrogatePair(codeUnit, nextCodeUnit); | |
| 789 return true; | |
| 790 } | |
| 791 } | |
| 792 _nextPosition = nextPosition; | |
| 793 _currentCodePoint = codeUnit; | |
| 794 return true; | |
| 795 } | |
| 796 | |
| 797 bool movePrevious() { | |
| 798 _nextPosition = _position; | |
| 799 if (_position == 0) { | |
| 800 _currentCodePoint = null; | |
| 801 return false; | |
| 802 } | |
| 803 int position = _position - 1; | |
| 804 int codeUnit = string.codeUnitAt(position); | |
| 805 if (_isTrailSurrogate(codeUnit) && position > 0) { | |
| 806 int prevCodeUnit = string.codeUnitAt(position - 1); | |
| 807 if (_isLeadSurrogate(prevCodeUnit)) { | |
| 808 _position = position - 1; | |
| 809 _currentCodePoint = _combineSurrogatePair(prevCodeUnit, codeUnit); | |
| 810 return true; | |
| 811 } | |
| 812 } | |
| 813 _position = position; | |
| 814 _currentCodePoint = codeUnit; | |
| 815 return true; | |
| 816 } | |
| 817 } | |
| OLD | NEW |