-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathlist.dart
More file actions
178 lines (151 loc) · 3.8 KB
/
Copy pathlist.dart
File metadata and controls
178 lines (151 loc) · 3.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
library md5.list;
/// a always sorted linked list
class MList<E extends MEntry> extends Iterable<E> implements _MListLink {
int _length = 0;
_MListLink _next;
_MListLink _previous;
MList() {
_next = _previous = this;
}
void add(E entry) {
if (entry.list == this) {
return;
}
if (entry.sortId == double.infinity || _next == this) {
_insertAfter(_previous, entry);
return;
}
num sortId = entry.sortId;
if ((_previous as MEntry).sortId <= sortId) {
_insertAfter(_previous, entry);
return;
}
MEntry current = _next as MEntry;
while (!identical(current, this)) {
if (current.sortId > sortId) {
_insertAfter(current._previous, entry);
return;
}
current = current._next as MEntry;
}
_insertAfter(_previous, entry);
}
bool remove(E entry) {
if (entry._list != this) return false;
_unlink(entry); // Unlink will decrement length.
return true;
}
Iterator<E> get iterator => new _MListIterator<E>(this);
int get length => _length;
void clear() {
_MListLink next = _next;
while (!identical(next, this)) {
E entry = next as E;
next = entry._next;
entry._next = entry._previous = entry._list = null;
}
_next = _previous = this;
_length = 0;
}
E get first {
if (identical(_next, this)) {
throw new StateError('No such element');
}
return _next as E;
}
E get last {
if (identical(_previous, this)) {
throw new StateError('No such element');
}
return _previous as E;
}
E get single {
if (identical(_previous, this)) {
throw new StateError('No such element');
}
if (!identical(_previous, _next)) {
throw new StateError('Too many elements');
}
return _next as E;
}
void forEach(void action(E entry)) {
_MListLink current = _next;
while (!identical(current, this)) {
action(current as E);
current = current._next;
}
}
bool get isEmpty => _length == 0;
void _insertAfter(_MListLink entry, E newEntry) {
if (newEntry.list != null) {
throw new StateError('MEntry is already in a MList');
}
newEntry._list = this;
var predecessor = entry;
var successor = entry._next;
successor._previous = newEntry;
newEntry._previous = predecessor;
newEntry._next = successor;
predecessor._next = newEntry;
_length++;
}
void _unlink(E entry) {
entry._next._previous = entry._previous;
entry._previous._next = entry._next;
_length--;
entry._list = null; // entry._next = entry._previous = null;
}
}
class _MListIterator<E extends MEntry> implements Iterator<E> {
final MList<E> _list;
E _current;
_MListLink _next;
_MListIterator(MList<E> list)
: _list = list,
_next = list._next;
E get current => _current;
bool moveNext() {
if (identical(_next, _list)) {
_current = null;
return false;
}
_current = _next as E;
_next = _next._next;
if (_current._list == null) {
// already removed
return moveNext();
}
return true;
}
}
class _MListLink {
_MListLink _next;
_MListLink _previous;
}
abstract class MEntry<E> implements _MListLink {
double get sortId => 10000.0;
MList<MEntry> _list;
_MListLink _next;
_MListLink _previous;
MList<MEntry> get list => _list;
void unlink() {
if (_list != null) {
_list._unlink(this);
}
}
MEntry<E> get next {
if (identical(_next, _list)) return null;
MEntry<E> result = _next as MEntry<E>;
return result;
}
MEntry<E> get previous {
if (identical(_previous, _list)) return null;
return _previous as MEntry<E>;
}
void insertAfter(MEntry entry) {
_list._insertAfter(this, entry);
}
void insertBefore(MEntry entry) {
_list._insertAfter(_previous, entry);
}
}