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

Side by Side Diff: sdk/lib/collection/linked_list.dart

Issue 13459002: Introduce new LinkedList to dart:collection. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Review updates. Created 7 years, 6 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 | Annotate | Revision Log
« no previous file with comments | « sdk/lib/collection/collection_sources.gypi ('k') | tests/lib/collection/linked_list_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 linked list implementation, providing O(1) removal(unlink) of elements and
10 * manual traversal through [next] and [previous].
11 *
12 * The list elements must extend [LinkedListEntry].
13 */
14 class LinkedList<E extends LinkedListEntry<E>>
15 extends IterableBase<E>
16 implements _LinkedListLink {
17 int _modificationCount = 0;
18 int _length = 0;
19 _LinkedListLink _next;
20 _LinkedListLink _previous;
21
22 /**
23 * Construct a new empty linked list.
24 */
25 LinkedList() {
26 _next = _previous = this;
27 }
28
29 /**
30 * Add [entry] to the beginning of the list.
31 */
32 void addFirst(E entry) {
33 _insertAfter(this, entry);
34 }
35
36 /**
37 * Add [entry] to the end of the list.
38 */
39 void add(E entry) {
40 _insertAfter(_previous, entry);
41 }
42
43 /**
44 * Add [entries] to the end of the list.
45 */
46 void addAll(Iterable<E> entries) {
47 entries.forEach((entry) => _insertAfter(_previous, entry));
48 }
49
50 /**
51 * Remove [entry] from the list. This is the same as calling `entry.unlink()`.
52 *
53 * If [entry] is not in the list, `false` is returned.
54 */
55 bool remove(E entry) {
56 if (entry._list != this) return false;
57 _unlink(entry); // Unlink will decrement length.
58 return true;
59 }
60
61 Iterator<E> get iterator => new _LinkedListIterator<E>(this);
62
63 String toString() => ToString.iterableToString(this);
64
65 int get length => _length;
66
67 void clear() {
68 _modificationCount++;
69 _LinkedListLink next = _next;
70 while (!identical(next, this)) {
71 _LinkedListLink entry = next;
72 next = entry._next;
73 entry._next = entry._previous = entry._list = null;
74 }
75 _next = _previous = this;
76 _length = 0;
77 }
78
79 E get first {
80 if (identical(_next, this)) {
81 throw new StateError('No such element');
82 }
83 return _next;
84 }
85
86 E get last {
87 if (identical(_previous, this)) {
88 throw new StateError('No such element');
89 }
90 return _previous;
91 }
92
93 E get single {
94 if (identical(_previous, this)) {
95 throw new StateError('No such element');
96 }
97 if (!identical(_previous, _next)) {
98 throw new StateError('Too many elements');
99 }
100 return _next;
101 }
102
103 /**
104 * Call [action] with each entry in the list.
105 *
106 * It's an error if [action] modify the list.
107 */
108 void forEach(void action(E entry)) {
109 int modificationCount = _modificationCount;
110 _LinkedListLink current = _next;
111 while (!identical(current, this)) {
112 action(current);
113 if (modificationCount != _modificationCount) {
114 throw new ConcurrentModificationError(this);
115 }
116 current = current._next;
117 }
118 }
119
120 bool get isEmpty => _length == 0;
121
122 void _insertAfter(_LinkedListLink entry, E newEntry) {
123 if (newEntry.list != null) {
124 throw new StateError(
125 'LinkedListEntry is already in a LinkedList');
126 }
127 _modificationCount++;
128 newEntry._list = this;
129 var predecessor = entry;
130 var successor = entry._next;
131 successor._previous = newEntry;
132 newEntry._previous = predecessor;
133 newEntry._next = successor;
134 predecessor._next = newEntry;
135 _length++;
136 }
137
138 void _unlink(E entry) {
139 _modificationCount++;
140 entry._next._previous = entry._previous;
141 entry._previous._next = entry._next;
142 _length--;
143 entry._list = entry._next = entry._previous = null;
144 }
145 }
146
147
148 class _LinkedListIterator<E extends LinkedListEntry>
149 implements Iterator<E> {
150 final LinkedList<E> _list;
151 final int _modificationCount;
152 E _current;
153 _LinkedListLink _next;
154
155 _LinkedListIterator(LinkedList<E> list)
156 : _list = list,
157 _modificationCount = list._modificationCount,
158 _next = list._next;
159
160 E get current => _current;
161
162 bool moveNext() {
163 if (identical(_next, _list)) {
164 _current = null;
165 return false;
166 }
167 if (_modificationCount != _list._modificationCount) {
168 throw new ConcurrentModificationError(this);
169 }
170 _current = _next;
171 _next = _next._next;
172 return true;
173 }
174 }
175
176
177 class _LinkedListLink {
178 _LinkedListLink _next;
179 _LinkedListLink _previous;
180 }
181
182
183 /**
184 * Entry element for a [LinkedList]. Any entry must extend this class.
185 */
186 abstract class LinkedListEntry<E> implements _LinkedListLink {
187 LinkedList<E> _list;
188 _LinkedListLink _next;
189 _LinkedListLink _previous;
190
191 /**
192 * Get the list containing this element.
193 */
194 LinkedList<E> get list => _list;
195
196 /**
197 * Unlink the element from the list.
198 */
199 void unlink() {
200 _list._unlink(this);
201 }
202
203 /**
204 * Return the succeeding element in the list.
205 */
206 E get next {
207 if (_next == _list) return null;
208 return _next;
209 }
210
211 /**
212 * Return the preceeding element in the list.
213 */
214 E get previous {
215 if (_previous == _list) return null;
216 return _previous;
217 }
218
219 /**
220 * insert an element after this.
221 */
222 void insertAfter(E entry) {
223 _list._insertAfter(this, entry);
224 }
225
226 /**
227 * Insert an element before this.
228 */
229 void insertBefore(E entry) {
230 _list._insertAfter(_previous, entry);
231 }
232 }
OLDNEW
« no previous file with comments | « sdk/lib/collection/collection_sources.gypi ('k') | tests/lib/collection/linked_list_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698