Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 * This contains extra functions and classes useful for implementing | 6 * This contains extra functions and classes useful for implementing |
| 7 * serialiation. Some or all of these will be removed once the functionality is | 7 * serialiation. Some or all of these will be removed once the functionality is |
| 8 * available in the core library. | 8 * available in the core library. |
| 9 */ | 9 */ |
| 10 library serialization_helpers; | 10 library serialization_helpers; |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 173 /** | 173 /** |
| 174 * This acts as a stand-in for some value that cannot be hashed. We can't | 174 * This acts as a stand-in for some value that cannot be hashed. We can't |
| 175 * just use const Object() because the compiler will fold them together. | 175 * just use const Object() because the compiler will fold them together. |
| 176 */ | 176 */ |
| 177 class _Sentinel { | 177 class _Sentinel { |
| 178 final _wrappedObject; | 178 final _wrappedObject; |
| 179 const _Sentinel(this._wrappedObject); | 179 const _Sentinel(this._wrappedObject); |
| 180 } | 180 } |
| 181 | 181 |
| 182 /** | 182 /** |
| 183 * This provides an identity map which also allows true, false, and null | 183 * This is used to provide an identity map. We wrap all the objects in |
|
Jennifer Messerly
2013/08/26 21:58:47
this comment belongs on the IdentityMap type inste
Alan Knight
2013/08/27 18:13:44
Rephrased and put it on both.
| |
| 184 * as valid keys. In the interests of avoiding duplicating map code, and | 184 * the map in something whose equality is based on identity of the |
| 185 * because hashCode for arbitrary objects is currently very slow on the VM, | 185 * wrapped objects. It also treats equal primitive values as identical |
| 186 * just do a linear lookup. | 186 * to conserve space. This is still not particularly efficient, and |
| 187 * should be removed once we have a real identity map. | |
| 188 */ | |
| 189 // TODO(alanknight): Replace with a real identityMap. Issue 4161. | |
|
Jennifer Messerly
2013/08/26 21:58:47
remove todo? or perhaps change it to:
TODO: implem
Alan Knight
2013/08/27 18:13:44
Rephrased the TODO. The bug is for the core librar
| |
| 190 class IdentityMapWrapper { | |
|
Jennifer Messerly
2013/08/26 21:58:47
maybe make this class library private to indicate
Alan Knight
2013/08/27 18:13:44
Done.
| |
| 191 IdentityMapWrapper(this._value); | |
| 192 var _value; | |
| 193 | |
| 194 /** | |
| 195 * Check if an object is primitive to know if we should compare it using | |
| 196 * equality or identity. We don't test null/true/false where it's the same. | |
| 197 */ | |
| 198 _isPrimitive(x) => x is String || x is num; | |
| 199 | |
| 200 operator ==(IdentityMapWrapper w) => | |
| 201 _isPrimitive(_value) ? _value == w._value : identical(_value, w._value); | |
| 202 get hashCode => _value.hashCode; | |
| 203 get object => _value; | |
| 204 } | |
| 205 | |
| 206 /** | |
| 207 * This provides an identity map. | |
| 187 */ | 208 */ |
| 188 class IdentityMap<K, V> implements Map<K, V> { | 209 class IdentityMap<K, V> implements Map<K, V> { |
|
Jennifer Messerly
2013/08/26 21:58:47
I wonder if it's possible and a good idea to exten
Alan Knight
2013/08/27 18:13:44
Possible, and does make the code simpler, but unfo
| |
| 189 | 210 |
| 190 final List<K> keys = <K>[]; | 211 final Map<IdentityMapWrapper, V> map = new Map<IdentityMapWrapper, V>(); |
| 191 final List<V> values = <V>[]; | |
| 192 | 212 |
| 193 V operator [](Object key) { | 213 _wrap(Object key) => new IdentityMapWrapper(key); |
| 194 var index = _indexOf(key); | 214 _unwrap(IdentityMapWrapper wrapper) => wrapper.object; |
| 195 return (index == -1) ? null : values[index]; | 215 |
| 216 Iterable<K> get keys => map.keys.map((x) => _unwrap(x)); | |
| 217 Iterable<V> get values => map.values; | |
| 218 | |
| 219 void forEach(void f(K key, V value)) { | |
| 220 map.keys.forEach((k) => f(_unwrap(k), map[k])); | |
|
Jennifer Messerly
2013/08/26 21:58:47
perhaps:
map.forEach((k, v) { f(_unwrap(k), v); }
Alan Knight
2013/08/27 18:13:44
Done.
| |
| 196 } | 221 } |
| 197 | 222 |
| 223 V operator [](K key) => map[_wrap(key)]; | |
| 224 | |
| 198 void operator []=(K key, V value) { | 225 void operator []=(K key, V value) { |
| 199 var index = _indexOf(key); | 226 map[_wrap(key)] = value; |
| 200 if (index == -1) { | |
| 201 keys.add(key); | |
| 202 values.add(value); | |
| 203 } else { | |
| 204 values[index] = value; | |
| 205 } | |
| 206 } | 227 } |
| 207 | 228 |
| 208 V putIfAbsent(K key, Function ifAbsent) { | 229 V putIfAbsent(K key, Function ifAbsent) => |
| 209 var index = _indexOf(key); | 230 map.putIfAbsent(_wrap(key), ifAbsent); |
| 210 if (index == -1) { | |
| 211 keys.add(key); | |
| 212 values.add(ifAbsent()); | |
| 213 return values.last; | |
| 214 } else { | |
| 215 return values[index]; | |
| 216 } | |
| 217 } | |
| 218 | 231 |
| 219 int _indexOf(Object key) { | 232 bool containsKey(Object key) => map.containsKey(_wrap(key)); |
| 220 // Go backwards on the guess that we are most likely to access the most | |
| 221 // recently added. | |
| 222 // Make strings and primitives unique | |
| 223 var compareEquality = isPrimitive(key); | |
| 224 for (var i = keys.length - 1; i >= 0; i--) { | |
| 225 var equal = compareEquality ? key == keys[i] : identical(key, keys[i]); | |
| 226 if (equal) return i; | |
| 227 } | |
| 228 return -1; | |
| 229 } | |
| 230 | 233 |
| 231 bool containsKey(Object key) => _indexOf(key) != -1; | 234 V remove(Object key) => map.remove(_wrap(key)); |
| 232 void forEach(f(K key, V value)) { | |
| 233 for (var i = 0; i < keys.length; i++) { | |
| 234 f(keys[i], values[i]); | |
| 235 } | |
| 236 } | |
| 237 | |
| 238 V remove(Object key) { | |
| 239 var index = _indexOf(key); | |
| 240 if (index == -1) return null; | |
| 241 keys.removeAt(index); | |
| 242 return values.removeAt(index); | |
| 243 } | |
| 244 | 235 |
| 245 int get length => keys.length; | 236 int get length => keys.length; |
| 246 void clear() { | 237 void clear() => map.clear(); |
| 247 keys.clear(); | 238 |
| 248 values.clear(); | 239 bool get isEmpty => map.isEmpty; |
| 249 } | 240 bool get isNotEmpty => !map.isEmpty; |
| 250 bool get isEmpty => keys.isEmpty; | |
| 251 bool get isNotEmpty => !isEmpty; | |
| 252 | 241 |
| 253 // Note that this is doing an equality comparison. | 242 // Note that this is doing an equality comparison. |
| 254 bool containsValue(Object x) => values.contains(x); | 243 bool containsValue(Object x) => map.containsValue(x); |
| 255 | 244 |
| 256 void addAll(Map<K, V> other) { | 245 void addAll(Map<K, V> other) { |
| 257 other.forEach((K key, V value) { | 246 other.forEach((K key, V value) { |
| 258 this[key] = value; | 247 this[key] = value; |
|
Jennifer Messerly
2013/08/26 21:58:47
_wrap?
Alan Knight
2013/08/27 18:13:44
[]= will wrap, so not needed. With subclassing, th
| |
| 259 }); | 248 }); |
| 260 } | 249 } |
| 261 } | 250 } |
| OLD | NEW |