diff --git a/lib/change_detection/prototype_map.dart b/lib/change_detection/prototype_map.dart index 3c634b36c..4aa85a9b6 100644 --- a/lib/change_detection/prototype_map.dart +++ b/lib/change_detection/prototype_map.dart @@ -1,37 +1,12 @@ part of angular.watch_group; -class PrototypeMap implements Map { +class PrototypeMap extends MicroMap { final Map prototype; - final Map self = new HashMap(); PrototypeMap(this.prototype); - void operator []=(name, value) { - self[name] = value; - } - V operator [](name) => self.containsKey(name) ? self[name] : prototype[name]; + V operator [](name) => containsKey(name) ? super[name] : prototype[name]; - bool get isEmpty => self.isEmpty && prototype.isEmpty; - bool get isNotEmpty => self.isNotEmpty || prototype.isNotEmpty; - // todo(vbe) include prototype keys ? - Iterable get keys => self.keys; - // todo(vbe) include prototype values ? - Iterable get values => self.values; - int get length => self.length; - - void forEach(fn) { - // todo(vbe) include prototype ? - self.forEach(fn); - } - V remove(key) => self.remove(key); - clear() => self.clear; - // todo(vbe) include prototype ? - bool containsKey(key) => self.containsKey(key); - // todo(vbe) include prototype ? - bool containsValue(key) => self.containsValue(key); - void addAll(map) { - self.addAll(map); - } - // todo(vbe) include prototype ? - V putIfAbsent(key, fn) => self.putIfAbsent(key, fn); + bool get isEmpty => count == 0 && prototype.isEmpty; + bool get isNotEmpty => count != 0 || prototype.isNotEmpty; } diff --git a/lib/change_detection/watch_group.dart b/lib/change_detection/watch_group.dart index f257260d5..72ac83d8f 100644 --- a/lib/change_detection/watch_group.dart +++ b/lib/change_detection/watch_group.dart @@ -1,6 +1,7 @@ library angular.watch_group; import 'package:angular/change_detection/change_detection.dart'; +import 'package:angular/collection/micro_map.dart'; import 'dart:collection'; part 'linked_list.dart'; diff --git a/lib/collection/micro_iterable.dart b/lib/collection/micro_iterable.dart new file mode 100644 index 000000000..66e30eac7 --- /dev/null +++ b/lib/collection/micro_iterable.dart @@ -0,0 +1,281 @@ +library angular.collection; + +import 'dart:collection'; + +const int _LIST_ELEMENTS = 20; + +class MicroIterable extends Object with IterableMixin implements Iterable { + var _element0; + var _element1; + var _element2; + var _element3; + var _element4; + var _element5; + var _element6; + var _element7; + var _element8; + var _element9; + var _element10; + var _element11; + var _element12; + var _element13; + var _element14; + var _element15; + var _element16; + var _element17; + var _element18; + var _element19; + var _count = 0; + + MicroIterable(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, count) { + _element0 = e0 ; + _element1 = e1 ; + _element2 = e2 ; + _element3 = e3 ; + _element4 = e4 ; + _element5 = e5 ; + _element6 = e6 ; + _element7 = e7 ; + _element8 = e8 ; + _element9 = e9 ; + _element10 = e10; + _element11 = e11; + _element12 = e12; + _element13 = e13; + _element14 = e14; + _element15 = e15; + _element16 = e16; + _element17 = e17; + _element18 = e18; + _element19 = e19; + _count = count; + } + + Iterator get iterator => new _ListIterator(this); + + bool contains(Object element) { + if (_element0 == element) return true; + else if (_element1 == element) return true; + else if (_element2 == element) return true; + else if (_element3 == element) return true; + else if (_element4 == element) return true; + else if (_element5 == element) return true; + else if (_element6 == element) return true; + else if (_element7 == element) return true; + else if (_element8 == element) return true; + else if (_element9 == element) return true; + else if (_element10 == element) return true; + else if (_element11 == element) return true; + else if (_element12 == element) return true; + else if (_element13 == element) return true; + else if (_element14 == element) return true; + else if (_element15 == element) return true; + else if (_element16 == element) return true; + else if (_element17 == element) return true; + else if (_element18 == element) return true; + else if (_element19 == element) return true; + else return false; + } + + String join([String separator = ""]) { + if (_element0 == null) return null; + var joined = '${_element0}'; + if (_element1 == null) return joined; + joined = '$joined$separator$_element1'; + if (_element2 == null) return joined; + joined = '$joined$separator$_element2'; + if (_element3 == null) return joined; + joined = '$joined$separator$_element3'; + if (_element4 == null) return joined; + joined = '$joined$separator$_element4'; + if (_element5 == null) return joined; + joined = '$joined$separator$_element5'; + if (_element6 == null) return joined; + joined = '$joined$separator$_element6'; + if (_element7 == null) return joined; + joined = '$joined$separator$_element7'; + if (_element8 == null) return joined; + joined = '$joined$separator$_element8'; + if (_element9 == null) return joined; + joined = '$joined$separator$_element9'; + if (_element10 == null) return joined; + joined = '$joined$separator$_element10'; + if (_element11 == null) return joined; + joined = '$joined$separator$_element11'; + if (_element12 == null) return joined; + joined = '$joined$separator$_element12'; + if (_element13 == null) return joined; + joined = '$joined$separator$_element13'; + if (_element14 == null) return joined; + joined = '$joined$separator$_element14'; + if (_element15 == null) return joined; + joined = '$joined$separator$_element15'; + if (_element16 == null) return joined; + joined = '$joined$separator$_element16'; + if (_element17 == null) return joined; + joined = '$joined$separator$_element17'; + if (_element18 == null) return joined; + joined = '$joined$separator$_element18'; + if (_element19 == null) return joined; + joined = '$joined$separator$_element19'; + return joined; + } + + List toList({bool growable}) { + if (growable != null) return new List.from(this, growable: growable); + return new List.from(this); + } + + Set toSet() { + Set set = new HashSet(); + if (_count == 0) return set; + if (_element0 != null) set.add(_element0 ); + if (_count == 1) return set; + if (_element1 != null) set.add(_element1 ); + if (_count == 2) return set; + if (_element2 != null) set.add(_element2 ); + if (_count == 3) return set; + if (_element3 != null) set.add(_element3 ); + if (_count == 4) return set; + if (_element4 != null) set.add(_element4 ); + if (_count == 5) return set; + if (_element5 != null) set.add(_element5 ); + if (_count == 6) return set; + if (_element6 != null) set.add(_element6 ); + if (_count == 7) return set; + if (_element7 != null) set.add(_element7 ); + if (_count == 8) return set; + if (_element8 != null) set.add(_element7 ); + if (_count == 9) return set; + if (_element9 != null) set.add(_element8 ); + if (_count == 10) return set; + if (_element10 != null) set.add(_element10); + if (_count == 11) return set; + if (_element11 != null) set.add(_element11); + if (_count == 12) return set; + if (_element12 != null) set.add(_element12); + if (_count == 13) return set; + if (_element13 != null) set.add(_element13); + if (_count == 14) return set; + if (_element14 != null) set.add(_element14); + if (_count == 15) return set; + if (_element15 != null) set.add(_element15); + if (_count == 16) return set; + if (_element16 != null) set.add(_element16); + if (_count == 17) return set; + if (_element17 != null) set.add(_element16); + if (_count == 18) return set; + if (_element18 != null) set.add(_element18); + if (_count == 19) return set; + if (_element19 != null) set.add(_element19); + return set; + } + + int get length => _count; + + bool get isEmpty => _count == 0; + + bool get isNotEmpty => _count != 0; + + E get first { + if (_element0 != null) return _element0 ; + if (_element1 != null) return _element1 ; + if (_element2 != null) return _element2 ; + if (_element3 != null) return _element3 ; + if (_element4 != null) return _element4 ; + if (_element5 != null) return _element5 ; + if (_element6 != null) return _element6 ; + if (_element7 != null) return _element7 ; + if (_element8 != null) return _element8 ; + if (_element9 != null) return _element9 ; + if (_element10 != null) return _element10; + if (_element11 != null) return _element11; + if (_element12 != null) return _element12; + if (_element13 != null) return _element13; + if (_element14 != null) return _element14; + if (_element15 != null) return _element15; + if (_element16 != null) return _element16; + if (_element17 != null) return _element17; + if (_element18 != null) return _element18; + if (_element19 != null) return _element19; + } + + E get last { + if (_element19 != null) return _element19; + if (_element18 != null) return _element18; + if (_element17 != null) return _element17; + if (_element16 != null) return _element16; + if (_element15 != null) return _element15; + if (_element14 != null) return _element14; + if (_element13 != null) return _element13; + if (_element12 != null) return _element12; + if (_element11 != null) return _element11; + if (_element10 != null) return _element10; + if (_element9 != null) return _element9 ; + if (_element8 != null) return _element8 ; + if (_element7 != null) return _element7 ; + if (_element6 != null) return _element6 ; + if (_element5 != null) return _element5 ; + if (_element4 != null) return _element4 ; + if (_element3 != null) return _element3 ; + if (_element2 != null) return _element2 ; + if (_element1 != null) return _element1 ; + if (_element0 != null) return _element0 ; + } + + E get single { + if (length == 0) throw "No elements"; + if (length > 1) throw "More then one element"; + return elementAt(0); + } + + E elementAt(int index) { + if (index == 0 ) return _element0 ; + if (index == 1 ) return _element1 ; + if (index == 2 ) return _element2 ; + if (index == 3 ) return _element3 ; + if (index == 4 ) return _element4 ; + if (index == 5 ) return _element5 ; + if (index == 6 ) return _element6 ; + if (index == 7 ) return _element7 ; + if (index == 8 ) return _element8 ; + if (index == 9 ) return _element9 ; + if (index == 10) return _element10; + if (index == 11) return _element11; + if (index == 12) return _element12; + if (index == 13) return _element13; + if (index == 14) return _element14; + if (index == 15) return _element15; + if (index == 16) return _element16; + if (index == 17) return _element17; + if (index == 18) return _element18; + if (index == 19) return _element19; + } +} + +class _ListIterator implements Iterator { + + MicroIterable _iterable; + var _length; + var _current; + var _cursor = 0; + + _ListIterator(iterable): _iterable = iterable, _length = iterable.length, _cursor = 0; + + bool moveNext() { + int length = _iterable.length; + if (_length != length) { + throw new ConcurrentModificationError(_iterable); + } + if (_cursor >= length) { + _current = null; + return false; + } + _current = _iterable.elementAt(_cursor); + _cursor++; + return true; + } + + E get current => _current; + +} \ No newline at end of file diff --git a/lib/collection/micro_map.dart b/lib/collection/micro_map.dart new file mode 100644 index 000000000..875f6564c --- /dev/null +++ b/lib/collection/micro_map.dart @@ -0,0 +1,522 @@ +library angular.collection; + +import 'dart:collection'; +import 'micro_iterable.dart'; + +const int _LIST_ELEMENTS = 20; +const int MODE_ARRAY = 0; +const int MODE_MAP = 1; + +class MicroMap implements Map { + + var _key0; var _obj0; + var _key1; var _obj1; + var _key2; var _obj2; + var _key3; var _obj3; + var _key4; var _obj4; + var _key5; var _obj5; + var _key6; var _obj6; + var _key7; var _obj7; + var _key8; var _obj8; + var _key9; var _obj9; + var _key10; var _obj10; + var _key11; var _obj11; + var _key12; var _obj12; + var _key13; var _obj13; + var _key14; var _obj14; + var _key15; var _obj15; + var _key16; var _obj16; + var _key17; var _obj17; + var _key18; var _obj18; + var _key19; var _obj19; + int count; + Map delegate; + + + MicroMap() { + count = 0; + } + + bool containsValue(Object value) { + if (delegate == null) { + if(_obj0 == value) return true; + if(count == 0) return false; + if(_obj1 == value) return true; + if(count == 1) return false; + if(_obj2 == value) return true; + if(count == 2) return false; + if(_obj3 == value) return true; + if(count == 3) return false; + if(_obj4 == value) return true; + if(count == 4) return false; + if(_obj5 == value) return true; + if(count == 5) return false; + if(_obj6 == value) return true; + if(count == 6) return false; + if(_obj7 == value) return true; + if(count == 7) return false; + if(_obj8 == value) return true; + if(count == 8) return false; + if(_obj9 == value) return true; + if(count == 9) return false; + if(_obj10 == value) return true; + if(count == 10) return false; + if(_obj11 == value) return true; + if(count == 11) return false; + if(_obj12 == value) return true; + if(count == 12) return false; + if(_obj13 == value) return true; + if(count == 13) return false; + if(_obj14 == value) return true; + if(count == 14) return false; + if(_obj15 == value) return true; + if(count == 15) return false; + if(_obj16 == value) return true; + if(count == 16) return false; + if(_obj17 == value) return true; + if(count == 17) return false; + if(_obj18 == value) return true; + if(count == 18) return false; + if(_obj19 == value) return true; + return false; + } else { + return delegate.containsValue(value); + } + } + + bool containsKey(Object key) { + if (delegate == null) { + if(_key0 == null) return false; + if(_key0 == key) return true; + if(_key1 == null) return false; + if(_key1 == key) return true; + if(_key2 == null) return false; + if(_key2 == key) return true; + if(_key3 == null) return false; + if(_key3 == key) return true; + if(_key4 == null) return false; + if(_key4 == key) return true; + if(_key5 == null) return false; + if(_key5 == key) return true; + if(_key6 == null) return false; + if(_key6 == key) return true; + if(_key7 == null) return false; + if(_key7 == key) return true; + if(_key8 == null) return false; + if(_key8 == key) return true; + if(_key9 == null) return false; + if(_key9 == key) return true; + if(_key10 == null) return false; + if(_key10 == key) return true; + if(_key11 == null) return false; + if(_key11 == key) return true; + if(_key12 == null) return false; + if(_key12 == key) return true; + if(_key13 == null) return false; + if(_key13 == key) return true; + if(_key14 == null) return false; + if(_key14 == key) return true; + if(_key15 == null) return false; + if(_key15 == key) return true; + if(_key16 == null) return false; + if(_key16 == key) return true; + if(_key17 == null) return false; + if(_key17 == key) return true; + if(_key18 == null) return false; + if(_key18 == key) return true; + if(_key19 == null) return false; + if(_key19 == key) return true; + return false; + } else { + return delegate.containsKey(key); + } + } + + V putIfAbsent(K key, V ifAbsent()) { + if(delegate==null) { + if (_key0 == null) { _key0 = key; _obj0 = ifAbsent(); count++; return _obj0; } + else if (_key0 == key ) { return _obj0; } + else if (_key1 == null) { _key1 = key; _obj1 = ifAbsent(); count++; return _obj1; } + else if (_key1 == key ) { return _obj1; } + else if (_key2 == null) { _key2 = key; _obj2 = ifAbsent(); count++; return _obj2; } + else if (_key2 == key ) { return _obj2; } + else if (_key3 == null) { _key3 = key; _obj3 = ifAbsent(); count++; return _obj3; } + else if (_key3 == key ) { return _obj3; } + else if (_key4 == null) { _key4 = key; _obj4 = ifAbsent(); count++; return _obj4; } + else if (_key4 == key ) { return _obj4; } + else if (_key5 == null) { _key5 = key; _obj5 = ifAbsent(); count++; return _obj5; } + else if (_key5 == key ) { return _obj5; } + else if (_key6 == null) { _key6 = key; _obj6 = ifAbsent(); count++; return _obj6;} + else if (_key6 == key ) { return _obj6; } + else if (_key7 == null) { _key7 = key; _obj7 = ifAbsent(); count++; return _obj7; } + else if (_key7 == key ) { return _obj7; } + else if (_key8 == null) { _key8 = key; _obj8 = ifAbsent(); count++; return _obj8; } + else if (_key8 == key ) { return _obj8; } + else if (_key9 == null) { _key9 = key; _obj9 = ifAbsent(); count++; return _obj9; } + else if (_key9 == key ) { return _obj9; } + else if (_key10 == null) { _key10 = key; _obj10 = ifAbsent(); count++; return _obj10; } + else if (_key10 == key ) { return _obj10; } + else if (_key11 == null) { _key11 = key; _obj11 = ifAbsent(); count++; return _obj11; } + else if (_key11 == key ) { return _obj11; } + else if (_key12 == null) { _key12 = key; _obj12 = ifAbsent(); count++; return _obj12; } + else if (_key12 == key ) { return _obj12; } + else if (_key13 == null) { _key13 = key; _obj13 = ifAbsent(); count++; return _obj13; } + else if (_key13 == key ) { return _obj13; } + else if (_key14 == null) { _key14 = key; _obj14 = ifAbsent(); count++; return _obj14; } + else if (_key14 == key ) { return _obj14; } + else if (_key15 == null) { _key15 = key; _obj15 = ifAbsent(); count++; return _obj15; } + else if (_key15 == key ) { return _obj15; } + else if (_key16 == null) { _key16 = key; _obj16 = ifAbsent(); count++; return _obj16; } + else if (_key16 == key ) { return _obj16; } + else if (_key17 == null) { _key17 = key; _obj17 = ifAbsent(); count++; return _obj17; } + else if (_key17 == key ) { return _obj1; } + else if (_key18 == null) { _key18 = key; _obj18 = ifAbsent(); count++; return _obj18; } + else if (_key18 == key ) { return _obj1; } + else if (_key19 == null) { _key19 = key; _obj19 = ifAbsent(); count++; return _obj19; } + else if (_key19 == key ) { return _obj19; } + + } else { + return delegate.putIfAbsent(key, ifAbsent); + } + } + + void addAll(Map other) { + other.forEach((K key, V value) => _put(key, value)); + } + + V remove(Object key) { + if (delegate == null) { + var value = null; + if (_key0 == key) { value = _obj0; _key0 = null; _obj0 = null; } + else if (_key1 == key) { value = _obj1; _key1 = null; _obj1 = null; } + else if (_key2 == key) { value = _obj2; _key2 = null; _obj2 = null; } + else if (_key3 == key) { value = _obj3; _key3 = null; _obj3 = null; } + else if (_key4 == key) { value = _obj4; _key4 = null; _obj4 = null; } + else if (_key5 == key) { value = _obj5; _key5 = null; _obj5 = null; } + else if (_key6 == key) { value = _obj6; _key6 = null; _obj6 = null; } + else if (_key7 == key) { value = _obj7; _key7 = null; _obj7 = null; } + else if (_key8 == key) { value = _obj8; _key8 = null; _obj8 = null; } + else if (_key9 == key) { value = _obj9; _key9 = null; _obj9 = null; } + else if (_key10 == key) { value = _obj10; _key10 = null; _obj10 = null; } + else if (_key11 == key) { value = _obj11; _key11 = null; _obj11 = null; } + else if (_key12 == key) { value = _obj12; _key12 = null; _obj12 = null; } + else if (_key13 == key) { value = _obj13; _key13 = null; _obj13 = null; } + else if (_key14 == key) { value = _obj14; _key14 = null; _obj14 = null; } + else if (_key15 == key) { value = _obj15; _key15 = null; _obj15 = null; } + else if (_key16 == key) { value = _obj16; _key16 = null; _obj16 = null; } + else if (_key17 == key) { value = _obj17; _key17 = null; _obj17 = null; } + else if (_key18 == key) { value = _obj18; _key18 = null; _obj18 = null; } + else if (_key19 == key) { value = _obj19; _key19 = null; _obj19 = null; } + if (value != null) { + count--; + _fillHole(); + } + return value; + } + else { + var value = delegate.remove(key); + if (delegate.length <= _LIST_ELEMENTS) _copyMapToElements(); + return value; + } + } + + void clear() { + _clearAllElements(); + if (delegate != null) delegate = null; + } + + void forEach(void f(K key, V value)) { + if(delegate == null) { + if (count == 0) return; + if(_key0 != null) { f(_key0 , _obj0 ); } + if (count == 1) return; + if(_key1 != null) { f(_key1 , _obj1 ); } + if (count == 2) return; + if(_key2 != null) { f(_key2 , _obj2 ); } + if (count == 3) return; + if(_key3 != null) { f(_key3 , _obj3 ); } + if (count == 4) return; + if(_key4 != null) { f(_key4 , _obj4 ); } + if (count == 5) return; + if(_key5 != null) { f(_key5 , _obj5 ); } + if (count == 6) return; + if(_key6 != null) { f(_key6 , _obj6 ); } + if (count == 7) return; + if(_key7 != null) { f(_key7 , _obj7 ); } + if (count == 8) return; + if(_key8 != null) { f(_key8 , _obj8 ); } + if (count == 9) return; + if(_key9 != null) { f(_key9 , _obj9 ); } + if (count == 10) return; + if(_key10 != null) { f(_key10, _obj10); } + if (count == 11) return; + if(_key11 != null) { f(_key11, _obj11); } + if (count == 12) return; + if(_key12 != null) { f(_key12, _obj12); } + if (count == 13) return; + if(_key13 != null) { f(_key13, _obj13); } + if (count == 14) return; + if(_key14 != null) { f(_key14, _obj14); } + if (count == 15) return; + if(_key15 != null) { f(_key15, _obj15); } + if (count == 16) return; + if(_key16 != null) { f(_key16, _obj16); } + if (count == 17) return; + if(_key17 != null) { f(_key17, _obj17); } + if (count == 18) return; + if(_key18 != null) { f(_key18, _obj18); } + if (count == 19) return; + if(_key19 != null) { f(_key19, _obj19); } + } + else { + delegate.forEach(f); + } + } + + Iterable get keys { + if (delegate != null) return delegate.keys; + return new MicroIterable(_key0, _key1, _key2, _key3, _key4, _key5, _key6, _key7, _key8, _key9, _key10, _key11, _key12, + _key13, _key14, _key15, _key16, _key17, _key18, _key19, length); + } + + Iterable get values { + if (delegate != null) return delegate.values; + List vs = []; + return new MicroIterable(_obj0, _obj1, _obj2, _obj3, _obj4, _obj5, _obj6, _obj7, _obj8, _obj9, _obj0, _obj11, _obj12, + _obj13, _obj14, _obj15, _obj16, _obj17, _obj18, _obj19, length); + } + + int get length { + return delegate == null ? count : delegate.length; + } + + bool get isEmpty { + return count == 0; + } + + bool get isNotEmpty { + return count != 0; + } + + V operator [](K key) { + if (delegate == null) { + if (key == _key0) return _obj0; + if (key == _key1) return _obj1; + if (key == _key2) return _obj2; + if (key == _key3) return _obj3; + if (key == _key4) return _obj4; + if (key == _key5) return _obj5; + if (key == _key6) return _obj6; + if (key == _key7) return _obj7; + if (key == _key8) return _obj8; + if (key == _key9) return _obj9; + if (key == _key10) return _obj10; + if (key == _key11) return _obj11; + if (key == _key12) return _obj12; + if (key == _key13) return _obj13; + if (key == _key14) return _obj14; + if (key == _key15) return _obj15; + if (key == _key16) return _obj16; + if (key == _key17) return _obj17; + if (key == _key18) return _obj18; + if (key == _key19) return _obj19; + } else { + return delegate[key]; + } + return null; + } + + void operator []=(K key, V value) { + if (this[key] == null) count++; + if (_key0 == null || _key0 == key) { _key0 = key; _obj0 = value; } + else if (_key1 == null || _key1 == key) { _key1 = key; _obj1 = value; } + else if (_key2 == null || _key2 == key) { _key2 = key; _obj2 = value; } + else if (_key3 == null || _key3 == key) { _key3 = key; _obj3 = value; } + else if (_key4 == null || _key4 == key) { _key4 = key; _obj4 = value; } + else if (_key5 == null || _key5 == key) { _key5 = key; _obj5 = value; } + else if (_key6 == null || _key6 == key) { _key6 = key; _obj6 = value; } + else if (_key7 == null || _key7 == key) { _key7 = key; _obj7 = value; } + else if (_key8 == null || _key8 == key) { _key8 = key; _obj8 = value; } + else if (_key9 == null || _key9 == key) { _key9 = key; _obj9 = value; } + else if (_key10 == null || _key10 == key) { _key10 = key; _obj10 = value; } + else if (_key11 == null || _key11 == key) { _key11 = key; _obj11 = value; } + else if (_key12 == null || _key12 == key) { _key12 = key; _obj12 = value; } + else if (_key13 == null || _key13 == key) { _key13 = key; _obj13 = value; } + else if (_key14 == null || _key14 == key) { _key14 = key; _obj14 = value; } + else if (_key15 == null || _key15 == key) { _key15 = key; _obj15 = value; } + else if (_key16 == null || _key16 == key) { _key16 = key; _obj16 = value; } + else if (_key17 == null || _key17 == key) { _key17 = key; _obj17 = value; } + else if (_key18 == null || _key18 == key) { _key18 = key; _obj18 = value; } + else if (_key19 == null || _key19 == key) { _key19 = key; _obj19 = value; } + else { + _copyAllElementsToMap(); + if (delegate==null) delegate = new HashMap(); + delegate[key] = value; + } + } + + int get mode { + return delegate == null ? MODE_ARRAY : MODE_MAP; + } + + String toString() { + var elements = []; + if (delegate == null) { + if(_key0 != null) elements.add('${_key0}: ${_obj0}'); + if(_key1 != null) elements.add('${_key1}: ${_obj1}'); + if(_key2 != null) elements.add('${_key2}: ${_obj2}'); + if(_key3 != null) elements.add('${_key3}: ${_obj3}'); + if(_key4 != null) elements.add('${_key4}: ${_obj4}'); + if(_key5 != null) elements.add('${_key5}: ${_obj5}'); + if(_key6 != null) elements.add('${_key6}: ${_obj6}'); + if(_key7 != null) elements.add('${_key7}: ${_obj7}'); + if(_key8 != null) elements.add('${_key8}: ${_obj8}'); + if(_key9 != null) elements.add('${_key9}: ${_obj9}'); + if(_key10 != null) elements.add('${_key10}: ${_obj10}'); + if(_key11 != null) elements.add('${_key11}: ${_obj11}'); + if(_key12 != null) elements.add('${_key12}: ${_obj12}'); + if(_key13 != null) elements.add('${_key13}: ${_obj13}'); + if(_key14 != null) elements.add('${_key14}: ${_obj14}'); + if(_key15 != null) elements.add('${_key15}: ${_obj15}'); + if(_key16 != null) elements.add('${_key16}: ${_obj16}'); + if(_key17 != null) elements.add('${_key17}: ${_obj17}'); + if(_key18 != null) elements.add('${_key18}: ${_obj18}'); + if(_key19 != null) elements.add('${_key19}: ${_obj19}'); + return '{${elements.join(', ')}}'; + } + return '$delegate'; + } + + void _clearAllElements() { + _key0 = null; _obj0 = null; + _key1 = null; _obj1 = null; + _key2 = null; _obj2 = null; + _key3 = null; _obj3 = null; + _key4 = null; _obj4 = null; + _key5 = null; _obj5 = null; + _key6 = null; _obj6 = null; + _key7 = null; _obj7 = null; + _key8 = null; _obj8 = null; + _key9 = null; _obj9 = null; + _key10 = null; _obj10 = null; + _key11 = null; _obj11 = null; + _key12 = null; _obj12 = null; + _key13 = null; _obj13 = null; + _key14 = null; _obj14 = null; + _key15 = null; _obj15 = null; + _key16 = null; _obj16 = null; + _key17 = null; _obj17 = null; + _key18 = null; _obj18 = null; + _key19 = null; _obj19 = null; + } + + void _copyAllElementsToMap() { + var i = 0; + if (delegate==null) delegate = new HashMap(); + delegate[_key0] = _obj0; + delegate[_key1] = _obj1; + delegate[_key2] = _obj2; + delegate[_key3] = _obj3; + delegate[_key4] = _obj4; + delegate[_key5] = _obj5; + delegate[_key6] = _obj6; + delegate[_key7] = _obj7; + delegate[_key8] = _obj8; + delegate[_key9] = _obj9; + delegate[_key10] = _obj10; + delegate[_key11] = _obj11; + delegate[_key12] = _obj12; + delegate[_key13] = _obj13; + delegate[_key14] = _obj14; + delegate[_key15] = _obj15; + delegate[_key16] = _obj16; + delegate[_key17] = _obj17; + delegate[_key18] = _obj18; + delegate[_key19] = _obj19; + _clearAllElements(); + } + + void _copyMapToElements() { + List ks = delegate.keys.toList(); + _key0 = ks[0]; _obj0 = delegate[_key0]; + _key1 = ks[1]; _obj1 = delegate[_key1]; + _key2 = ks[2]; _obj2 = delegate[_key2]; + _key3 = ks[3]; _obj3 = delegate[_key3]; + _key4 = ks[4]; _obj4 = delegate[_key4]; + _key5 = ks[5]; _obj5 = delegate[_key5]; + _key6 = ks[6]; _obj6 = delegate[_key6]; + _key7 = ks[7]; _obj7 = delegate[_key7]; + _key8 = ks[8]; _obj8 = delegate[_key8]; + _key9 = ks[9]; _obj9 = delegate[_key9]; + _key10 = ks[10]; _obj10 = delegate[_key10]; + _key11 = ks[11]; _obj11 = delegate[_key11]; + _key12 = ks[12]; _obj12 = delegate[_key12]; + _key13 = ks[13]; _obj13 = delegate[_key13]; + _key14 = ks[14]; _obj14 = delegate[_key14]; + _key15 = ks[15]; _obj15 = delegate[_key15]; + _key16 = ks[16]; _obj16 = delegate[_key16]; + _key17 = ks[17]; _obj17 = delegate[_key17]; + _key18 = ks[18]; _obj18 = delegate[_key18]; + _key19 = ks[19]; _obj19 = delegate[_key19]; + count = _LIST_ELEMENTS; + delegate = null; + } + + void _fillHole() { + var lastKey, lastObj; + // find the last element which is not null and remove it + if (_key19 != null) { lastKey = _key19; lastObj = _obj19; } + else if (_key18 != null) { lastKey = _key18; lastObj = _obj18; _key18 = null; _obj18 = null; } + else if (_key17 != null) { lastKey = _key17; lastObj = _obj17; _key17 = null; _obj17 = null; } + else if (_key16 != null) { lastKey = _key16; lastObj = _obj16; _key16 = null; _obj16 = null; } + else if (_key15 != null) { lastKey = _key15; lastObj = _obj15; _key15 = null; _obj15 = null; } + else if (_key14 != null) { lastKey = _key14; lastObj = _obj14; _key14 = null; _obj14 = null; } + else if (_key13 != null) { lastKey = _key13; lastObj = _obj13; _key13 = null; _obj13 = null; } + else if (_key12 != null) { lastKey = _key12; lastObj = _obj12; _key12 = null; _obj12 = null; } + else if (_key11 != null) { lastKey = _key11; lastObj = _obj11; _key11 = null; _obj11 = null; } + else if (_key10 != null) { lastKey = _key10; lastObj = _obj10; _key10 = null; _obj10 = null; } + else if (_key9 != null) { lastKey = _key9 ; lastObj = _obj9 ; _key9 = null; _obj9 = null; } + else if (_key8 != null) { lastKey = _key8 ; lastObj = _obj8 ; _key8 = null; _obj8 = null; } + else if (_key7 != null) { lastKey = _key7 ; lastObj = _obj7 ; _key7 = null; _obj7 = null; } + else if (_key6 != null) { lastKey = _key6 ; lastObj = _obj6 ; _key6 = null; _obj6 = null; } + else if (_key5 != null) { lastKey = _key5 ; lastObj = _obj5 ; _key5 = null; _obj5 = null; } + else if (_key4 != null) { lastKey = _key4 ; lastObj = _obj4 ; _key4 = null; _obj4 = null; } + else if (_key3 != null) { lastKey = _key3 ; lastObj = _obj3 ; _key3 = null; _obj3 = null; } + else if (_key2 != null) { lastKey = _key2 ; lastObj = _obj2 ; _key2 = null; _obj2 = null; } + else if (_key1 != null) { lastKey = _key1 ; lastObj = _obj1 ; _key1 = null; _obj1 = null; } + else if (_key0 != null) { lastKey = _key0 ; lastObj = _obj0 ; _key0 = null; _obj0 = null; } + if (lastKey != null) { + // fill in first element which is null + if(_key0 == null) { _key0 = lastKey; _obj0 = lastObj; } + else if(_key1 == null) { _key1 = lastKey; _obj1 = lastObj; } + else if(_key2 == null) { _key2 = lastKey; _obj2 = lastObj; } + else if(_key3 == null) { _key3 = lastKey; _obj3 = lastObj; } + else if(_key4 == null) { _key4 = lastKey; _obj4 = lastObj; } + else if(_key5 == null) { _key5 = lastKey; _obj5 = lastObj; } + else if(_key6 == null) { _key6 = lastKey; _obj6 = lastObj; } + else if(_key7 == null) { _key7 = lastKey; _obj7 = lastObj; } + else if(_key8 == null) { _key8 = lastKey; _obj8 = lastObj; } + else if(_key9 == null) { _key9 = lastKey; _obj9 = lastObj; } + else if(_key10 == null) { _key10 = lastKey; _obj10 = lastObj; } + else if(_key11 == null) { _key11 = lastKey; _obj11 = lastObj; } + else if(_key12 == null) { _key12 = lastKey; _obj12 = lastObj; } + else if(_key13 == null) { _key13 = lastKey; _obj13 = lastObj; } + else if(_key14 == null) { _key14 = lastKey; _obj14 = lastObj; } + else if(_key15 == null) { _key15 = lastKey; _obj15 = lastObj; } + else if(_key16 == null) { _key16 = lastKey; _obj16 = lastObj; } + else if(_key17 == null) { _key17 = lastKey; _obj17 = lastObj; } + else if(_key18 == null) { _key18 = lastKey; _obj18 = lastObj; } + else if(_key18 == null) { _key18 = lastKey; _obj18 = lastObj; } + } + } + + V _put(K key, V value) { + if (count >= _LIST_ELEMENTS) { + _copyAllElementsToMap(); + return delegate[key] = value; + } else { + this[key] = value; + return value; + } + } +} \ No newline at end of file diff --git a/test/collection/micro_iterable_spec.dart b/test/collection/micro_iterable_spec.dart new file mode 100644 index 000000000..23427b71d --- /dev/null +++ b/test/collection/micro_iterable_spec.dart @@ -0,0 +1,73 @@ +library micro_iterable_spec; + +import '../_specs.dart'; +import 'package:angular/collection/micro_iterable.dart'; + +void main() { + describe('MicroIterable', () { + MicroIterable iterable; + + beforeEach(() { + iterable = new MicroIterable(1,2,3,4,5,6,7,8,null, null, null, null, null, null, null, null, null, null, null, null, 8); + }); + + it('should have length', () { + expect(iterable.length).toBe(8); + }); + + it('should not be empty', () { + expect(iterable.isNotEmpty).toBe(true); + }); + + it('should be able to get a list', () { + var list = iterable.toList(); + expect(list).toEqual([1,2,3,4,5,6,7,8]); + expect(() { + list.add('foo'); + }).not.toThrow(); + }); + + it('should be able to get a fixed size list', () { + var list = iterable.toList(growable: false); + expect(list).toEqual([1,2,3,4,5,6,7,8]); + expect(() { + list.add('foo'); + }).toThrow(); + }); + + it('should take specified number of elements', () { + expect(iterable.take(4)).toEqual([1,2,3,4]); + }); + + it('should join elements', () { + expect(iterable.join(", ")).toEqual("1, 2, 3, 4, 5, 6, 7, 8"); + }); + + it('should work with methods provided by IterableMixin', () { + expect(iterable.takeWhile((value) => value < 6)).toEqual([1,2,3,4,5]); + }); + + it('should iterate correctly', () { + Iterator iter = iterable.iterator; + expect(iter.current).toBe(null); + expect(iter.moveNext()).toBe(true); + expect(iter.current).toBe(1); + expect(iter.moveNext()).toBe(true); + expect(iter.current).toBe(2); + expect(iter.moveNext()).toBe(true); + expect(iter.current).toBe(3); + expect(iter.moveNext()).toBe(true); + expect(iter.current).toBe(4); + expect(iter.moveNext()).toBe(true); + expect(iter.current).toBe(5); + expect(iter.moveNext()).toBe(true); + expect(iter.current).toBe(6); + expect(iter.moveNext()).toBe(true); + expect(iter.current).toBe(7); + expect(iter.moveNext()).toBe(true); + expect(iter.current).toBe(8); + expect(iter.moveNext()).toBe(false); + expect(iter.current).toBe(null); + }); + }); +} \ No newline at end of file diff --git a/test/collection/micro_map_spec.dart b/test/collection/micro_map_spec.dart new file mode 100644 index 000000000..71d79e976 --- /dev/null +++ b/test/collection/micro_map_spec.dart @@ -0,0 +1,198 @@ +library micro_map_spec; + +import '../_specs.dart'; +import 'package:angular/collection/micro_map.dart'; + +void main() { + insert(Map map, int start, int end) { + List alphabet = ['0', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', + 't', 'u', 'v', 'w', 'x', 'y', 'z']; + for(var i=start; i<=end; i++) map[i] = alphabet[i]; + } + describe('MicroMap', () { + it('should behave as a map', () { + MicroMap map = new MicroMap(); + map[1] = 'a'; + expect(map.length).toBe(1); + expect(map.toString()).toEqual('{1: a}'); + expect(map.mode).toEqual(MODE_ARRAY); + + map[2] = 'b'; + expect(map.length).toBe(2); + expect(map.toString()).toEqual('{1: a, 2: b}'); + expect(map.mode).toEqual(MODE_ARRAY); + + map[3] = 'c'; + expect(map.length).toBe(3); + expect(map.toString()).toEqual('{1: a, 2: b, 3: c}'); + expect(map.mode).toEqual(MODE_ARRAY); + + insert(map, 4, 21); + expect(map.length).toBe(21); + expect(map).toEqual({1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e', 6: 'f', 7: 'g', 8: 'h', 9: 'i', 10: 'j', 11: 'k', + 12: 'l', 13: 'm', 14: 'n', 15: 'o', 16: 'p', 17: 'q', 18: 'r', 19: 's', 20: 't', 21: 'u'}); + expect(map.mode).toEqual(MODE_MAP); + + map.remove(21); + expect(map.length).toBe(20); + expect(map.toString()).toEqual('{1: a, 2: b, 3: c, 4: d, 5: e, 6: f, 7: g, 8: h, 9: i, 10: j, 11: k,' + ' 12: l, 13: m, 14: n, 15: o, 16: p, 17: q, 18: r, 19: s, 20: t}'); + expect(map.mode).toEqual(MODE_ARRAY); + + map.remove(20); + map.remove(19); + map.remove(18); + map.remove(17); + map.remove(16); + expect(map.length).toBe(15); + expect(map.toString()).toEqual('{1: a, 2: b, 3: c, 4: d, 5: e, 6: f, 7: g, 8: h, 9: i, 10: j, 11: k,' + ' 12: l, 13: m, 14: n, 15: o}'); + expect(map.mode).toEqual(MODE_ARRAY); + }); + + describe('mode', () { + MicroMap map = new MicroMap(); + + beforeEach(() { + insert(map, 1, 20); + }); + + it('should switch to map mode', () { + map[21] = '21'; + expect(map.mode).toBe(MODE_MAP); + }); + + it('should switch back to array mode', () { + map[21] = '21'; + expect(map.mode).toBe(MODE_MAP); + + var removed = map.remove(14); + expect(removed).toEqual('n'); + expect(map.mode).toBe(MODE_ARRAY); + }); + }); + + describe('add elements', () { + MicroMap map; + + beforeEach(() { + map = new MicroMap(); + map[1] = '1'; + }); + + afterEach(() { + map = null; + }); + + it('should add element using bracket notation', () { + map[2] = 'nd'; + expect(map.length).toBe(2); + expect(map[2]).toEqual('nd'); + }); + + it('should add element which does not exist when using putIfAbsent', () { + map.putIfAbsent(2, () => 'second'); + expect(map.length).toBe(2); + expect(map[2]).toEqual('second'); + expect(map.mode).toBe(MODE_ARRAY); + }); + + it('should not add element which already exists when using putIfAbsent', () { + map.putIfAbsent(1, () => 'foo'); + expect(map[1]).toEqual('1'); + map[2] = '2'; + map[3] = '3'; + map.putIfAbsent(3, () => 'foo'); + expect(map[3]).toBe('3'); + }); + + it('should overwrite existing value', () { + map[1] = 'foo'; + expect(map.length).toBe(1); + expect(map.mode).toBe(MODE_ARRAY); + }); + }); + + describe('add all elements', () { + MicroMap map; + + beforeEach(() { + map = new MicroMap(); + }); + + it('should add all elements', () { + Map other = {1 : 'first', 2: 'second', 3: 'third'}; + map.addAll(other); + expect(map.length).toBe(3); + expect(map[1]).toBe('first'); + expect(map[2]).toBe('second'); + expect(map[3]).toBe('third'); + expect(map.mode).toBe(MODE_ARRAY); + }); + + it('should add all elements', () { + Map other = {1 : 'first', 2: 'second', 3: 'third', 4:'fourth', 5:'fifth'}; + map.addAll(other); + expect(map.length).toBe(5); + expect(map[1]).toBe('first'); + expect(map[2]).toBe('second'); + expect(map[3]).toBe('third'); + expect(map[4]).toBe('fourth'); + expect(map[5]).toBe('fifth'); + expect(map.mode).toBe(MODE_ARRAY); + }); + + it('should add to existing elements', () { + insert(map, 1, 18); + Map other = {19: '19', 20: '20'}; + map.addAll(other); + expect(map.length).toBe(20); + expect(map.mode).toBe(MODE_ARRAY); + }); + + it('should add to existing elements', () { + insert(map, 1, 18); + Map other = {19: '19', 20: '20', 21: '21'}; + map.addAll(other); + expect(map.length).toBe(21); + expect(map.mode).toBe(MODE_MAP); + }); + + it('should overwrite elements with same key', () { + map[1] = 'first'; + map[2] = 'second'; + Map other = {1: 'foo', 3:'bar', 4:'baz'}; + map.addAll(other); + expect(map.length).toBe(4); + expect(map[1]).toBe('foo'); + expect(map[2]).toBe('second'); + expect(map[3]).toBe('bar'); + expect(map[4]).toBe('baz'); + expect(map.mode).toBe(MODE_ARRAY); + }); + }); + + describe('clear', () { + it('should be in fast mode (array) after clearing', () { + MicroMap map = new MicroMap(); + insert(map, 0, 25); + map.clear(); + expect(map.mode).toBe(MODE_ARRAY); + }); + + it('should be in fast mode (array) after clearing', () { + MicroMap map = new MicroMap(); + insert(map, 0, 15); + map.clear(); + expect(map.mode).toBe(MODE_ARRAY); + }); + }); + + describe('remove', () { + it('should return null when removing element which does not exist', () { + MicroMap map = new MicroMap(); + expect(map.remove(1)).toBeNull(); + }); + }); + }); +} \ No newline at end of file