4 import "List" // Ugly dependency for List optimization in Sort()
7 extern int __ecereVMethodID_class_OnCompare;
10 public struct LinkElement<class T:void *>
15 public class ListItem : IteratorPointer
21 LinkElement<thisclass> link;
22 struct { thisclass prev, next; };
26 public class LinkList<class LT:void * = ListItem, bool circ = false, link = LT::link> : Container<LT>
33 // Generic iterator support
34 LT GetFirst() { return first; }
35 LT GetLast() { return last; }
36 LT GetPrev(IteratorPointer item) { return ((LT)item).link.prev; }
37 LT GetNext(IteratorPointer item) { return ((LT)item).link.next; }
38 LT GetData(IteratorPointer pointer) { return (LT)pointer; }
40 IteratorPointer GetAtPosition(const I pos, bool create, bool * justAdded)
44 for(c = 0, item = first; c < (int)pos && item; c++, item = item.link.next);
45 return (IteratorPointer)item;
47 bool SetData(IteratorPointer pointer, LT data)
49 // Not supported for LinkList
53 IteratorPointer Add(LT item)
57 item.link.prev = last;
59 item.link.prev.link.next = item;
60 if(!first) first = item;
62 item.link.next = circ ? first : null;
64 first.link.prev = item;
67 return (IteratorPointer)item;
70 IteratorPointer Insert(IteratorPointer _prevItem, T item)
72 LT prevItem = (LT)_prevItem;
73 if(item && prevItem != item)
75 item.link.prev = prevItem ? prevItem : (circ ? last : null);
78 item.link.next = prevItem.link.next;
79 prevItem.link.next = item;
83 item.link.next = first;
88 item.link.prev.link.next = item;
90 item.link.next = item;
93 if(prevItem == last) last = item;
95 item.link.next.link.prev = item;
97 return (IteratorPointer)item;
102 void Remove(IteratorPointer _item)
108 item.link.prev.link.next = item.link.next;
110 item.link.next.link.prev = item.link.prev;
111 if(circ && last == first)
115 if(last == item) last = item.link.prev;
116 if(first == item) first = item.link.next;
118 item.link.prev = null;
119 item.link.next = null;
124 void Move(IteratorPointer _item, IteratorPointer _prevItem)
127 LT prevItem = (LT)_prevItem;
130 if(prevItem != item && (first != item || prevItem))
133 item.link.prev.link.next = item.link.next;
135 item.link.next.link.prev = item.link.prev;
136 if(item == first) first = item.link.next;
137 if(item == last) last = item.link.prev;
142 item.link.prev = prevItem ? prevItem : (circ ? last : null);
145 item.link.next = prevItem.link.next;
146 prevItem.link.next = item;
150 item.link.next = first;
155 item.link.prev.link.next = item;
157 item.link.next = item;
161 item.link.next.link.prev = item;
166 IteratorPointer Find(LT value)
168 return (IteratorPointer)value;
174 while((item = first))
181 // TOFIX: This compiles without error but produces bad code, since the virtual method prototype is an IteratorPointer which should be a pointer, not a uint64
182 //void Delete(LT item)
183 void Delete(void * item)
189 // Optimized Merge Sort Reusing List Nodes
190 static void _Sort(bool ascending, LinkList * lists)
192 // Only sort containers with more than 1 items and which are integer indexable
196 Class Dclass = class(D);
197 bool byRef = (Dclass.type == systemClass && !Dclass.byValueSystemClass) || Dclass.type == bitClass || Dclass.type == enumClass || Dclass.type == unitClass;
198 bool isList = GetData == List::GetData;
199 bool isLinkList = GetData == LinkList::GetData;
200 bool isStruct = Dclass.type == structClass;
201 int (* onCompare)(void *, const void *, const void *) = (void *)Dclass._vTbl[__ecereVMethodID_class_OnCompare];
202 LinkList listA = lists[0];
203 LinkList listB = lists[1];
206 mid = GetAtPosition(count / 2-1, false, null);
208 // Split into 2 lists
215 bool done = (a == mid);
217 listA.LinkList::Add((void *)(uintptr)i);
225 listB.LinkList::Add((void *)(uintptr)i);
228 first = null, last = null, count = 0;
230 // Sort each of the 2 lists
231 listA._Sort(ascending, lists+2);
232 listB._Sort(ascending, lists+2);
244 r = onCompare(Dclass, a, b);
247 if(isStruct || byRef)
248 r = onCompare(Dclass, &((Link)a).data, &((Link)b).data);
250 r = onCompare(Dclass, (const void *)(uintptr)((Link)a).data, (const void *)(uintptr)((Link)b).data);
254 D dataA = GetData(a), dataB = GetData(b);
255 r = onCompare(Dclass, byRef ? &dataA : (const void *)(uintptr)dataA, byRef ? &dataB : (const void *)(uintptr)dataB);
262 if(!ascending) r *= -1;
268 LinkList::Add((void *)(uintptr)i);
274 LinkList::Add((void *)(uintptr)i);
277 listA.first = null, listA.last = null, listA.count = 0;
278 listB.first = null, listB.last = null, listB.count = 0;
282 void Sort(bool ascending)
284 // Pre-allocate 2 log2(n) lists
285 int i, numLists = log2i(count) * 2;
286 LinkList * lists = new LinkList[numLists];
287 for(i = 0; i < numLists; i++)
288 lists[i] = eInstance_New(_class);
289 _Sort(ascending, lists);
290 for(i = 0; i < numLists; i++)