Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(106)

Side by Side Diff: pkg/dev_compiler/tool/input_sdk/lib/collection/linked_list.dart

Issue 2698353003: unfork DDC's copy of most SDK libraries (Closed)
Patch Set: revert core_patch Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2013, 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.collection;
6
7
8 /**
9 * A specialized double-linked list of elements that extends [LinkedListEntry].
10 *
11 * This is not a generic data structure. It only accepts elements that extend
12 * the [LinkedListEntry] class. See the [Queue] implementations for
13 * generic collections that allow constant time adding and removing at the ends.
14 *
15 * This is not a [List] implementation. Despite its name, this class does not
16 * implement the [List] interface. It does not allow constant time lookup by
17 * index.
18 *
19 * Because the elements themselves contain the links of this linked list,
20 * each element can be in only one list at a time. To add an element to another
21 * list, it must first be removed from its current list (if any).
22 *
23 * In return, each element knows its own place in the linked list, as well as
24 * which list it is in. This allows constant time [LinkedListEntry.addAfter],
25 * [LinkedListEntry.addBefore] and [LinkedListEntry.unlink] operations
26 * when all you have is the element.
27 *
28 * A `LinkedList` also allows constant time adding and removing at either end,
29 * and a constant time length getter.
30 */
31 class LinkedList<E extends LinkedListEntry<E>>
32 extends Iterable<E> {
33
34 int _modificationCount = 0;
35 int _length = 0;
36 E _first;
37
38 /**
39 * Construct a new empty linked list.
40 */
41 LinkedList();
42
43 /**
44 * Add [entry] to the beginning of the linked list.
45 */
46 void addFirst(E entry) {
47 _insertBefore(_first, entry, updateFirst: true);
48 _first = entry;
49 }
50
51 /**
52 * Add [entry] to the end of the linked list.
53 */
54 void add(E entry) {
55 _insertBefore(_first, entry, updateFirst: false);
56 }
57
58 /**
59 * Add [entries] to the end of the linked list.
60 */
61 void addAll(Iterable<E> entries) {
62 entries.forEach(add);
63 }
64
65 /**
66 * Remove [entry] from the linked list.
67 *
68 * Returns false and does nothing if [entry] is not in this linked list.
69 *
70 * This is equivalent to calling `entry.unlink()` if the entry is in this
71 * list.
72 */
73 bool remove(E entry) {
74 if (entry._list != this) return false;
75 _unlink(entry); // Unlink will decrement length.
76 return true;
77 }
78
79 Iterator<E> get iterator => new _LinkedListIterator<E>(this);
80
81 int get length => _length;
82
83 /**
84 * Remove all elements from this linked list.
85 */
86 void clear() {
87 _modificationCount++;
88 if (isEmpty) return;
89
90 E next = _first;
91 do {
92 E entry = next;
93 next = entry._next;
94 entry._next = entry._previous = entry._list = null;
95 } while (!identical(next, _first));
96
97 _first = null;
98 _length = 0;
99 }
100
101 E get first {
102 if (isEmpty) {
103 throw new StateError('No such element');
104 }
105 return _first;
106 }
107
108 E get last {
109 if (isEmpty) {
110 throw new StateError('No such element');
111 }
112 return _first._previous;
113 }
114
115 E get single {
116 if (isEmpty) {
117 throw new StateError('No such element');
118 }
119 if (_length > 1) {
120 throw new StateError('Too many elements');
121 }
122 return _first;
123 }
124
125 /**
126 * Call [action] with each entry in this linked list.
127 *
128 * It's an error if [action] modify the linked list.
129 */
130 void forEach(void action(E entry)) {
131 int modificationCount = _modificationCount;
132 if (isEmpty) return;
133
134 E current = _first;
135 do {
136 action(current);
137 if (modificationCount != _modificationCount) {
138 throw new ConcurrentModificationError(this);
139 }
140 current = current._next;
141 } while (!identical(current, _first));
142 }
143
144 bool get isEmpty => _length == 0;
145
146 /// Inserts [newEntry] as last entry of the list.
147 ///
148 /// If [updateFirst] is true and [entry] is the first entry in the list,
149 /// updates the [_first] field to point to the [newEntry] as first entry.
150 void _insertBefore(E entry, E newEntry, {bool updateFirst}) {
151 if (newEntry.list != null) {
152 throw new StateError(
153 'LinkedListEntry is already in a LinkedList');
154 }
155 _modificationCount++;
156
157 newEntry._list = this;
158 if (isEmpty) {
159 assert(entry == null);
160 newEntry._previous = newEntry._next = newEntry;
161 _first = newEntry;
162 _length++;
163 return;
164 }
165 E predecessor = entry._previous;
166 E successor = entry;
167 newEntry._previous = predecessor;
168 newEntry._next = successor;
169 predecessor._next = newEntry;
170 successor._previous = newEntry;
171 if (updateFirst && identical(entry, _first)) {
172 _first = newEntry;
173 }
174 _length++;
175 }
176
177 void _unlink(E entry) {
178 _modificationCount++;
179 entry._next._previous = entry._previous;
180 E next = entry._previous._next = entry._next;
181 _length--;
182 entry._list = entry._next = entry._previous = null;
183 if (isEmpty) {
184 _first = null;
185 } else if (identical(entry, _first)) {
186 _first = next;
187 }
188 }
189 }
190
191
192 class _LinkedListIterator<E extends LinkedListEntry<E>>
193 implements Iterator<E> {
194 final LinkedList<E> _list;
195 final int _modificationCount;
196 E _current;
197 LinkedListEntry<E> _next;
198 bool _visitedFirst;
199
200 _LinkedListIterator(LinkedList<E> list)
201 : _list = list,
202 _modificationCount = list._modificationCount,
203 _next = list._first,
204 _visitedFirst = false;
205
206 E get current => _current;
207
208 bool moveNext() {
209 if (_modificationCount != _list._modificationCount) {
210 throw new ConcurrentModificationError(this);
211 }
212 if (_list.isEmpty ||
213 (_visitedFirst && identical(_next, _list.first))) {
214 _current = null;
215 return false;
216 }
217 _visitedFirst = true;
218 _current = _next;
219 _next = _next._next;
220 return true;
221 }
222 }
223
224
225 /**
226 * An object that can be an element in a [LinkedList].
227 *
228 * All elements of a `LinkedList` must extend this class.
229 * The class provides the internal links that link elements together
230 * in the `LinkedList`, and a reference to the linked list itself
231 * that an element is currently part of.
232 *
233 * An entry can be in at most one linked list at a time.
234 * While an entry is in a linked list, the [list] property points to that
235 * linked list, and otherwise the `list` property is `null`.
236 *
237 * When created, an entry is not in any linked list.
238 */
239 abstract class LinkedListEntry<E extends LinkedListEntry<E>> {
240 LinkedList<E> _list;
241 E _next;
242 E _previous;
243
244 /**
245 * Get the linked list containing this element.
246 *
247 * Returns `null` if this entry is not currently in any list.
248 */
249 LinkedList<E> get list => _list;
250
251 /**
252 * Unlink the element from its linked list.
253 *
254 * The entry must currently be in a linked list when this method is called.
255 */
256 void unlink() {
257 _list._unlink(this);
258 }
259
260 /**
261 * Return the succeessor of this element in its linked list.
262 *
263 * Returns `null` if there is no successor in the linked list, or if this
264 * entry is not currently in any list.
265 */
266 E get next {
267 if (identical(this, _next)) return null;
268 return _next;
269 }
270
271 /**
272 * Return the predecessor of this element in its linked list.
273 *
274 * Returns `null` if there is no predecessor in the linked list, or if this
275 * entry is not currently in any list.
276 */
277 E get previous {
278 if (identical(this, _previous)) return null;
279 return _previous;
280 }
281
282 /**
283 * Insert an element after this element in this element's linked list.
284 *
285 * This entry must be in a linked list when this method is called.
286 * The [entry] must not be in a linked list.
287 */
288 void insertAfter(E entry) {
289 _list._insertBefore(_next, entry, updateFirst: false);
290 }
291
292 /**
293 * Insert an element before this element in this element's linked list.
294 *
295 * This entry must be in a linked list when this method is called.
296 * The [entry] must not be in a linked list.
297 */
298 void insertBefore(E entry) {
299 _list._insertBefore(this as dynamic/*=E*/, entry, updateFirst: true);
300 }
301 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698