Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(288)

Side by Side Diff: runtime/lib/string_base.dart

Issue 11783009: Big merge from experimental to bleeding edge. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/lib/regexp_patch.dart ('k') | runtime/lib/string_patch.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « runtime/lib/regexp_patch.dart ('k') | runtime/lib/string_patch.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698