| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2013, 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.collection.dev; | |
| 6 | |
| 7 /** | |
| 8 * Temporary move `toString` methods into this class. | |
| 9 */ | |
| 10 class ToString { | |
| 11 // TODO(jjb): visiting list should be an identityHashSet when it exists | |
| 12 | |
| 13 /** | |
| 14 * Returns a string representing the specified collection. If the | |
| 15 * collection is a [List], the returned string looks like this: | |
| 16 * [:'[element0, element1, ... elementN]':]. The value returned by its | |
| 17 * [toString] method is used to represent each element. If the specified | |
| 18 * collection is not a list, the returned string looks like this: | |
| 19 * [:{element0, element1, ... elementN}:]. In other words, the strings | |
| 20 * returned for lists are surrounded by square brackets, while the strings | |
| 21 * returned for other collections are surrounded by curly braces. | |
| 22 * | |
| 23 * If the specified collection contains a reference to itself, either | |
| 24 * directly or indirectly through other collections or maps, the contained | |
| 25 * reference is rendered as [:'[...]':] if it is a list, or [:'{...}':] if | |
| 26 * it is not. This prevents the infinite regress that would otherwise occur. | |
| 27 * So, for example, calling this method on a list whose sole element is a | |
| 28 * reference to itself would return [:'[[...]]':]. | |
| 29 * | |
| 30 * A typical implementation of a collection's [toString] method will | |
| 31 * simply return the results of this method applied to the collection. | |
| 32 */ | |
| 33 static String collectionToString(Collection c) { | |
| 34 var result = new StringBuffer(); | |
| 35 _emitCollection(c, result, new List()); | |
| 36 return result.toString(); | |
| 37 } | |
| 38 | |
| 39 /** | |
| 40 * Appends a string representing the specified collection to the specified | |
| 41 * string buffer. The string is formatted as per [collectionToString]. | |
| 42 * The [:visiting:] list contains references to all of the enclosing | |
| 43 * collections and maps (which are currently in the process of being | |
| 44 * emitted into [:result:]). The [:visiting:] parameter allows this method to | |
| 45 * generate a [:'[...]':] or [:'{...}':] where required. In other words, | |
| 46 * it allows this method and [_emitMap] to identify recursive collections | |
| 47 * and maps. | |
| 48 */ | |
| 49 static void _emitCollection(Collection c, | |
| 50 StringBuffer result, | |
| 51 List visiting) { | |
| 52 visiting.add(c); | |
| 53 bool isList = c is List; | |
| 54 result.add(isList ? '[' : '{'); | |
| 55 | |
| 56 bool first = true; | |
| 57 for (var e in c) { | |
| 58 if (!first) { | |
| 59 result.add(', '); | |
| 60 } | |
| 61 first = false; | |
| 62 _emitObject(e, result, visiting); | |
| 63 } | |
| 64 | |
| 65 result.add(isList ? ']' : '}'); | |
| 66 visiting.removeLast(); | |
| 67 } | |
| 68 | |
| 69 /** | |
| 70 * Appends a string representing the specified object to the specified | |
| 71 * string buffer. If the object is a [Collection] or [Map], it is formatted | |
| 72 * as per [collectionToString] or [mapToString]; otherwise, it is formatted | |
| 73 * by invoking its own [toString] method. | |
| 74 * | |
| 75 * The [:visiting:] list contains references to all of the enclosing | |
| 76 * collections and maps (which are currently in the process of being | |
| 77 * emitted into [:result:]). The [:visiting:] parameter allows this method | |
| 78 * to generate a [:'[...]':] or [:'{...}':] where required. In other words, | |
| 79 * it allows this method and [_emitCollection] to identify recursive maps | |
| 80 * and collections. | |
| 81 */ | |
| 82 static void _emitObject(Object o, StringBuffer result, List visiting) { | |
| 83 if (o is Collection) { | |
| 84 if (_containsRef(visiting, o)) { | |
| 85 result.add(o is List ? '[...]' : '{...}'); | |
| 86 } else { | |
| 87 _emitCollection(o, result, visiting); | |
| 88 } | |
| 89 } else if (o is Map) { | |
| 90 if (_containsRef(visiting, o)) { | |
| 91 result.add('{...}'); | |
| 92 } else { | |
| 93 _emitMap(o, result, visiting); | |
| 94 } | |
| 95 } else { // o is neither a collection nor a map | |
| 96 result.add(o); | |
| 97 } | |
| 98 } | |
| 99 | |
| 100 /** | |
| 101 * Returns true if the specified collection contains the specified object | |
| 102 * reference. | |
| 103 */ | |
| 104 static _containsRef(Collection c, Object ref) { | |
| 105 for (var e in c) { | |
| 106 if (identical(e, ref)) return true; | |
| 107 } | |
| 108 return false; | |
| 109 } | |
| 110 | |
| 111 /** | |
| 112 * Returns a string representing the specified map. The returned string | |
| 113 * looks like this: [:'{key0: value0, key1: value1, ... keyN: valueN}':]. | |
| 114 * The value returned by its [toString] method is used to represent each | |
| 115 * key or value. | |
| 116 * | |
| 117 * If the map collection contains a reference to itself, either | |
| 118 * directly as a key or value, or indirectly through other collections | |
| 119 * or maps, the contained reference is rendered as [:'{...}':]. This | |
| 120 * prevents the infinite regress that would otherwise occur. So, for example, | |
| 121 * calling this method on a map whose sole entry maps the string key 'me' | |
| 122 * to a reference to the map would return [:'{me: {...}}':]. | |
| 123 * | |
| 124 * A typical implementation of a map's [toString] method will | |
| 125 * simply return the results of this method applied to the collection. | |
| 126 */ | |
| 127 static String mapToString(Map m) { | |
| 128 var result = new StringBuffer(); | |
| 129 _emitMap(m, result, new List()); | |
| 130 return result.toString(); | |
| 131 } | |
| 132 | |
| 133 /** | |
| 134 * Appends a string representing the specified map to the specified | |
| 135 * string buffer. The string is formatted as per [mapToString]. | |
| 136 * The [:visiting:] list contains references to all of the enclosing | |
| 137 * collections and maps (which are currently in the process of being | |
| 138 * emitted into [:result:]). The [:visiting:] parameter allows this method | |
| 139 * to generate a [:'[...]':] or [:'{...}':] where required. In other words, | |
| 140 * it allows this method and [_emitCollection] to identify recursive maps | |
| 141 * and collections. | |
| 142 */ | |
| 143 static void _emitMap(Map m, StringBuffer result, List visiting) { | |
| 144 visiting.add(m); | |
| 145 result.add('{'); | |
| 146 | |
| 147 bool first = true; | |
| 148 m.forEach((k, v) { | |
| 149 if (!first) { | |
| 150 result.add(', '); | |
| 151 } | |
| 152 first = false; | |
| 153 _emitObject(k, result, visiting); | |
| 154 result.add(': '); | |
| 155 _emitObject(v, result, visiting); | |
| 156 }); | |
| 157 | |
| 158 result.add('}'); | |
| 159 visiting.removeLast(); | |
| 160 } | |
| 161 } | |
| OLD | NEW |