Chromium Code Reviews| Index: pkg/collection/lib/src/canonicalized_map.dart |
| diff --git a/pkg/collection/lib/src/canonicalized_map.dart b/pkg/collection/lib/src/canonicalized_map.dart |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..8ec48ed68285498609a9caaf54e17b5afa7db3e4 |
| --- /dev/null |
| +++ b/pkg/collection/lib/src/canonicalized_map.dart |
| @@ -0,0 +1,88 @@ |
| +// Copyright (c) 2014, 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. |
| + |
| +library dart.pkg.collection.canonicalized_map; |
| + |
| +import '../wrappers.dart'; |
| + |
| +/** |
| + * A map whose keys are converted to canonical values. |
| + * |
| + * This is useful for using case-insensitive String keys, for example. It's more |
| + * efficient than a [LinkedHashMap] with a custom equality operator because it |
| + * only canonicalizes each once, rather than doing so for each comparison. |
| + */ |
| +class CanonicalizedMap<K, V> extends DelegatingMap<K, V> { |
|
Lasse Reichstein Nielsen
2014/06/27 06:57:47
Could we allow the canonicalization of a key to no
nweiz
2014/06/30 20:37:46
Done.
|
| + final Function _canonicalize; |
| + |
| + /** |
| + * A map from the canonicalized keys to their original values. |
| + */ |
| + final _keys = new Map<K, V>(); |
|
Lasse Reichstein Nielsen
2014/06/27 06:57:47
Should be <K,K>.
Have you considered using a
nweiz
2014/06/30 20:37:46
Done, using the Pair class that's used elsewhere i
|
| + |
| + /** |
| + * Creates an empty canonicalized map. |
| + * |
| + * The [canonicalize] function should return the canonical value for the given |
| + * key. Keys with the same canonical value are considered identical, and the |
|
Lasse Reichstein Nielsen
2014/06/27 06:57:47
identical -> equivalent
Ditto below.
nweiz
2014/06/30 20:37:46
Done.
|
| + * canonical values of the keys are stored in the map. |
|
Lasse Reichstein Nielsen
2014/06/27 06:57:47
"stored in the map" is vague but sounds significan
nweiz
2014/06/30 20:37:46
I just removed this. It was a holdover from before
|
| + */ |
| + CanonicalizedMap(K canonicalize(K key)) |
|
Lasse Reichstein Nielsen
2014/06/27 06:57:47
I'd also like to have an "bool isValidKey(Object o
Lasse Reichstein Nielsen
2014/06/27 06:57:47
Please see if you can also make the map a paramete
nweiz
2014/06/30 20:37:46
I don't completely understand the purpose of this
nweiz
2014/06/30 20:37:46
I don't think it's worth complicating the API to s
Lasse Reichstein Nielsen
2014/07/01 09:18:14
ACK, if we make the type of canonical object C ins
Lasse Reichstein Nielsen
2014/07/01 09:18:14
I assume that if isValidKey(o) return false, then
nweiz
2014/07/01 21:21:44
Done.
|
| + : _canonicalize = canonicalize, |
| + super({}); |
| + |
| + /** |
| + * Creates a canonicalized map that contains all key/value pairs of [other]. |
|
Lasse Reichstein Nielsen
2014/06/27 06:57:47
Because of the canonicalization, it might contain
nweiz
2014/06/30 20:37:46
Good point. Done.
|
| + * |
| + * The [canonicalize] function should return the canonical value for the given |
| + * key. Keys with the same canonical value are considered identical, and the |
| + * canonical values of the keys are stored in the map. |
| + */ |
| + CanonicalizedMap.from(Map<K, V> other, K canonicalize(K key)) |
| + : _canonicalize = canonicalize, |
| + super({}) { |
| + addAll(other); |
| + } |
| + |
| + V operator [](Object key) { |
| + if (key != null && key is! K) return null; |
| + return super[_canonicalize(key)]; |
| + } |
| + |
| + void operator []=(K key, V value) { |
| + var canonical = _canonicalize(key); |
| + _keys[canonical] = key; |
| + super[canonical] = value; |
| + } |
| + |
| + void addAll(Map<K, V> other) { |
| + other.forEach((key, value) => this[key] = value); |
| + } |
| + |
| + bool containsKey(Object key) { |
| + if (key != null && key is! K) return null; |
| + return super.containsKey(_canonicalize(key)); |
| + } |
| + |
| + void forEach(void f(K key, V value)) { |
| + super.forEach((key, value) => f(_keys[key], value)); |
| + } |
| + |
| + Iterable<K> get keys => _keys.values; |
| + |
| + V putIfAbsent(K key, V ifAbsent()) { |
| + var canonical = _canonicalize(key); |
| + return super.putIfAbsent(canonical, () { |
| + _keys[canonical] = key; |
| + return ifAbsent(); |
| + }); |
| + } |
| + |
| + V remove(Object key) { |
| + if (key != null && key is! K) return null; |
| + var canonical = _canonicalize(key); |
| + _keys.remove(canonical); |
| + return super.remove(canonical); |
| + } |
| +} |