Chromium Code Reviews| Index: pkg/serialization/lib/src/serialization_helpers.dart |
| diff --git a/pkg/serialization/lib/src/serialization_helpers.dart b/pkg/serialization/lib/src/serialization_helpers.dart |
| index df4b2cf285d0c38e28de414868e61c494b9f21f8..9423afe35ce783a0e043bbb1b9687b2155defe35 100644 |
| --- a/pkg/serialization/lib/src/serialization_helpers.dart |
| +++ b/pkg/serialization/lib/src/serialization_helpers.dart |
| @@ -8,7 +8,6 @@ |
| * available in the core library. |
| */ |
| library serialization_helpers; |
| -import 'polyfill_identity_set.dart'; |
| /** |
| * A named function of one argument that just returns it. Useful for using |
| @@ -39,6 +38,12 @@ List sorted(aCollection) { |
| return result; |
| } |
| +/** Helper function for PrimitiveRule to tell which objects it applies to. */ |
| +bool isPrimitive(object) { |
| + return identical(object, null) || object is num || object is String || |
| + identical(object, true) || identical(object, false); |
| +} |
| + |
| /** |
| * Be able to iterate polymorphically between List-like and Map-like things. |
| * For example, keysAndValues(["a", "b", "c"]).forEach((key, value) => ...); |
| @@ -167,39 +172,75 @@ class _Sentinel { |
| } |
| /** |
| - * This provides an identity map which allows true, false, and null as |
| - * valid keys. It does this by special casing them and using some other |
| - * known object as the key instead. |
| + * This provides an identity map which also allows true, false, and null |
| + * as valid keys. In the interests of avoiding duplicating map code, and |
| + * because hashCode for arbitrary objects is currently very slow on the VM, |
| + * just do a linear lookup. |
| */ |
| -class IdentityMapPlus<K, V> extends IdentityMap { |
| - final trueish = const _Sentinel(true); |
| - final falseish = const _Sentinel(false); |
| - final nullish = const _Sentinel(null); |
| - |
| - wrap(x) { |
| - if (x == true) return trueish; |
| - if (x == false) return falseish; |
| - if (x == null) return nullish; |
| - return x; |
| +class IdentityMap<K, V> implements Map<K, V> { |
| + |
| + List<K> keys = <K>[]; |
| + List<V> values = <V>[]; |
| + |
| + V operator [](K key) { |
| + var index = _indexOf(key); |
| + return (index == -1) ? null : values[index]; |
| } |
| - unwrap(x) { |
| - if (x is _Sentinel) return x._wrappedObject; |
| - return x; |
| + void operator []=(K key, V value) { |
| + var index = _indexOf(key); |
| + if (index == -1) { |
| + keys.add(key); |
| + values.add(value); |
| + } else { |
| + values[index] = value; |
| + } |
| } |
| - operator [](key) => super[wrap(key)]; |
| - operator []=(key, value) => super[wrap(key)] = value; |
| + putIfAbsent(K key, Function ifAbsent) { |
| + var index = _indexOf(key); |
| + if (index == -1) { |
| + keys.add(key); |
| + values.add(ifAbsent()); |
| + return values.last; |
| + } else { |
| + return values[index]; |
| + } |
| + } |
| - putIfAbsent(key, ifAbsent) => super.putIfAbsent(wrap(key), ifAbsent); |
| + _indexOf(K key) { |
| + // Go backwards on the guess that we are most likely to access the most |
| + // recently added. |
| + // Make strings and primitives unique |
| + var compareEquality = isPrimitive(key); |
| + for (var i = keys.length - 1; i >= 0; i--) { |
| + var equal = compareEquality ? key == keys[i] : identical(key, keys[i]); |
| + if (equal) return i; |
| + } |
| + return -1; |
| + } |
| - containsKey(key) => super.containsKey(wrap(key)); |
| - forEach(f) => super.forEach((key, value) => f(unwrap(key), value)); |
| - remove(key) => super.remove(unwrap(key)); |
| - /** |
| - * Note that keys is a very inefficient operation for this type. Don't do it. |
| - */ |
| - get keys => super.keys.map((x) => unwrap(x)); |
| -} |
| + bool containsKey(K key) => _indexOf(key) != -1; |
| + void forEach(f(K key, V value)) { |
| + for (var i = 0; i < keys.length; i++) { |
| + f(keys[i], values[i]); |
| + } |
| + } |
| + |
| + V remove(K key) { |
| + var index = _indexOf(key); |
| + if (index == -1) return null; |
| + keys.removeAt(index); |
| + return values.removeAt(index); |
| + } |
| + int get length => keys.length; |
| + void clear() { |
| + keys = <K>[]; |
|
Jennifer Messerly
2012/12/17 19:29:53
perhaps:
keys.clear();
values.clear(); ?
then ke
Alan Knight
2012/12/17 21:15:27
Nice. Done.
|
| + values = <V>[]; |
| + } |
| + bool get isEmpty => keys.isEmpty; |
| + // Note that this is doing an equality comparison. |
| + bool containsValue(x) => values.contains(x); |
| +} |