| 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..f1cd85912a29d906fa9fc9af945dc6c0040401ed
|
| --- /dev/null
|
| +++ b/pkg/collection/lib/src/canonicalized_map.dart
|
| @@ -0,0 +1,115 @@
|
| +// 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 'dart:collection';
|
| +
|
| +import 'utils.dart';
|
| +
|
| +/**
|
| + * A map whose keys are converted to canonical values of type `C`.
|
| + *
|
| + * 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 key once, rather than doing so for each comparison.
|
| + *
|
| + * By default, `null` is allowed as a key. It can be forbidden via the
|
| + * `isValidKey` parameter.
|
| + */
|
| +class CanonicalizedMap<C, K, V> implements Map<K, V> {
|
| + final Function _canonicalize;
|
| +
|
| + final Function _isValidKeyFn;
|
| +
|
| + final _base = new Map<C, Pair<K, V>>();
|
| +
|
| + /**
|
| + * 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 equivalent.
|
| + *
|
| + * The [isValidKey] function is called before calling [canonicalize] for
|
| + * methods that take arbitrary objects. It can be used to filter out keys that
|
| + * can't be canonicalized.
|
| + */
|
| + CanonicalizedMap(C canonicalize(K key), {bool isValidKey(K key)})
|
| + : _canonicalize = canonicalize,
|
| + _isValidKeyFn = isValidKey;
|
| +
|
| + /**
|
| + * Creates a canonicalized map that is initialized with the key/value pairs of
|
| + * [other].
|
| + *
|
| + * The [canonicalize] function should return the canonical value for the given
|
| + * key. Keys with the same canonical value are considered equivalent.
|
| + *
|
| + * The [isValidKey] function is called before calling [canonicalize] for
|
| + * methods that take arbitrary objects. It can be used to filter out keys that
|
| + * can't be canonicalized.
|
| + */
|
| + CanonicalizedMap.from(Map<K, V> other, C canonicalize(K key),
|
| + {bool isValidKey(K key)})
|
| + : _canonicalize = canonicalize,
|
| + _isValidKeyFn = isValidKey {
|
| + addAll(other);
|
| + }
|
| +
|
| + V operator [](Object key) {
|
| + if (!_isValidKey(key)) return null;
|
| + var pair = _base[_canonicalize(key)];
|
| + return pair == null ? null : pair.last;
|
| + }
|
| +
|
| + void operator []=(K key, V value) {
|
| + _base[_canonicalize(key)] = new Pair(key, value);
|
| + }
|
| +
|
| + void addAll(Map<K, V> other) {
|
| + other.forEach((key, value) => this[key] = value);
|
| + }
|
| +
|
| + void clear() {
|
| + _base.clear();
|
| + }
|
| +
|
| + bool containsKey(Object key) {
|
| + if (!_isValidKey(key)) return false;
|
| + return _base.containsKey(_canonicalize(key));
|
| + }
|
| +
|
| + bool containsValue(Object value) =>
|
| + _base.values.any((pair) => pair.last == value);
|
| +
|
| + void forEach(void f(K key, V value)) {
|
| + _base.forEach((key, pair) => f(pair.first, pair.last));
|
| + }
|
| +
|
| + bool get isEmpty => _base.isEmpty;
|
| +
|
| + bool get isNotEmpty => _base.isNotEmpty;
|
| +
|
| + Iterable<K> get keys => _base.values.map((pair) => pair.first);
|
| +
|
| + int get length => _base.length;
|
| +
|
| + V putIfAbsent(K key, V ifAbsent()) {
|
| + return _base.putIfAbsent(_canonicalize(key),
|
| + () => new Pair(key, ifAbsent())).last;
|
| + }
|
| +
|
| + V remove(Object key) {
|
| + if (!_isValidKey(key)) return null;
|
| + var pair = _base.remove(_canonicalize(key));
|
| + return pair == null ? null : pair.last;
|
| + }
|
| +
|
| + Iterable<V> get values => _base.values.map((pair) => pair.last);
|
| +
|
| + String toString() => Maps.mapToString(this);
|
| +
|
| + bool _isValidKey(Object key) => (key == null || key is K) &&
|
| + (_isValidKeyFn == null || _isValidKeyFn(key));
|
| +}
|
|
|