blob: b8d0d3c62d7b9cb8ed74402db42413aba5f6c39e [file] [log] [blame]
// Copyright (c) 2012, 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.
// Immutable map class for compiler generated map literals.
class ImmutableMap<K, V> implements Map<K, V> {
final _ImmutableList _kvPairs;
const ImmutableMap._create(_ImmutableList keyValuePairs)
: _kvPairs = keyValuePairs;
V operator [](Object key) {
// To preserve the key-value order of the map literal, the keys are
// not sorted. Need to do linear search or implement an additional
// lookup table.
for (int i = 0; i < _kvPairs.length - 1; i += 2) {
if (key == _kvPairs[i]) {
return _kvPairs[i+1];
}
}
return null;
}
bool get isEmpty {
return _kvPairs.length == 0;
}
bool get isNotEmpty => !isEmpty;
int get length {
return _kvPairs.length ~/ 2;
}
void forEach(void f(K key, V value)) {
for (int i = 0; i < _kvPairs.length; i += 2) {
f(_kvPairs[i], _kvPairs[i+1]);
}
}
Iterable<K> get keys {
return new _ImmutableMapKeyIterable<K>(this);
}
Iterable<V> get values {
return new _ImmutableMapValueIterable<V>(this);
}
bool containsKey(Object key) {
for (int i = 0; i < _kvPairs.length; i += 2) {
if (key == _kvPairs[i]) {
return true;
}
}
return false;
}
bool containsValue(Object value) {
for (int i = 1; i < _kvPairs.length; i += 2) {
if (value == _kvPairs[i]) {
return true;
}
}
return false;
}
void operator []=(K key, V value) {
throw new UnsupportedError("Cannot set value in unmodifiable Map");
}
V putIfAbsent(K key, V ifAbsent()) {
throw new UnsupportedError("Cannot set value in unmodifiable Map");
}
void clear() {
throw new UnsupportedError("Cannot clear unmodifiable Map");
}
V remove(Object key) {
throw new UnsupportedError("Cannot remove from unmodifiable Map");
}
String toString() {
return Maps.mapToString(this);
}
}
class _ImmutableMapKeyIterable<E> extends IterableBase<E>
implements EfficientLength {
final ImmutableMap _map;
_ImmutableMapKeyIterable(this._map);
Iterator<E> get iterator {
return new _ImmutableMapKeyIterator<E>(_map);
}
int get length => _map.length;
}
class _ImmutableMapValueIterable<E> extends IterableBase<E>
implements EfficientLength {
final ImmutableMap _map;
_ImmutableMapValueIterable(this._map);
Iterator<E> get iterator {
return new _ImmutableMapValueIterator<E>(_map);
}
int get length => _map.length;
}
class _ImmutableMapKeyIterator<E> implements Iterator<E> {
ImmutableMap _map;
int _index = -1;
E _current;
_ImmutableMapKeyIterator(this._map);
bool moveNext() {
int newIndex = _index + 1;
if (newIndex < _map.length) {
_index = newIndex;
_current = _map._kvPairs[newIndex * 2];
return true;
}
_current = null;
_index = _map.length;
return false;
}
E get current => _current;
}
class _ImmutableMapValueIterator<E> implements Iterator<E> {
ImmutableMap _map;
int _index = -1;
E _current;
_ImmutableMapValueIterator(this._map);
bool moveNext() {
int newIndex = _index + 1;
if (newIndex < _map.length) {
_index = newIndex;
_current = _map._kvPairs[newIndex * 2 + 1];
return true;
}
_current = null;
_index = _map.length;
return false;
}
E get current => _current;
}