10 extern int __ecereVMethodID_class_OnUnserialize;
11 extern int __ecereVMethodID_class_OnCompare;
13 // qsort_r/_s wrappers adapted from public domain code by Isaac Turner
14 #if !defined(ECERE_BOOTSTRAP)
15 #if (defined __APPLE__ || defined __MACH__ || defined __DARWIN__ || defined __FreeBSD__ || defined __BSD__ || defined __bsdi__ || defined OpenBSD3_1 || defined OpenBSD3_9 || defined __OpenBSD__ || \
16 defined __NetBSD__ || defined __DragonFly__ || defined AMIGA)
18 extern void qsort_r(void *base, uintsize nel, uintsize width, void *arg, int (*compare)(void *, const void *, const void *));
19 #elif defined(__WIN32__)
20 extern void qsort_s(void *base, uintsize nel, uintsize width, int (*compare)(void *, const void *, const void *), void * arg);
21 #elif (defined __GLIBC__ && ((__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 8)))
23 extern void qsort_r(void *base, uintsize nel, uintsize width, int(* compare)(const void *, const void *, void *), void *arg);
28 // Quick Sort algorithm adapted from public domain code by Darel Rex Finley
29 static inline void quickSort(void *base, uintsize nel, uintsize w, char * piv, int (*compare)(void *, const void *, const void *), void *arg)
31 #define MAX_LEVELS 300
32 uintsize beg[MAX_LEVELS], end[MAX_LEVELS];
39 uintsize L = beg[frame], R = end[frame]-1;
42 memcpy(piv, (char *)base + L*w, w);
45 while(compare(arg, (char *)base + (R*w), piv) >= 0 && L < R) R--;
48 memcpy((char *)base + L*w, (char *)base + R*w, w);
51 while(compare(arg, (char *)base + (L*w), piv) <= 0 && L < R) L++;
54 memcpy((char *)base + R*w, (char *)base + L*w, w);
58 memcpy((char *)base + L*w, piv, w);
60 end[frame+1] = end[frame];
63 // Process smaller partition first
64 if(end[frame]-beg[frame] > end[frame-1]-beg[frame-1])
67 swap = beg[frame]; beg[frame] = beg[frame-1]; beg[frame-1] = swap;
68 swap = end[frame]; end[frame] = end[frame-1]; end[frame-1] = swap;
77 static struct SortRData { void *arg; int (*compare)(void *, const void *, const void *); };
79 static inline int compareDeref (SortRData cs, const void **a, const void **b) { return cs.compare(cs.arg, *a, *b); }
80 static inline int compareDescDeref (SortRData cs, const void **a, const void **b) { return -cs.compare(cs.arg, *a, *b); }
81 static inline int compareDesc (SortRData cs, const void * a, const void * b) { return -cs.compare(cs.arg, a, b); }
83 static inline int compareArgLast (const void * a, const void * b, SortRData cs) { return cs.compare(cs.arg, a, b); }
84 static inline int compareDerefArgLast (const void **a, const void **b, SortRData cs) { return cs.compare(cs.arg, *a, *b); }
85 static inline int compareDescDerefArgLast (const void **a, const void **b, SortRData cs) { return -cs.compare(cs.arg, *a, *b); }
86 static inline int compareDescArgLast (const void * a, const void * b, SortRData cs) { return -cs.compare(cs.arg, a, b); }
88 static inline void _qsortrx(void *base, uintsize nel, uintsize width,
89 int (*compare)(void *arg, const void *a, const void *b),
90 int (*optCompareArgLast)(const void *a, const void *b, void *arg),
92 bool deref, bool ascending)
94 #if defined(GLIBC) && !defined(ECERE_BOOTSTRAP)
95 if(!deref && ascending && optCompareArgLast)
96 qsort_r(base, nel, width, optCompareArgLast, arg);
99 SortRData s { arg, compare };
100 #define compare_fn !deref && ascending ? compareArgLast : !deref ? compareDescArgLast : ascending ? compareDerefArgLast : compareDescDerefArgLast
101 qsort_r(base, nel, width, compare_fn, s);
105 if(!deref && ascending)
107 #if defined(BSD) && !defined(ECERE_BOOTSTRAP)
108 qsort_r(base, nel, width, arg, compare);
109 #elif defined(__WIN32__) && !defined(ECERE_BOOTSTRAP)
110 qsort_s(base, nel, width, compare, arg);
113 char * buf = new char[width];
114 quickSort(base, nel, width, buf, compare, arg);
121 SortRData s { arg, compare };
122 #define compare_fn !deref ? compareDesc : ascending ? compareDeref : compareDescDeref
123 #if defined(BSD) && !defined(ECERE_BOOTSTRAP)
124 qsort_r(base, nel, width, s, compare_fn);
125 #elif defined(__WIN32__) && !defined(ECERE_BOOTSTRAP)
126 qsort_s(base, nel, width, compare_fn, s);
129 char * buf = new char[width];
130 quickSort(base, nel, width, buf, compare_fn, s);
139 public void qsortrx(void *base, uintsize nel, uintsize width,
140 int (*compare)(void *arg, const void *a, const void *b),
141 int (*optCompareArgLast)(const void *a, const void *b, void *arg),
143 bool deref, bool ascending)
145 _qsortrx(base, nel, width, compare, optCompareArgLast, arg, deref, ascending);
148 public void qsortr(void *base, uintsize nel, uintsize width, int (*compare)(void *arg, const void *a, const void *b), void *arg)
150 _qsortrx(base, nel, width, compare, null, arg, false, true);
153 public class Array : Container
167 void OnUnserialize(IOChannel channel)
169 Array array = eInstance_New(_class); //.fullName);
171 Class Dclass = class(D);
174 //printf("%d %ss\n", count, Dclass.name);
179 for(c = 0; c < count; c++)
180 ((void (*)(void *, void *, void *))(void *)Dclass._vTbl[__ecereVMethodID_class_OnUnserialize])
181 (Dclass, ((byte *)array.array) + Dclass.typeSize * c, channel);
185 // Generic iterator support
186 IteratorPointer GetFirst() { return (IteratorPointer)array; }
187 IteratorPointer GetLast() { return (IteratorPointer)(array ? (array + (count - 1)) : null); }
188 IteratorPointer GetPrev(IteratorPointer ip)
191 return (IteratorPointer)((item && item > array) ? (item - 1) : null);
193 IteratorPointer GetNext(IteratorPointer ip)
196 return (IteratorPointer)((item && item < array + count - 1) ? (item + 1) : null);
198 T GetData(IteratorPointer ip)
203 bool SetData(IteratorPointer ip, T value)
209 IteratorPointer GetAtPosition(const I pos, bool create, bool * justAdded)
211 if((int)pos > count && create)
213 if((int)pos + 1 > minAllocSize)
214 array = renew array T[(int)pos + 1];
215 count = (int)pos + 1;
216 if(justAdded) *justAdded = true;
217 #if !defined(MEMINFO) && defined(MEMTRACKING)
220 MemBlock block = (MemBlock)((byte *)array - sizeof(class MemBlock));
221 block._class = class(T);
225 return ((int)pos < count && array) ? (IteratorPointer)(array + (int)pos) : null;
227 IteratorPointer Insert(IteratorPointer ip, T value)
231 int offset = after ? (after - array) : 0;
232 if(count + 1 > minAllocSize)
234 array = renew array T[count + 1];
235 if(after) after = array + offset;
237 memmove(after ? (after + 2) : (array + 1), after ? (after + 1) : array, (count - offset) * class(T).typeSize);
243 return (IteratorPointer)(after ? (after + 1) : array);
245 uint tsize = class(T).typeSize;
246 byte * pos = ip ? ((byte *)ip + tsize) : (byte *)array;
247 if(count+1 > minAllocSize)
249 int offset = pos - (byte *)array;
250 array = renew array T[count + 1];
251 pos = (byte *)array+offset;
253 memmove(pos + tsize, pos, (byte *)array+(count++) * tsize - pos);
255 return (IteratorPointer)pos;
258 IteratorPointer Add(T value)
260 if(count + 1 > minAllocSize)
261 array = renew array T[count + 1];
262 array[count] = value;
263 return (IteratorPointer)(array + (count++));
266 void Remove(IteratorPointer ip)
269 memmove(it, it + 1, (count - (it - array) - 1) * class(T).typeSize);
271 if(count + 1 > minAllocSize)
272 array = renew array T[count];
275 void Move(IteratorPointer ip, IteratorPointer afterIp)
279 T * after = (T *)afterIp;
283 virtual void RemoveAll()
285 if(minAllocSize && array)
286 array = renew0 array T[minAllocSize];
292 virtual int GetCount() { return count; }
296 get { return count; }
301 if(value > minAllocSize)
302 array = renew0 array T[value];
303 else if(value > count)
304 memset((byte *)array + count * class(T).typeSize, 0, (value - count) * class(T).typeSize);
306 #if !defined(MEMINFO) && defined(MEMTRACKING)
309 MemBlock block = (MemBlock)((byte *)array - sizeof(class MemBlock));
310 block._class = class(T);
317 property uint minAllocSize
319 get { return minAllocSize; }
322 if(minAllocSize != value)
325 array = renew array T[value];
326 minAllocSize = value;
328 #if !defined(MEMINFO) && defined(MEMTRACKING)
331 MemBlock block = (MemBlock)((byte *)array - sizeof(class MemBlock));
332 block._class = class(T);
338 virtual void Copy(Container source)
340 count = source.GetCount();
341 if(count > minAllocSize)
342 array = renew array T[count];
344 #if !defined(MEMINFO) && defined(MEMTRACKING)
347 MemBlock block = (MemBlock)((byte *)array - sizeof(class MemBlock));
348 block._class = class(T);
352 // TOFIX: Precomp fails on (BuiltInContainer *)
353 if((source._class == class(BuiltInContainer) && ((struct BuiltInContainer *)source)->type.type != structClass ) ||
354 eClass_IsDerived(source._class, class(Array)))
356 memcpy(array, ((Array)source).array, count * class(T).typeSize);
362 for(c = 0, i = source.GetFirst(); i; i = source.GetNext(i), c++)
364 D data = source.GetData(i);
373 for(c = 0; c<count; c++)
383 void Delete(IteratorPointer item)
390 void Sort(bool ascending)
392 Class Dclass = class(D);
393 bool byRef = (Dclass.type == systemClass && !Dclass.byValueSystemClass) || Dclass.type == bitClass || Dclass.type == enumClass || Dclass.type == unitClass;
394 _qsortrx(array, count, Dclass.typeSize, (void *)Dclass._vTbl[__ecereVMethodID_class_OnCompare], null, Dclass, !byRef, ascending);