| 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 137 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 148     } | 148     } | 
| 149     if ((endIndex < 0) || (endIndex > this.length)) { | 149     if ((endIndex < 0) || (endIndex > this.length)) { | 
| 150       throw new RangeError.value(endIndex); | 150       throw new RangeError.value(endIndex); | 
| 151     } | 151     } | 
| 152     if (startIndex > endIndex) { | 152     if (startIndex > endIndex) { | 
| 153       throw new RangeError.value(startIndex); | 153       throw new RangeError.value(startIndex); | 
| 154     } | 154     } | 
| 155     return _substringUnchecked(startIndex, endIndex); | 155     return _substringUnchecked(startIndex, endIndex); | 
| 156   } | 156   } | 
| 157 | 157 | 
|  | 158   String slice([int startIndex, int endIndex]) { | 
|  | 159     int start, end; | 
|  | 160     if (startIndex == null) { | 
|  | 161       start = 0; | 
|  | 162     } else if (startIndex is! int) { | 
|  | 163       throw new ArgumentError("startIndex is not int"); | 
|  | 164     } else if (startIndex >= 0) { | 
|  | 165       start = startIndex; | 
|  | 166     } else { | 
|  | 167       start = this.length + startIndex; | 
|  | 168     } | 
|  | 169     if (start < 0 || start > this.length) { | 
|  | 170       throw new RangeError( | 
|  | 171           "startIndex out of range: $startIndex (length: $length)"); | 
|  | 172     } | 
|  | 173     if (endIndex == null) { | 
|  | 174       end = this.length; | 
|  | 175     } else if (endIndex is! int) { | 
|  | 176       throw new ArgumentError("endIndex is not int"); | 
|  | 177     } else if (endIndex >= 0) { | 
|  | 178       end = endIndex; | 
|  | 179     } else { | 
|  | 180       end = this.length + endIndex; | 
|  | 181     } | 
|  | 182     if (end < 0 || end > this.length) { | 
|  | 183       throw new RangeError( | 
|  | 184           "endIndex out of range: $endIndex (length: $length)"); | 
|  | 185     } | 
|  | 186     if (end < start) { | 
|  | 187       throw new ArgumentError( | 
|  | 188           "End before start: $endIndex < $startIndex (length: $length)"); | 
|  | 189     } | 
|  | 190     return _substringUnchecked(start, end); | 
|  | 191   } | 
|  | 192 | 
| 158   String _substringUnchecked(int startIndex, int endIndex) { | 193   String _substringUnchecked(int startIndex, int endIndex) { | 
| 159     assert(endIndex != null); | 194     assert(endIndex != null); | 
| 160     assert((startIndex >= 0) && (startIndex <= this.length)); | 195     assert((startIndex >= 0) && (startIndex <= this.length)); | 
| 161     assert((endIndex >= 0) && (endIndex <= this.length)); | 196     assert((endIndex >= 0) && (endIndex <= this.length)); | 
| 162     assert(startIndex <= endIndex); | 197     assert(startIndex <= endIndex); | 
| 163 | 198 | 
| 164     if (startIndex == endIndex) { | 199     if (startIndex == endIndex) { | 
| 165       return ""; | 200       return ""; | 
| 166     } | 201     } | 
| 167     if ((startIndex + 1) == endIndex) { | 202     if ((startIndex + 1) == endIndex) { | 
| (...skipping 29 matching lines...) Expand all  Loading... | 
| 197       return this; | 232       return this; | 
| 198     } else { | 233     } else { | 
| 199       return _substringUnchecked(first, last + 1); | 234       return _substringUnchecked(first, last + 1); | 
| 200     } | 235     } | 
| 201   } | 236   } | 
| 202 | 237 | 
| 203   bool contains(Pattern pattern, [int startIndex = 0]) { | 238   bool contains(Pattern pattern, [int startIndex = 0]) { | 
| 204     if (pattern is String) { | 239     if (pattern is String) { | 
| 205       return indexOf(pattern, startIndex) >= 0; | 240       return indexOf(pattern, startIndex) >= 0; | 
| 206     } | 241     } | 
| 207     return pattern.allMatches(this.substring(startIndex)).iterator().hasNext; | 242     return pattern.allMatches(this.substring(startIndex)).iterator.moveNext(); | 
| 208   } | 243   } | 
| 209 | 244 | 
| 210   String replaceFirst(Pattern pattern, String replacement) { | 245   String replaceFirst(Pattern pattern, String replacement) { | 
| 211     if (pattern is! Pattern) { | 246     if (pattern is! Pattern) { | 
| 212       throw new ArgumentError("${pattern} is not a Pattern"); | 247       throw new ArgumentError("${pattern} is not a Pattern"); | 
| 213     } | 248     } | 
| 214     if (replacement is! String) { | 249     if (replacement is! String) { | 
| 215       throw new ArgumentError("${replacement} is not a String"); | 250       throw new ArgumentError("${replacement} is not a String"); | 
| 216     } | 251     } | 
| 217     StringBuffer buffer = new StringBuffer(); | 252     StringBuffer buffer = new StringBuffer(); | 
| 218     int startIndex = 0; | 253     int startIndex = 0; | 
| 219     Iterator iterator = pattern.allMatches(this).iterator(); | 254     Iterator iterator = pattern.allMatches(this).iterator; | 
| 220     if (iterator.hasNext) { | 255     if (iterator.moveNext()) { | 
| 221       Match match = iterator.next(); | 256       Match match = iterator.current; | 
| 222       buffer..add(this.substring(startIndex, match.start)) | 257       buffer..add(this.substring(startIndex, match.start)) | 
| 223             ..add(replacement); | 258             ..add(replacement); | 
| 224       startIndex = match.end; | 259       startIndex = match.end; | 
| 225     } | 260     } | 
| 226     return (buffer..add(this.substring(startIndex))).toString(); | 261     return (buffer..add(this.substring(startIndex))).toString(); | 
| 227   } | 262   } | 
| 228 | 263 | 
| 229   String replaceAll(Pattern pattern, String replacement) { | 264   String replaceAll(Pattern pattern, String replacement) { | 
| 230     if (pattern is! Pattern) { | 265     if (pattern is! Pattern) { | 
| 231       throw new ArgumentError("${pattern} is not a Pattern"); | 266       throw new ArgumentError("${pattern} is not a Pattern"); | 
| 232     } | 267     } | 
| 233     if (replacement is! String) { | 268     if (replacement is! String) { | 
| 234       throw new ArgumentError("${replacement} is not a String"); | 269       throw new ArgumentError( | 
|  | 270           "${replacement} is not a String or Match->String function"); | 
| 235     } | 271     } | 
| 236     StringBuffer buffer = new StringBuffer(); | 272     StringBuffer buffer = new StringBuffer(); | 
| 237     int startIndex = 0; | 273     int startIndex = 0; | 
| 238     for (Match match in pattern.allMatches(this)) { | 274     for (Match match in pattern.allMatches(this)) { | 
| 239       buffer..add(this.substring(startIndex, match.start)) | 275       buffer..add(this.substring(startIndex, match.start)) | 
| 240             ..add(replacement); | 276             ..add(replacement); | 
| 241       startIndex = match.end; | 277       startIndex = match.end; | 
| 242     } | 278     } | 
| 243     return (buffer..add(this.substring(startIndex))).toString(); | 279     return (buffer..add(this.substring(startIndex))).toString(); | 
| 244   } | 280   } | 
| 245 | 281 | 
|  | 282   String replaceAllMapped(Pattern pattern, String replace(Match match)) { | 
|  | 283     return splitMapJoin(pattern, onMatch: replace); | 
|  | 284   } | 
|  | 285 | 
|  | 286   static String _matchString(Match match) => match[0]; | 
|  | 287   static String _stringIdentity(String string) => string; | 
|  | 288 | 
|  | 289   String _splitMapJoinEmptyString(String onMatch(Match match), | 
|  | 290                                   String onNonMatch(String nonMatch)) { | 
|  | 291     // Pattern is the empty string. | 
|  | 292     StringBuffer buffer = new StringBuffer(); | 
|  | 293     int length = this.length; | 
|  | 294     int i = 0; | 
|  | 295     buffer.add(onNonMatch("")); | 
|  | 296     while (i < length) { | 
|  | 297       buffer.add(onMatch(new _StringMatch(i, this, ""))); | 
|  | 298       // Special case to avoid splitting a surrogate pair. | 
|  | 299       int code = this.charCodeAt(i); | 
|  | 300       if ((code & ~0x3FF) == 0xD800 && length > i + 1) { | 
|  | 301         // Leading surrogate; | 
|  | 302         code = this.charCodeAt(i + 1); | 
|  | 303         if ((code & ~0x3FF) == 0xDC00) { | 
|  | 304           // Matching trailing surrogate. | 
|  | 305           buffer.add(onNonMatch(this.substring(i, i + 2))); | 
|  | 306           i += 2; | 
|  | 307           continue; | 
|  | 308         } | 
|  | 309       } | 
|  | 310       buffer.add(onNonMatch(this[i])); | 
|  | 311       i++; | 
|  | 312     } | 
|  | 313     buffer.add(onMatch(new _StringMatch(i, this, ""))); | 
|  | 314     buffer.add(onNonMatch("")); | 
|  | 315     return buffer.toString(); | 
|  | 316   } | 
|  | 317 | 
|  | 318   String splitMapJoin(Pattern pattern, | 
|  | 319                       {String onMatch(Match match), | 
|  | 320                        String onNonMatch(String nonMatch)}) { | 
|  | 321     if (pattern is! Pattern) { | 
|  | 322       throw new ArgumentError("${pattern} is not a Pattern"); | 
|  | 323     } | 
|  | 324     if (onMatch == null) onMatch = _matchString; | 
|  | 325     if (onNonMatch == null) onNonMatch = _stringIdentity; | 
|  | 326     if (pattern is String) { | 
|  | 327       String stringPattern = pattern; | 
|  | 328       if (stringPattern.isEmpty) { | 
|  | 329         return _splitMapJoinEmptyString(onMatch, onNonMatch); | 
|  | 330       } | 
|  | 331     } | 
|  | 332     StringBuffer buffer = new StringBuffer(); | 
|  | 333     int startIndex = 0; | 
|  | 334     for (Match match in pattern.allMatches(this)) { | 
|  | 335       buffer.add(onNonMatch(this.substring(startIndex, match.start))); | 
|  | 336       buffer.add(onMatch(match).toString()); | 
|  | 337       startIndex = match.end; | 
|  | 338     } | 
|  | 339     buffer.add(onNonMatch(this.substring(startIndex))); | 
|  | 340     return buffer.toString(); | 
|  | 341   } | 
|  | 342 | 
|  | 343 | 
| 246   /** | 344   /** | 
| 247    * Convert all objects in [values] to strings and concat them | 345    * Convert all objects in [values] to strings and concat them | 
| 248    * into a result string. | 346    * into a result string. | 
| 249    */ | 347    */ | 
| 250   static String _interpolate(List values) { | 348   static String _interpolate(List values) { | 
| 251     int numValues = values.length; | 349     int numValues = values.length; | 
| 252     var stringList = new List(numValues); | 350     var stringList = new List.fixedLength(numValues); | 
| 253     for (int i = 0; i < numValues; i++) { | 351     for (int i = 0; i < numValues; i++) { | 
| 254       stringList[i] = values[i].toString(); | 352       stringList[i] = values[i].toString(); | 
| 255     } | 353     } | 
| 256     return _concatAll(stringList); | 354     return _concatAll(stringList); | 
| 257   } | 355   } | 
| 258 | 356 | 
| 259   Iterable<Match> allMatches(String str) { | 357   Iterable<Match> allMatches(String str) { | 
| 260     List<Match> result = new List<Match>(); | 358     List<Match> result = new List<Match>(); | 
| 261     int length = str.length; | 359     int length = str.length; | 
| 262     int patternLength = this.length; | 360     int patternLength = this.length; | 
| (...skipping 14 matching lines...) Expand all  Loading... | 
| 277       } | 375       } | 
| 278     } | 376     } | 
| 279     return result; | 377     return result; | 
| 280   } | 378   } | 
| 281 | 379 | 
| 282   List<String> split(Pattern pattern) { | 380   List<String> split(Pattern pattern) { | 
| 283     if ((pattern is String) && pattern.isEmpty) { | 381     if ((pattern is String) && pattern.isEmpty) { | 
| 284       return splitChars(); | 382       return splitChars(); | 
| 285     } | 383     } | 
| 286     int length = this.length; | 384     int length = this.length; | 
| 287     Iterator iterator = pattern.allMatches(this).iterator(); | 385     Iterator iterator = pattern.allMatches(this).iterator; | 
| 288     if (length == 0 && iterator.hasNext) { | 386     if (length == 0 && iterator.moveNext()) { | 
| 289       // A matched empty string input returns the empty list. | 387       // A matched empty string input returns the empty list. | 
| 290       return <String>[]; | 388       return <String>[]; | 
| 291     } | 389     } | 
| 292     List<String> result = new List<String>(); | 390     List<String> result = new List<String>(); | 
| 293     int startIndex = 0; | 391     int startIndex = 0; | 
| 294     int previousIndex = 0; | 392     int previousIndex = 0; | 
| 295     while (true) { | 393     while (true) { | 
| 296       if (startIndex == length || !iterator.hasNext) { | 394       if (startIndex == length || !iterator.moveNext()) { | 
| 297         result.add(this._substringUnchecked(previousIndex, length)); | 395         result.add(this._substringUnchecked(previousIndex, length)); | 
| 298         break; | 396         break; | 
| 299       } | 397       } | 
| 300       Match match = iterator.next(); | 398       Match match = iterator.current; | 
| 301       if (match.start == length) { | 399       if (match.start == length) { | 
| 302         result.add(this._substringUnchecked(previousIndex, length)); | 400         result.add(this._substringUnchecked(previousIndex, length)); | 
| 303         break; | 401         break; | 
| 304       } | 402       } | 
| 305       int endIndex = match.end; | 403       int endIndex = match.end; | 
| 306       if (startIndex == endIndex && endIndex == previousIndex) { | 404       if (startIndex == endIndex && endIndex == previousIndex) { | 
| 307         ++startIndex;  // empty match, advance and restart | 405         ++startIndex;  // empty match, advance and restart | 
| 308         continue; | 406         continue; | 
| 309       } | 407       } | 
| 310       result.add(this._substringUnchecked(previousIndex, match.start)); | 408       result.add(this._substringUnchecked(previousIndex, match.start)); | 
| 311       startIndex = previousIndex = endIndex; | 409       startIndex = previousIndex = endIndex; | 
| 312     } | 410     } | 
| 313     return result; | 411     return result; | 
| 314   } | 412   } | 
| 315 | 413 | 
| 316   List<String> splitChars() { | 414   List<String> splitChars() { | 
| 317     int len = this.length; | 415     int len = this.length; | 
| 318     final result = new List<String>(len); | 416     final result = new List<String>.fixedLength(len); | 
| 319     for (int i = 0; i < len; i++) { | 417     for (int i = 0; i < len; i++) { | 
| 320       result[i] = this[i]; | 418       result[i] = this[i]; | 
| 321     } | 419     } | 
| 322     return result; | 420     return result; | 
| 323   } | 421   } | 
| 324 | 422 | 
| 325   List<int> get charCodes { | 423   List<int> get charCodes { | 
| 326     int len = this.length; | 424     int len = this.length; | 
| 327     final result = new List<int>(len); | 425     final result = new List<int>.fixedLength(len); | 
| 328     for (int i = 0; i < len; i++) { | 426     for (int i = 0; i < len; i++) { | 
| 329       result[i] = this.charCodeAt(i); | 427       result[i] = this.charCodeAt(i); | 
| 330     } | 428     } | 
| 331     return result; | 429     return result; | 
| 332   } | 430   } | 
| 333 | 431 | 
| 334   String toUpperCase() native "String_toUpperCase"; | 432   String toUpperCase() native "String_toUpperCase"; | 
| 335 | 433 | 
| 336   String toLowerCase() native "String_toLowerCase"; | 434   String toLowerCase() native "String_toLowerCase"; | 
| 337 | 435 | 
| 338   // Implementations of Strings methods follow below. | 436   // Implementations of Strings methods follow below. | 
| 339   static String join(List<String> strings, String separator) { | 437   static String join(Iterable<String> strings, String separator) { | 
| 340     final int length = strings.length; | 438     bool first = true; | 
| 341     if (length == 0) { | 439     List<String> stringsList = <String>[]; | 
| 342       return ""; | 440     for (String string in strings) { | 
| 343     } | 441       if (first) { | 
|  | 442         first = false; | 
|  | 443       } else { | 
|  | 444         stringsList.add(separator); | 
|  | 445       } | 
| 344 | 446 | 
| 345     List stringsList = strings; | 447       if (string is! String) { | 
| 346     if (separator.length != 0) { | 448         throw new ArgumentError(Error.safeToString(string)); | 
| 347       stringsList = new List(2 * length - 1); |  | 
| 348       stringsList[0] = strings[0]; |  | 
| 349       int j = 1; |  | 
| 350       for (int i = 1; i < length; i++) { |  | 
| 351         stringsList[j++] = separator; |  | 
| 352         stringsList[j++] = strings[i]; |  | 
| 353       } | 449       } | 
|  | 450       stringsList.add(string); | 
| 354     } | 451     } | 
| 355     return concatAll(stringsList); | 452     return concatAll(stringsList); | 
| 356   } | 453   } | 
| 357 | 454 | 
| 358   static String concatAll(List<String> strings) { | 455   static String concatAll(Iterable<String> strings) { | 
| 359     _ObjectArray stringsArray; | 456     _ObjectArray stringsArray; | 
| 360     if (strings is _ObjectArray) { | 457     if (strings is _ObjectArray) { | 
| 361       stringsArray = strings; | 458       stringsArray = strings; | 
|  | 459       for (int i = 0; i < strings.length; i++) { | 
|  | 460         if (strings[i] is! String) throw new ArgumentError(strings[i]); | 
|  | 461       } | 
| 362     } else { | 462     } else { | 
| 363       int len = strings.length; | 463       int len = strings.length; | 
| 364       stringsArray = new _ObjectArray(len); | 464       stringsArray = new _ObjectArray(len); | 
| 365       for (int i = 0; i < len; i++) { | 465       int i = 0; | 
| 366         stringsArray[i] = strings[i]; | 466       for (String string in strings) { | 
|  | 467         if (string is! String) throw new ArgumentError(string); | 
|  | 468         stringsArray[i++] = string; | 
| 367       } | 469       } | 
| 368     } | 470     } | 
| 369     return _concatAll(stringsArray); | 471     return _concatAll(stringsArray); | 
| 370   } | 472   } | 
| 371 | 473 | 
| 372   static String _concatAll(List<String> strings) | 474   static String _concatAll(List<String> strings) | 
| 373       native "Strings_concatAll"; | 475       native "Strings_concatAll"; | 
| 374 } | 476 } | 
| 375 | 477 | 
| 376 | 478 | 
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 510     for (int g in groups) { | 612     for (int g in groups) { | 
| 511       result.add(group(g)); | 613       result.add(group(g)); | 
| 512     } | 614     } | 
| 513     return result; | 615     return result; | 
| 514   } | 616   } | 
| 515 | 617 | 
| 516   final int start; | 618   final int start; | 
| 517   final String str; | 619   final String str; | 
| 518   final String pattern; | 620   final String pattern; | 
| 519 } | 621 } | 
| OLD | NEW | 
|---|