| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012, 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 | |
| 6 /** | |
| 7 * An entry in a doubly linked list. It contains a pointer to the next | |
| 8 * entry, the previous entry, and the boxed element. | |
| 9 */ | |
| 10 class DoubleLinkedQueueEntry<E> { | |
| 11 DoubleLinkedQueueEntry<E> _previous; | |
| 12 DoubleLinkedQueueEntry<E> _next; | |
| 13 E _element; | |
| 14 | |
| 15 DoubleLinkedQueueEntry(E e) { | |
| 16 _element = e; | |
| 17 } | |
| 18 | |
| 19 void _link(DoubleLinkedQueueEntry<E> p, | |
| 20 DoubleLinkedQueueEntry<E> n) { | |
| 21 _next = n; | |
| 22 _previous = p; | |
| 23 p._next = this; | |
| 24 n._previous = this; | |
| 25 } | |
| 26 | |
| 27 void append(E e) { | |
| 28 new DoubleLinkedQueueEntry<E>(e)._link(this, _next); | |
| 29 } | |
| 30 | |
| 31 void prepend(E e) { | |
| 32 new DoubleLinkedQueueEntry<E>(e)._link(_previous, this); | |
| 33 } | |
| 34 | |
| 35 E remove() { | |
| 36 _previous._next = _next; | |
| 37 _next._previous = _previous; | |
| 38 _next = null; | |
| 39 _previous = null; | |
| 40 return _element; | |
| 41 } | |
| 42 | |
| 43 DoubleLinkedQueueEntry<E> _asNonSentinelEntry() { | |
| 44 return this; | |
| 45 } | |
| 46 | |
| 47 DoubleLinkedQueueEntry<E> previousEntry() { | |
| 48 return _previous._asNonSentinelEntry(); | |
| 49 } | |
| 50 | |
| 51 DoubleLinkedQueueEntry<E> nextEntry() { | |
| 52 return _next._asNonSentinelEntry(); | |
| 53 } | |
| 54 | |
| 55 E get element() { | |
| 56 return _element; | |
| 57 } | |
| 58 | |
| 59 void set element(E e) { | |
| 60 _element = e; | |
| 61 } | |
| 62 } | |
| 63 | |
| 64 /** | |
| 65 * A sentinel in a double linked list is used to manipulate the list | |
| 66 * at both ends. A double linked list has exactly one sentinel, which | |
| 67 * is the only entry when the list is constructed. Initially, a | |
| 68 * sentinel has its next and previous entry point to itself. A | |
| 69 * sentinel does not box any user element. | |
| 70 */ | |
| 71 class _DoubleLinkedQueueEntrySentinel<E> extends DoubleLinkedQueueEntry<E> { | |
| 72 _DoubleLinkedQueueEntrySentinel() : super(null) { | |
| 73 _link(this, this); | |
| 74 } | |
| 75 | |
| 76 E remove() { | |
| 77 throw const EmptyQueueException(); | |
| 78 } | |
| 79 | |
| 80 DoubleLinkedQueueEntry<E> _asNonSentinelEntry() { | |
| 81 return null; | |
| 82 } | |
| 83 | |
| 84 void set element(E e) { | |
| 85 // This setter is unreachable. | |
| 86 assert(false); | |
| 87 } | |
| 88 | |
| 89 E get element() { | |
| 90 throw const EmptyQueueException(); | |
| 91 } | |
| 92 } | |
| 93 | |
| 94 /** | |
| 95 * Implementation of a double linked list that box list elements into | |
| 96 * DoubleLinkedQueueEntry objects. | |
| 97 */ | |
| 98 class DoubleLinkedQueue<E> implements Queue<E> { | |
| 99 _DoubleLinkedQueueEntrySentinel<E> _sentinel; | |
| 100 | |
| 101 DoubleLinkedQueue() { | |
| 102 _sentinel = new _DoubleLinkedQueueEntrySentinel<E>(); | |
| 103 } | |
| 104 | |
| 105 factory DoubleLinkedQueue.from(Iterable<E> other) { | |
| 106 Queue<E> list = new DoubleLinkedQueue(); | |
| 107 for (final e in other) { | |
| 108 list.addLast(e); | |
| 109 } | |
| 110 return list; | |
| 111 } | |
| 112 | |
| 113 void addLast(E value) { | |
| 114 _sentinel.prepend(value); | |
| 115 } | |
| 116 | |
| 117 void addFirst(E value) { | |
| 118 _sentinel.append(value); | |
| 119 } | |
| 120 | |
| 121 void add(E value) { | |
| 122 addLast(value); | |
| 123 } | |
| 124 | |
| 125 void addAll(Collection<E> collection) { | |
| 126 for (final e in collection) { | |
| 127 add(e); | |
| 128 } | |
| 129 } | |
| 130 | |
| 131 E removeLast() { | |
| 132 return _sentinel._previous.remove(); | |
| 133 } | |
| 134 | |
| 135 E removeFirst() { | |
| 136 return _sentinel._next.remove(); | |
| 137 } | |
| 138 | |
| 139 E first() { | |
| 140 return _sentinel._next.element; | |
| 141 } | |
| 142 | |
| 143 E last() { | |
| 144 return _sentinel._previous.element; | |
| 145 } | |
| 146 | |
| 147 DoubleLinkedQueueEntry<E> lastEntry() { | |
| 148 return _sentinel.previousEntry(); | |
| 149 } | |
| 150 | |
| 151 DoubleLinkedQueueEntry<E> firstEntry() { | |
| 152 return _sentinel.nextEntry(); | |
| 153 } | |
| 154 | |
| 155 int get length() { | |
| 156 int counter = 0; | |
| 157 forEach(void _(E element) { counter++; }); | |
| 158 return counter; | |
| 159 } | |
| 160 | |
| 161 bool isEmpty() { | |
| 162 return (_sentinel._next === _sentinel); | |
| 163 } | |
| 164 | |
| 165 void clear() { | |
| 166 _sentinel._next = _sentinel; | |
| 167 _sentinel._previous = _sentinel; | |
| 168 } | |
| 169 | |
| 170 void forEach(void f(E element)) { | |
| 171 DoubleLinkedQueueEntry<E> entry = _sentinel._next; | |
| 172 while (entry !== _sentinel) { | |
| 173 DoubleLinkedQueueEntry<E> nextEntry = entry._next; | |
| 174 f(entry._element); | |
| 175 entry = nextEntry; | |
| 176 } | |
| 177 } | |
| 178 | |
| 179 void forEachEntry(void f(DoubleLinkedQueueEntry<E> element)) { | |
| 180 DoubleLinkedQueueEntry<E> entry = _sentinel._next; | |
| 181 while (entry !== _sentinel) { | |
| 182 DoubleLinkedQueueEntry<E> nextEntry = entry._next; | |
| 183 f(entry); | |
| 184 entry = nextEntry; | |
| 185 } | |
| 186 } | |
| 187 | |
| 188 bool every(bool f(E element)) { | |
| 189 DoubleLinkedQueueEntry<E> entry = _sentinel._next; | |
| 190 while (entry !== _sentinel) { | |
| 191 DoubleLinkedQueueEntry<E> nextEntry = entry._next; | |
| 192 if (!f(entry._element)) return false; | |
| 193 entry = nextEntry; | |
| 194 } | |
| 195 return true; | |
| 196 } | |
| 197 | |
| 198 bool some(bool f(E element)) { | |
| 199 DoubleLinkedQueueEntry<E> entry = _sentinel._next; | |
| 200 while (entry !== _sentinel) { | |
| 201 DoubleLinkedQueueEntry<E> nextEntry = entry._next; | |
| 202 if (f(entry._element)) return true; | |
| 203 entry = nextEntry; | |
| 204 } | |
| 205 return false; | |
| 206 } | |
| 207 | |
| 208 Queue map(f(E element)) { | |
| 209 Queue other = new Queue(); | |
| 210 DoubleLinkedQueueEntry<E> entry = _sentinel._next; | |
| 211 while (entry !== _sentinel) { | |
| 212 DoubleLinkedQueueEntry<E> nextEntry = entry._next; | |
| 213 other.addLast(f(entry._element)); | |
| 214 entry = nextEntry; | |
| 215 } | |
| 216 return other; | |
| 217 } | |
| 218 | |
| 219 Dynamic reduce(Dynamic initialValue, | |
| 220 Dynamic combine(Dynamic previousValue, E element)) { | |
| 221 return Collections.reduce(this, initialValue, combine); | |
| 222 } | |
| 223 | |
| 224 Queue<E> filter(bool f(E element)) { | |
| 225 Queue<E> other = new Queue<E>(); | |
| 226 DoubleLinkedQueueEntry<E> entry = _sentinel._next; | |
| 227 while (entry !== _sentinel) { | |
| 228 DoubleLinkedQueueEntry<E> nextEntry = entry._next; | |
| 229 if (f(entry._element)) other.addLast(entry._element); | |
| 230 entry = nextEntry; | |
| 231 } | |
| 232 return other; | |
| 233 } | |
| 234 | |
| 235 _DoubleLinkedQueueIterator<E> iterator() { | |
| 236 return new _DoubleLinkedQueueIterator<E>(_sentinel); | |
| 237 } | |
| 238 | |
| 239 String toString() { | |
| 240 return Collections.collectionToString(this); | |
| 241 } | |
| 242 } | |
| 243 | |
| 244 class _DoubleLinkedQueueIterator<E> implements Iterator<E> { | |
| 245 final _DoubleLinkedQueueEntrySentinel<E> _sentinel; | |
| 246 DoubleLinkedQueueEntry<E> _currentEntry; | |
| 247 | |
| 248 _DoubleLinkedQueueIterator(_DoubleLinkedQueueEntrySentinel this._sentinel) { | |
| 249 _currentEntry = _sentinel; | |
| 250 } | |
| 251 | |
| 252 bool hasNext() { | |
| 253 return _currentEntry._next !== _sentinel; | |
| 254 } | |
| 255 | |
| 256 E next() { | |
| 257 if (!hasNext()) { | |
| 258 throw const NoMoreElementsException(); | |
| 259 } | |
| 260 _currentEntry = _currentEntry._next; | |
| 261 return _currentEntry.element; | |
| 262 } | |
| 263 } | |
| OLD | NEW |