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

Side by Side Diff: sdk/lib/collection/iterable.dart

Issue 297053002: Reinstall previous behavior for Set and Queue toString. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comments. Created 6 years, 6 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 | « sdk/lib/collection/hash_set.dart ('k') | sdk/lib/collection/list.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 part of dart.collection; 5 part of dart.collection;
6 6
7 /** 7 /**
8 * This [Iterable] mixin implements all [Iterable] members except `iterator`. 8 * This [Iterable] mixin implements all [Iterable] members except `iterator`.
9 * 9 *
10 * All other methods are implemented in terms of `iterator`. 10 * All other methods are implemented in terms of `iterator`.
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
188 E elementAt(int index) { 188 E elementAt(int index) {
189 if (index is! int || index < 0) throw new RangeError.value(index); 189 if (index is! int || index < 0) throw new RangeError.value(index);
190 int remaining = index; 190 int remaining = index;
191 for (E element in this) { 191 for (E element in this) {
192 if (remaining == 0) return element; 192 if (remaining == 0) return element;
193 remaining--; 193 remaining--;
194 } 194 }
195 throw new RangeError.value(index); 195 throw new RangeError.value(index);
196 } 196 }
197 197
198 String toString() => _iterableToString(this); 198 String toString() => IterableBase.iterableToShortString(this, '(', ')');
199 } 199 }
200 200
201 /** 201 /**
202 * Base class for implementing [Iterable]. 202 * Base class for implementing [Iterable].
203 * 203 *
204 * This class implements all methods of [Iterable] except [Iterable.iterator] 204 * This class implements all methods of [Iterable] except [Iterable.iterator]
205 * in terms of `iterator`. 205 * in terms of `iterator`.
206 */ 206 */
207 abstract class IterableBase<E> implements Iterable<E> { 207 abstract class IterableBase<E> implements Iterable<E> {
208 // TODO(lrn): Base this on IterableMixin if there ever becomes a way 208 // TODO(lrn): Base this on IterableMixin if there ever becomes a way
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
395 * Elements are represented by their own `toString` results. 395 * Elements are represented by their own `toString` results.
396 * 396 *
397 * The representation always contains the first three elements. 397 * The representation always contains the first three elements.
398 * If there are less than a hundred elements in the iterable, it also 398 * If there are less than a hundred elements in the iterable, it also
399 * contains the last two elements. 399 * contains the last two elements.
400 * 400 *
401 * If the resulting string isn't above 80 characters, more elements are 401 * If the resulting string isn't above 80 characters, more elements are
402 * included from the start of the iterable. 402 * included from the start of the iterable.
403 * 403 *
404 * The conversion may omit calling `toString` on some elements if they 404 * The conversion may omit calling `toString` on some elements if they
405 * are known to now occur in the output, and it may stop iterating after 405 * are known to not occur in the output, and it may stop iterating after
406 * a hundred elements. 406 * a hundred elements.
407 */ 407 */
408 String toString() => _iterableToString(this); 408 String toString() => iterableToShortString(this, '(', ')');
409 }
410 409
411 String _setToString(Set set) => _collectionToString(set, "{" , "}"); 410 /**
412 411 * Convert an `Iterable` to a string like [IterableBase.toString].
413 String _iterableToString(Iterable iterable) => 412 *
414 _collectionToString(iterable, "(", ")"); 413 * Allows using other delimiters than '(' and ')'.
415 414 *
416 String _collectionToString(Iterable iterable, String before, String after) { 415 * Handles circular references where converting one of the elements
417 if (_toStringVisiting.contains(iterable)) return "$before...$after"; 416 * to a string ends up converting [iterable] to a string again.
418 _toStringVisiting.add(iterable); 417 */
419 List parts = []; 418 static String iterableToShortString(Iterable iterable,
420 try { 419 [String leftDelimiter = '(',
421 _collectionPartsToStrings(iterable, parts); 420 String rightDelimiter = ')']) {
422 } finally { 421 if (_toStringVisiting.contains(iterable)) {
423 _toStringVisiting.remove(iterable); 422 if (leftDelimiter == "(" && rightDelimiter == ")") {
424 } 423 // Avoid creating a new string in the "common" case.
425 return (new StringBuffer(before) 424 return "(...)";
426 ..writeAll(parts, ", ") 425 }
427 ..write(after)).toString(); 426 return "$leftDelimiter...$rightDelimiter";
428 }
429
430 /** Convert elments of [iterable] to strings and store them in [parts]. */
431 void _collectionPartsToStrings(Iterable iterable, List parts) {
432 /// Try to stay below this many characters.
433 const int LENGTH_LIMIT = 80;
434 /// Always at least this many elements at the start.
435 const int HEAD_COUNT = 3;
436 /// Always at least this many elements at the end.
437 const int TAIL_COUNT = 2;
438 /// Stop iterating after this many elements. Iterables can be infinite.
439 const int MAX_COUNT = 100;
440 // Per entry length overhead. It's for ", " for all after the first entry,
441 // and for "(" and ")" for the initial entry. By pure luck, that's the same
442 // number.
443 const int OVERHEAD = 2;
444 const int ELLIPSIS_SIZE = 3; // "...".length.
445 int length = 0;
446 int count = 0;
447 Iterator it = iterable.iterator;
448 // Initial run of elements, at least HEAD_COUNT, and then continue until
449 // passing at most LENGTH_LIMIT characters.
450 while (length < LENGTH_LIMIT || count < HEAD_COUNT) {
451 if (!it.moveNext()) {
452 return;
453 } 427 }
454 String next = "${it.current}"; 428 List parts = [];
455 parts.add(next); 429 _toStringVisiting.add(iterable);
456 length += next.length + OVERHEAD; 430 try {
457 count++; 431 _iterablePartsToStrings(iterable, parts);
432 } finally {
433 _toStringVisiting.remove(iterable);
434 }
435 return (new StringBuffer(leftDelimiter)
436 ..writeAll(parts, ", ")
437 ..write(rightDelimiter)).toString();
458 } 438 }
459 439
460 String penultimateString; 440 /**
461 String ultimateString; 441 * Converts an `Iterable` to a string.
442 *
443 * Converts each elements to a string, and separates the results by ", ".
444 * Then wraps the result in [leftDelimiter] and [rightDelimiter].
445 *
446 * Unlike [iterableToShortString], this conversion doesn't omit any
447 * elements or puts any limit on the size of the result.
448 *
449 * Handles circular references where converting one of the elements
450 * to a string ends up converting [iterable] to a string again.
451 */
452 static String iterableToFullString(Iterable iterable,
453 [String leftDelimiter = '(',
454 String rightDelimiter = ')']) {
455 if (_toStringVisiting.contains(iterable)) {
456 return "$leftDelimiter...$rightDelimiter";
457 }
458 StringBuffer buffer = new StringBuffer(leftDelimiter);
459 _toStringVisiting.add(iterable);
460 try {
461 buffer.writeAll(iterable, ", ");
462 } finally {
463 _toStringVisiting.remove(iterable);
464 }
465 buffer.write(rightDelimiter);
466 return buffer.toString();
467 }
462 468
463 // Find last two elements. One or more of them may already be in the 469 /** A set used to identify cyclic lists during toString() calls. */
464 // parts array. Include their length in `length`. 470 static Set _toStringVisiting = new HashSet.identity();
465 var penultimate = null; 471
466 var ultimate = null; 472 /**
467 if (!it.moveNext()) { 473 * Convert elments of [iterable] to strings and store them in [parts].
468 if (count <= HEAD_COUNT + TAIL_COUNT) return; 474 */
469 ultimateString = parts.removeLast(); 475 static void _iterablePartsToStrings(Iterable iterable, List parts) {
470 penultimateString = parts.removeLast(); 476 /*
471 } else { 477 * This is the complicated part of [iterableToShortString].
472 penultimate = it.current; 478 * It is extracted as a separate function to avoid having too much code
473 count++; 479 * inside the try/finally.
480 */
481 /// Try to stay below this many characters.
482 const int LENGTH_LIMIT = 80;
483 /// Always at least this many elements at the start.
484 const int HEAD_COUNT = 3;
485 /// Always at least this many elements at the end.
486 const int TAIL_COUNT = 2;
487 /// Stop iterating after this many elements. Iterables can be infinite.
488 const int MAX_COUNT = 100;
489 // Per entry length overhead. It's for ", " for all after the first entry,
490 // and for "(" and ")" for the initial entry. By pure luck, that's the same
491 // number.
492 const int OVERHEAD = 2;
493 const int ELLIPSIS_SIZE = 3; // "...".length.
494
495 int length = 0;
496 int count = 0;
497 Iterator it = iterable.iterator;
498 // Initial run of elements, at least HEAD_COUNT, and then continue until
499 // passing at most LENGTH_LIMIT characters.
500 while (length < LENGTH_LIMIT || count < HEAD_COUNT) {
501 if (!it.moveNext()) return;
502 String next = "${it.current}";
503 parts.add(next);
504 length += next.length + OVERHEAD;
505 count++;
506 }
507
508 String penultimateString;
509 String ultimateString;
510
511 // Find last two elements. One or more of them may already be in the
512 // parts array. Include their length in `length`.
513 var penultimate = null;
514 var ultimate = null;
474 if (!it.moveNext()) { 515 if (!it.moveNext()) {
475 if (count <= HEAD_COUNT + 1) { 516 if (count <= HEAD_COUNT + TAIL_COUNT) return;
476 parts.add("$penultimate"); 517 ultimateString = parts.removeLast();
477 return;
478 }
479 ultimateString = "$penultimate";
480 penultimateString = parts.removeLast(); 518 penultimateString = parts.removeLast();
481 length += ultimateString.length + OVERHEAD;
482 } else { 519 } else {
483 ultimate = it.current; 520 penultimate = it.current;
484 count++; 521 count++;
485 // Then keep looping, keeping the last two elements in variables. 522 if (!it.moveNext()) {
486 assert(count < MAX_COUNT); 523 if (count <= HEAD_COUNT + 1) {
487 while (it.moveNext()) { 524 parts.add("$penultimate");
488 penultimate = ultimate; 525 return;
526 }
527 ultimateString = "$penultimate";
528 penultimateString = parts.removeLast();
529 length += ultimateString.length + OVERHEAD;
530 } else {
489 ultimate = it.current; 531 ultimate = it.current;
490 count++; 532 count++;
491 if (count > MAX_COUNT) { 533 // Then keep looping, keeping the last two elements in variables.
492 // If we haven't found the end before MAX_COUNT, give up. 534 assert(count < MAX_COUNT);
493 // This cannot happen in the code above because each entry 535 while (it.moveNext()) {
494 // increases length by at least two, so there is no way to 536 penultimate = ultimate;
495 // visit more than ~40 elements before this loop. 537 ultimate = it.current;
538 count++;
539 if (count > MAX_COUNT) {
540 // If we haven't found the end before MAX_COUNT, give up.
541 // This cannot happen in the code above because each entry
542 // increases length by at least two, so there is no way to
543 // visit more than ~40 elements before this loop.
496 544
497 // Remove any surplus elements until length, including ", ...)", 545 // Remove any surplus elements until length, including ", ...)",
498 // is at most LENGTH_LIMIT. 546 // is at most LENGTH_LIMIT.
499 while (length > LENGTH_LIMIT - ELLIPSIS_SIZE - OVERHEAD && 547 while (length > LENGTH_LIMIT - ELLIPSIS_SIZE - OVERHEAD &&
500 count > HEAD_COUNT) { 548 count > HEAD_COUNT) {
501 length -= parts.removeLast().length + OVERHEAD; 549 length -= parts.removeLast().length + OVERHEAD;
502 count--; 550 count--;
551 }
552 parts.add("...");
553 return;
503 } 554 }
504 parts.add("...");
505 return;
506 } 555 }
556 penultimateString = "$penultimate";
557 ultimateString = "$ultimate";
558 length +=
559 ultimateString.length + penultimateString.length + 2 * OVERHEAD;
507 } 560 }
508 penultimateString = "$penultimate";
509 ultimateString = "$ultimate";
510 length +=
511 ultimateString.length + penultimateString.length + 2 * OVERHEAD;
512 } 561 }
513 }
514 562
515 // If there is a gap between the initial run and the last two, 563 // If there is a gap between the initial run and the last two,
516 // prepare to add an ellipsis. 564 // prepare to add an ellipsis.
517 String elision = null; 565 String elision = null;
518 if (count > parts.length + TAIL_COUNT) { 566 if (count > parts.length + TAIL_COUNT) {
519 elision = "...";
520 length += ELLIPSIS_SIZE + OVERHEAD;
521 }
522
523 // If the last two elements were very long, and we have more than
524 // HEAD_COUNT elements in the initial run, drop some to make room for
525 // the last two.
526 while (length > LENGTH_LIMIT && parts.length > HEAD_COUNT) {
527 String lastPart = parts.removeLast();
528 length -= lastPart.length + OVERHEAD;
529 if (elision == null) {
530 elision = "..."; 567 elision = "...";
531 length += ELLIPSIS_SIZE + OVERHEAD; 568 length += ELLIPSIS_SIZE + OVERHEAD;
532 } 569 }
570
571 // If the last two elements were very long, and we have more than
572 // HEAD_COUNT elements in the initial run, drop some to make room for
573 // the last two.
574 while (length > LENGTH_LIMIT && parts.length > HEAD_COUNT) {
575 length -= parts.removeLast().length + OVERHEAD;
576 if (elision == null) {
577 elision = "...";
578 length += ELLIPSIS_SIZE + OVERHEAD;
579 }
580 }
581 if (elision != null) {
582 parts.add(elision);
583 }
584 parts.add(penultimateString);
585 parts.add(ultimateString);
533 } 586 }
534 if (elision != null) {
535 parts.add(elision);
536 }
537 parts.add(penultimateString);
538 parts.add(ultimateString);
539 } 587 }
OLDNEW
« no previous file with comments | « sdk/lib/collection/hash_set.dart ('k') | sdk/lib/collection/list.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698