OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 part of dart._internal; |
| 6 |
| 7 /// A rudimentary linked list. |
| 8 class LinkedList<T extends LinkedListEntry<T>> extends IterableBase<T> { |
| 9 T first; |
| 10 T last; |
| 11 int length = 0; |
| 12 |
| 13 bool get isEmpty => length == 0; |
| 14 |
| 15 /** |
| 16 * Adds [newLast] to the end of this linked list. |
| 17 */ |
| 18 void add(T newLast) { |
| 19 assert(newLast._next == null && newLast._previous == null); |
| 20 if (last != null) { |
| 21 assert(last._next == null); |
| 22 last._next = newLast; |
| 23 } else { |
| 24 first = newLast; |
| 25 } |
| 26 newLast._previous = last; |
| 27 last = newLast; |
| 28 last._list = this; |
| 29 length++; |
| 30 } |
| 31 |
| 32 /** |
| 33 * Adds [newFirst] to the beginning of this linked list. |
| 34 */ |
| 35 void addFirst(T newFirst) { |
| 36 if (first != null) { |
| 37 assert(first._previous == null); |
| 38 first._previous = newFirst; |
| 39 } else { |
| 40 last = newFirst; |
| 41 } |
| 42 newFirst._next = first; |
| 43 first = newFirst; |
| 44 first._list = this; |
| 45 length++; |
| 46 } |
| 47 |
| 48 /** |
| 49 * Removes the given [node] from this list. |
| 50 * |
| 51 * If the entry is not in this linked list nothing happens. |
| 52 * |
| 53 * Also see [LinkedListEntry.unlink]. |
| 54 */ |
| 55 void remove(T node) { |
| 56 if (node._list != this) return; |
| 57 length--; |
| 58 if (node._previous == null) { |
| 59 assert(identical(node, first)); |
| 60 first = node._next; |
| 61 } else { |
| 62 node._previous._next = node._next; |
| 63 } |
| 64 if (node._next == null) { |
| 65 assert(identical(node, last)); |
| 66 last = node._previous; |
| 67 } else { |
| 68 node._next._previous = node._previous; |
| 69 } |
| 70 node._next = node._previous = null; |
| 71 node._list = null; |
| 72 } |
| 73 |
| 74 Iterator<T> get iterator => new _LinkedListIterator<T>(this); |
| 75 } |
| 76 |
| 77 class LinkedListEntry<T extends LinkedListEntry<T>> { |
| 78 T _next; |
| 79 T _previous; |
| 80 LinkedList<T> _list; |
| 81 |
| 82 /** |
| 83 * Unlinks the element from its linked list. |
| 84 * |
| 85 * If the entry is not in a linked list, does nothing. Otherwise, this |
| 86 * is equivalent to calling [LinkedList.remove] on the list this entry |
| 87 * is currently in. |
| 88 */ |
| 89 void unlink() { |
| 90 if (_list == null) return; |
| 91 _list.remove(this); |
| 92 } |
| 93 } |
| 94 |
| 95 class _LinkedListIterator<T extends LinkedListEntry<T>> implements Iterator<T> { |
| 96 /// The current element of the iterator. |
| 97 // This field is writeable, but should only read by users of this class. |
| 98 T current; |
| 99 |
| 100 /// The list the iterator iterates over. |
| 101 /// |
| 102 /// Set to [null] if the provided list was empty (indicating that there were |
| 103 /// no entries to iterate over). |
| 104 /// |
| 105 /// Set to [null] as soon as [moveNext] was invoked (indicating that the |
| 106 /// iterator has to work with [current] from now on. |
| 107 LinkedList<T> _list; |
| 108 |
| 109 _LinkedListIterator(this._list) { |
| 110 if (_list.length == 0) _list = null; |
| 111 } |
| 112 |
| 113 bool moveNext() { |
| 114 // current is null if the iterator hasn't started iterating, or if the |
| 115 // iteration is finished. In the first case, the [_list] field is not null. |
| 116 if (current == null) { |
| 117 if (_list == null) return false; |
| 118 assert(_list.length > 0); |
| 119 current = _list.first; |
| 120 _list = null; |
| 121 return true; |
| 122 } |
| 123 current = current._next; |
| 124 return current != null; |
| 125 } |
| 126 } |
OLD | NEW |