Chromium Code Reviews| Index: runtime/lib/collections.dart |
| =================================================================== |
| --- runtime/lib/collections.dart (revision 4243) |
| +++ runtime/lib/collections.dart (working copy) |
| @@ -1,4 +1,4 @@ |
| -// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| @@ -49,4 +49,102 @@ |
| static bool isEmpty(Iterable<Object> iterable) { |
| return !iterable.iterator().hasNext(); |
| } |
| + |
| + // todo(jjb): visiting list should be an identityHashSet when it exists |
|
Ivan Posva
2012/02/15 09:54:10
All caps TODO.
|
| + |
| + /** |
| + * Returns a string representing the specified collection. If the |
| + * collection is a [List], the returned string looks like this: |
| + * [:"[element0, element1, ... elementN]":]. The value returned by its |
| + * [toString] method is used to represent each element. If the specified |
| + * collection is not a list, the returned string looks like this: |
| + * [:{element0, element1, ... elementN}:]. In other words, the strings |
| + * returned for lists are surrounded by square brackets, while the strings |
| + * returned for other collections are surrounded by curly braces. |
| + * |
| + * If the specified collection contains a reference to itself, either |
| + * directly or indirectly through other collections or maps, the contained |
| + * reference is rendered as [:"[...]":] if it is a list, or [:"{...}":] if |
| + * it is not. This prevents the infinite regress that would otherwise occur. |
| + * So, for example, calling this method on a list whose sole element is a |
| + * reference to itself would return [:"[[...]]":]. |
| + * |
| + * A typical implementation of a collection's [toString] method will |
| + * simply return the results of this method applied to the collection. |
| + */ |
| + static String collectionToString(Collection c) { |
| + var result = new StringBuffer(); |
| + _emitCollection(c, result, new List()); |
| + return result.toString(); |
| + } |
| + |
| + /** |
| + * Appends a string representing the specified collection to the specified |
| + * string buffer. The string is formatted as per [collectionToString]. |
| + * The [:visiting:] list contains references to all of the enclosing |
| + * collections and maps (which are currently in the process of being |
| + * emitted into [:result:]). The [:visiting:] parameter allows this method to |
| + * generate a [:"[...]":] or [:"{...}":] where required. In other words, |
| + * it allows this method and [_emitMap] to identify recursive collections |
| + * and maps. |
| + */ |
| + static void _emitCollection(Collection c, StringBuffer result, List visiting) { |
| + visiting.add(c); |
| + bool isList = c is List; |
| + result.add(isList ? "[" : "{"); |
| + |
| + bool first = true; |
| + for (var e in c) { |
| + if (!first) { |
| + result.add(", "); |
| + } |
| + first = false; |
| + _emitObject(e, result, visiting); |
| + } |
| + |
| + result.add(isList ? "]" : "}"); |
| + visiting.removeLast(); |
| + } |
| + |
| + /** |
| + * Appends a string representing the specified object to the specified |
| + * string buffer. If the object is a [Collection] or [Map], it is formatted |
| + * as per [collectionToString] or [mapToString]; otherwise, it is formatted |
| + * by invoking its own [toString] method. |
| + * |
| + * The [:visiting:] list contains references to all of the enclosing |
| + * collections and maps (which are currently in the process of being |
| + * emitted into [:result:]). The [:visiting:] parameter allows this method |
| + * to generate a [:"[...]":] or [:"{...}":] where required. In other words, |
| + * it allows this method and [_emitCollection] to identify recursive maps |
| + * and collections. |
| + */ |
| + static void _emitObject(Object o, StringBuffer result, List visiting) { |
| + if (o is Collection) { |
| + if (_containsRef(visiting, o)) { |
| + result.add(o is List ? "[...]" : "{...}"); |
| + } else { |
| + _emitCollection(o, result, visiting); |
| + } |
| + } else if (o is Map) { |
| + if (_containsRef(visiting, o)) { |
| + result.add("{...}"); |
| + } else { |
| + Maps._emitMap(o, result, visiting); |
| + } |
| + } else { // o is neither a collection nor a map |
| + result.add(o); |
| + } |
| + } |
| + |
| + /** |
| + * Returns true if the specified collection contains the specified object |
| + * reference. |
| + */ |
| + static _containsRef(Collection c, Object ref) { |
| + for (var e in c) { |
| + if (e === ref) return true; |
| + } |
| + return false; |
| + } |
| } |