library facade.collection; import 'dart:collection' show IterableBase; import 'dart:convert' show JsonEncoder; export 'dart:core' show Iterator, Map, List, Set; import 'dart:math' show max, min; var jsonEncoder = new JsonEncoder(); class MapIterator extends Iterator { final Iterator _iterator; final Map _map; MapIterator(Map map) : _map = map, _iterator = map.keys.iterator; bool moveNext() => _iterator.moveNext(); List get current { return _iterator.current != null ? [_iterator.current, _map[_iterator.current]] : null; } } class IterableMap extends IterableBase { final Map _map; IterableMap(Map map) : _map = map; Iterator get iterator => new MapIterator(_map); } class MapWrapper { static Map/**/ clone/**/(Map/**/ m) => new Map.from(m); // in opposite to JS, Dart does not create a new map static Map/**/ createFromStringMap/**/(Map/**/ m) => m; // in opposite to JS, Dart does not create a new map static Map/**/ toStringMap/**/(Map/**/ m) => m; static Map/**/ createFromPairs/**/(List pairs) => pairs.fold(/**/{}, (m, p) { m[p[0]] = p[1]; return m; }); static void clearValues(Map m) { for (var k in m.keys) { m[k] = null; } } static Iterable/*>*/ iterable/**/(Map/**/ m) => new IterableMap(m); static List/**/ keys/**/(Map/**/ m) => m.keys.toList(); static List/**/ values/**/(Map/**/ m) => m.values.toList(); } class StringMapWrapper { static Map/**/ create/**/() => {}; static bool contains/**/(Map/**/ map, String key) => map.containsKey(key); static get/**/(Map/**/ map, String key) => map[key]; static void set/**/(Map/**/ map, String key, /*=V*/value) { map[key] = value; } static void delete/**/(Map/**/ m, String k) { m.remove(k); } static void forEach/**/(Map/**/ m, fn(/*=V*/ v, String k)) { m.forEach((k, v) => fn(v, k)); } static Map/**/ merge/**/(Map/**/ a, Map/**/ b) { var m = new Map/**/.from(a); if (b != null) { b.forEach((k, v) => m[k] = v); } return m; } static List keys(Map a) { return a.keys.toList(); } static List values(Map a) { return a.values.toList(); } static bool isEmpty(Map m) => m.isEmpty; static bool equals/**/(Map/**/ m1, Map/**/ m2) { if (m1.length != m2.length) { return false; } for (var key in m1.keys) { if (m1[key] != m2[key]) { return false; } } return true; } } typedef bool Predicate(T item); class ListWrapper { static List/**/ clone/**/(Iterable/**/ l) => new List.from(l); static List/**/ createFixedSize/**/(int size) => new List(size); static List/**/ createGrowableSize/**/(int size) => new List.generate(size, (_) => null, growable: true); static bool contains(List m, k) => m.contains(k); static int indexOf(List list, value, [int startIndex = 0]) => list.indexOf(value, startIndex); static int lastIndexOf(List list, value, [int startIndex = null]) => list.lastIndexOf(value, startIndex == null ? list.length : startIndex); static void forEachWithIndex/**/(List/**/ list, fn(/*=T*/ item, int index)) { for (var i = 0; i < list.length; ++i) { fn(list[i], i); } } static /*=T*/ first/**/(List/**/ list) => list.isEmpty ? null : list.first; static /*=T*/ last/**/(List/**/ list) => list.isEmpty ? null : list.last; static List/**/ reversed/**/(List/**/ list) => list.reversed.toList(); static List/**/ concat/**/(List/**/ a, List/**/ b) { return new List() ..length = a.length + b.length ..setRange(0, a.length, a) ..setRange(a.length, a.length + b.length, b); } static void insert/**/(List/**/ l, int index, /*=T*/ value) { l.insert(index, value); } static removeAt(List l, int index) => l.removeAt(index); static void removeAll/**/(List/**/ list, List/**/ items) { for (var i = 0; i < items.length; ++i) { list.remove(items[i]); } } static bool remove/**/(List/**/ list, /*=T*/ item) => list.remove(item); static void clear(List l) { l.clear(); } static bool isEmpty(Iterable list) => list.isEmpty; static void fill/**/(List/**/ l, /*=T*/ value, [int start = 0, int end]) { l.fillRange(_startOffset(l, start), _endOffset(l, end), value); } static bool equals/**/(List/**/ a, List/**/ b) { if (a.length != b.length) return false; for (var i = 0; i < a.length; ++i) { if (a[i] != b[i]) return false; } return true; } static List/**/ slice/**/(List/**/ l, [int from = 0, int to]) { from = _startOffset(l, from); to = _endOffset(l, to); //in JS if from > to an empty array is returned if (to != null && from > to) { return []; } return l.sublist(from, to); } static List/**/ splice/**/(List/**/ l, int from, int length) { from = _startOffset(l, from); var to = from + length; var sub = l.sublist(from, to); l.removeRange(from, to); return sub; } static void sort/**/(List/**/ l, [int compareFn(/*=T*/a, /*=T*/b) = null]) { if (compareFn == null) { l.sort(); } else { l.sort(compareFn); } } static String toJSON(List l) { return jsonEncoder.convert(l); } // JS splice, slice, fill functions can take start < 0 which indicates a position relative to // the end of the list static int _startOffset(List l, int start) { int len = l.length; return start < 0 ? max(len + start, 0) : min(start, len); } // JS splice, slice, fill functions can take end < 0 which indicates a position relative to // the end of the list static int _endOffset(List l, int end) { int len = l.length; if (end == null) return len; return end < 0 ? max(len + end, 0) : min(end, len); } static maximum(List l, fn(item)) { if (l.length == 0) { return null; } var solution = null; var maxValue = double.NEGATIVE_INFINITY; for (var index = 0; index < l.length; index++) { var candidate = l[index]; if (candidate == null) { continue; } var candidateValue = fn(candidate); if (candidateValue > maxValue) { solution = candidate; maxValue = candidateValue; } } return solution; } static List flatten(List l) { var target = []; _flattenArray(l, target); return target; } static addAll(List l, List source) { l.addAll(source); } } List _flattenArray(List source, List target) { if (source != null) { for (var i = 0; i < source.length; i++) { var item = source[i]; if (item is List) { _flattenArray(item, target); } else { target.add(item); } } } return target; } bool isListLikeIterable(obj) => obj is Iterable; bool areIterablesEqual/**/( Iterable/**/ a, Iterable/**/ b, bool comparator(/*=T*/a, /*=T*/b)) { var iterator1 = a.iterator; var iterator2 = b.iterator; while (true) { var done1 = !iterator1.moveNext(); var done2 = !iterator2.moveNext(); if (done1 && done2) return true; if (done1 || done2) return false; if (!comparator(iterator1.current, iterator2.current)) return false; } } void iterateListLike/**/(Iterable/**/ iter, fn(/*=T*/item)) { assert(iter is Iterable); for (var item in iter) { fn(item); } } class SetWrapper { static Set/**/ createFromList/**/(List/**/ l) => new Set.from(l); static bool has/**/(Set/**/ s, /*=T*/key) => s.contains(key); static void delete/**/(Set/**/ m, /*=T*/k) { m.remove(k); } }