3 import "BuiltInContainer"
7 static __attribute__((unused)) void UnusedFunction()
12 a.OnGetString(null, null, null);
14 a.OnUnserialize(null);
17 extern int __ecereVMethodID_class_OnCompare;
18 extern int __ecereVMethodID_class_OnGetString;
19 extern int __ecereVMethodID_class_OnSerialize;
20 extern int __ecereVMethodID_class_OnUnserialize;
23 // CAUSES PROBLEM WHEN AFTER
24 public struct Iterator<class T, class IT = int>
26 Container<T, IT> container;
28 IteratorPointer pointer;
33 get { return container.GetData(pointer); }
34 set { container.SetData(pointer, value); }
39 if(pointer && container)
40 pointer = container.GetPrev(pointer);
42 pointer = container.GetLast();
43 return pointer != null;
48 if(pointer && container)
49 pointer = container.GetNext(pointer);
51 pointer = container.GetFirst();
52 return pointer != null;
57 return container.GetData(pointer);
62 return container.SetData(pointer, value);
65 bool Find(const T value)
70 pointer = container.Find(value);
72 return pointer != null;
78 container.Remove(pointer);
85 container.FreeIterator(pointer);
88 bool Index(const IT index, bool create)
92 bool justAdded = false;
94 pointer = container.GetAtPosition(index, create, &justAdded);
95 return !justAdded && pointer != null;
101 public class Container<class T, class I = int, class D = T>
105 public property Container<T> copySrc { set { if(value) Copy(value); } }
106 property Iterator<T> firstIterator { get { value = { (Container<T>)this, pointer = GetFirst() }; } }
107 property Iterator<T> lastIterator { get { value = { (Container<T>)this, pointer = GetLast() }; } }
109 virtual IteratorPointer GetFirst() { return null; }
110 virtual IteratorPointer GetLast() { return null; }
111 virtual IteratorPointer GetPrev(IteratorPointer pointer) { return null; }
112 virtual IteratorPointer GetNext(IteratorPointer pointer) { return null; }
113 virtual D GetData(IteratorPointer pointer) { return (D)0; }
114 virtual bool SetData(IteratorPointer pointer, D data);
115 virtual IteratorPointer GetAtPosition(const I pos, bool create, bool * justAdded) { return null; }
117 virtual IteratorPointer Insert(IteratorPointer after, T value);
118 virtual IteratorPointer Add(T value);
119 virtual void Remove(IteratorPointer it);
120 virtual void Move(IteratorPointer it, IteratorPointer after);
122 virtual void RemoveAll()
124 IteratorPointer i, next;
125 for(i = GetFirst(), next = i ? GetNext(i) : null; i; i = next, next = i ? GetNext(i) : null)
129 virtual void Copy(Container<T> source)
133 for(i = source.GetFirst(); i; i = source.GetNext(i))
135 D data = source.GetData(i);
136 // WARNING: This doesn't make a new copy of the elements it adds
150 int OnCompare(Container<T> b)
152 IteratorPointer ia, ib;
153 Class Dclass = class(D);
154 bool byRef = (Dclass.type == systemClass && !Dclass.byValueSystemClass) || Dclass.type == bitClass || Dclass.type == enumClass || Dclass.type == unitClass;
155 int (* onCompare)(void *, const void *, const void *) = (void *)Dclass._vTbl[__ecereVMethodID_class_OnCompare];
157 if(this && !b) return 1;
158 if(b && !this) return -1;
159 if(!b && !this) return 0;
160 if(GetCount() > b.GetCount()) return 1;
161 if(GetCount() < b.GetCount()) return -1;
167 D dataA = GetData(ia);
168 D dataB = b.GetData(ib);
169 int r = onCompare(Dclass, byRef ? &dataA : (const void *)(uintptr)dataA, byRef ? &dataB : (const void *)(uintptr)dataB);
179 void OnCopy(Container<T> source)
183 // BUG IN this = SYNTAX
184 Container<T> container = eInstance_New(source._class);
185 // See WARNING in Copy()
186 container.Copy(source);
187 //*(void **)this = container;
196 virtual IteratorPointer Find(const D value)
199 Class Dclass = class(D);
200 bool byRef = (Dclass.type == systemClass && !Dclass.byValueSystemClass) || Dclass.type == bitClass || Dclass.type == enumClass || Dclass.type == unitClass;
201 int (* onCompare)(void *, const void *, const void *) = (void *)Dclass._vTbl[__ecereVMethodID_class_OnCompare];
205 for(i = GetFirst(); i; i = GetNext(i))
208 int result = onCompare(Dclass, &value, &data);
215 for(i = GetFirst(); i; i = GetNext(i))
218 int result = onCompare(Dclass, (const void *)(uintptr) value, (const void *)(uintptr) data);
226 virtual void FreeIterator(IteratorPointer it);
228 virtual int GetCount()
232 for(i = GetFirst(); i; i = GetNext(i)) count++;
239 while((i = GetFirst()))
243 virtual void Delete(IteratorPointer i)
250 const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
254 char itemString[4096];//1024];
257 tempString[0] = '\0';
258 for(i = GetFirst(); i; i = GetNext(i))
260 Class Dclass = class(D);
264 itemString[0] = '\0';
266 result = ((const char *(*)(void *, void *, char *, void *, bool *))(void *)Dclass._vTbl[__ecereVMethodID_class_OnGetString])(Dclass,
267 ((Dclass.type == systemClass && !Dclass.byValueSystemClass) || Dclass.type == bitClass || Dclass.type == enumClass || Dclass.type == unitClass) ? &data : (void *)data, itemString, null, null);
268 if(!first) strcat(tempString, ", ");
270 strcat(tempString, result);
279 // TODO: Warn against the danger of using TakeOut with 'normal' classes, as they will be considered equivalent if onCompare says so
280 void TakeOut(const D d)
282 IteratorPointer i = Find(d);
291 void OnSerialize(IOChannel channel)
293 // NOTE: Null containers currently get serialized as empty
294 uint count = this ? GetCount() : 0;
296 Class Dclass = class(D);
297 bool isNormalClass = (Dclass.type == normalClass) && Dclass.structSize;
301 for(i = GetFirst(); i; i = GetNext(i))
304 Class Eclass = isNormalClass ? ((Instance)data)._class : Dclass;
305 ((void (*)(void *, void *, void *))(void *)Eclass._vTbl[__ecereVMethodID_class_OnSerialize])(Eclass,
306 ((Dclass.type == systemClass && !Dclass.byValueSystemClass) || Dclass.type == bitClass || Dclass.type == enumClass || Dclass.type == unitClass) ? &data : (void *)data, channel);
310 void OnUnserialize(IOChannel channel)
312 Container container = eInstance_New(_class.fullName);
314 Class Dclass = class(D);
316 bool isStruct = Dclass.type == structClass;
320 data = (D)(new byte[Dclass.structSize]);
321 for(c = 0; c < count; c++)
324 memset((char *)data, 0, Dclass.structSize);
327 ((void (*)(void *, void *, void *))(void *)Dclass._vTbl[__ecereVMethodID_class_OnUnserialize])
328 (Dclass, isStruct ? (void *)data : &data, channel);
336 static void _Sort(bool ascending, Container * lists)
338 // Only sort containers with more than 1 items and which are integer indexable
339 int count = GetCount();
340 if(count >= 2 && class(I) == class(int))
344 Iterator mid { this };
346 Class Dclass = class(D);
347 bool byRef = (Dclass.type == systemClass && !Dclass.byValueSystemClass) || Dclass.type == bitClass || Dclass.type == enumClass || Dclass.type == unitClass;
348 int (* onCompare)(void *, const void *, const void *) = (void *)Dclass._vTbl[__ecereVMethodID_class_OnCompare];
350 Container listA = lists[0];
351 Container listB = lists[1];
354 mid.Index(count / 2-1, false);
356 // Split into 2 lists
360 if(a.pointer == mid.pointer)
364 b.pointer = mid.pointer;
370 // Sort each of the 2 lists
371 listA._Sort(ascending, lists + 2);
372 listB._Sort(ascending, lists + 2);
380 while(a.pointer || b.pointer)
383 if(a.pointer && b.pointer)
385 D dataA = a.data, dataB = b.data;
386 r = onCompare(Dclass, byRef ? &dataA : (const void *)(uintptr)dataA, byRef ? &dataB : (const void *)(uintptr)dataB);
392 if(!ascending) r *= -1;
411 virtual void Sort(bool ascending)
413 // Pre-allocate 2 log2(n) containers
414 int i, numLists = log2i(GetCount()) * 2;
415 Container * lists = new Container[numLists];
416 for(i = 0; i < numLists; i++)
417 lists[i] = eInstance_New(_class);
418 _Sort(ascending, lists);
419 for(i = 0; i < numLists; i++)