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 |