tarball; installer: Updated NEWS, README, LICENSE for 0.44.13
[sdk] / ecere / src / com / containers / Array.ec
1 namespace com;
2
3 import "Container"
4
5 #ifdef _DEBUG
6 // #define MEMTRACKING
7 #endif
8
9 default:
10 extern int __ecereVMethodID_class_OnUnserialize;
11 private:
12
13 public class Array : Container
14 {
15    class_fixed
16
17 public:
18    T * array;
19    uint count;
20    uint minAllocSize;
21
22    ~Array()
23    {
24       delete array;
25    }
26
27    void OnUnserialize(IOChannel channel)
28    {
29       Array array = eInstance_New(_class.fullName);
30       uint count, c;
31       Class Dclass = class(D);
32       channel.Get(count);
33 #ifdef _DEBUG
34       //printf("%d %ss\n", count, Dclass.name);
35       if(count > 10000)
36          printf("Bug");
37 #endif
38       array.size = count;
39       for(c = 0; c < count; c++)
40          ((void (*)(void *, void *, void *))(void *)Dclass._vTbl[__ecereVMethodID_class_OnUnserialize])
41             (Dclass, ((byte *)array.array) + Dclass.typeSize * c, channel);
42       this = array;
43    }
44
45    // Generic iterator support
46    IteratorPointer GetFirst() { return (IteratorPointer)array; }
47    IteratorPointer GetLast() { return (IteratorPointer)(array ? (array + (count - 1)) : null); }
48    IteratorPointer GetPrev(IteratorPointer ip)
49    {
50       T * item = (T *)ip;
51       return (IteratorPointer)((item && item > array) ? (item - 1) : null);
52    }
53    IteratorPointer GetNext(IteratorPointer ip)
54    {
55       T * item = (T *)ip;
56       return (IteratorPointer)((item && item < array + count - 1) ? (item + 1) : null);
57    }
58    T GetData(IteratorPointer ip)
59    {
60       T * item = (T *)ip;
61       return *item;
62    }
63    bool SetData(IteratorPointer ip, T value)
64    {
65       T * item = (T *)ip;
66       *item = value;
67       return true;
68    }
69    IteratorPointer GetAtPosition(const I pos, bool create, bool * justAdded)
70    {
71       if((int)pos > count && create)
72       {
73          if((int)pos + 1 > minAllocSize)
74             array = renew array T[(int)pos + 1];
75          count = (int)pos + 1;
76          if(justAdded) *justAdded = true;
77 #if !defined(MEMINFO) && defined(MEMTRACKING)
78          if(array)
79          {
80             MemBlock block = (MemBlock)((byte *)array - sizeof(class MemBlock));
81             block._class = class(T);
82          }
83 #endif
84       }
85       return ((int)pos < count && array) ? (IteratorPointer)(array + (int)pos) : null;
86    }
87    IteratorPointer Insert(IteratorPointer ip, T value)
88    {
89 /*
90       T * after = (T *)ip;
91       int offset = after ? (after - array) : 0;
92       if(count + 1 > minAllocSize)
93       {
94          array = renew array T[count + 1];
95          if(after) after = array + offset;
96       }
97       memmove(after ? (after + 2) : (array + 1), after ? (after + 1) : array, (count - offset) * class(T).typeSize);
98       if(after)
99          after[1] = value;
100       else
101          array[0] = value;
102       count++;
103       return (IteratorPointer)(after ? (after + 1) : array);
104 */
105       uint tsize = class(T).typeSize;
106       byte * pos = ip ? ((byte *)ip + tsize) : (byte *)array;
107       if(count+1 > minAllocSize)
108       {
109          int offset = pos - (byte *)array;
110          array = renew array T[count + 1];
111          pos = (byte *)array+offset;
112       }
113       memmove(pos + tsize, pos, (byte *)array+(count++) * tsize - pos);
114       *(T*)pos = value;
115       return (IteratorPointer)pos;
116    }
117
118    IteratorPointer Add(T value)
119    {
120       if(count + 1 > minAllocSize)
121          array = renew array T[count + 1];
122       array[count] = value;
123       return (IteratorPointer)(array + (count++));
124    }
125
126    void Remove(IteratorPointer ip)
127    {
128       T * it = (T *)ip;
129       memmove(it, it + 1, (count - (it - array) - 1) * class(T).typeSize);
130       count--;
131       if(count + 1 > minAllocSize)
132          array = renew array T[count];
133    }
134
135    void Move(IteratorPointer ip, IteratorPointer afterIp)
136    {
137       /*
138       T * it = (T *)ip;
139       T * after = (T *)afterIp;
140       */
141    }
142
143    virtual void RemoveAll()
144    {
145       if(minAllocSize && array)
146          array = renew0 array T[minAllocSize];
147       else
148          delete array;
149       count = 0;
150    }
151
152    virtual int GetCount() { return count; }
153
154    property uint size
155    {
156       get { return count; }
157       set
158       {
159          if(count != value)
160          {
161             if(value > minAllocSize)
162                array = renew0 array T[value];
163             else if(value > count)
164                memset((byte *)array + count * class(T).typeSize, 0, (value - count) * class(T).typeSize);
165             count = value;
166 #if !defined(MEMINFO) && defined(MEMTRACKING)
167             if(array)
168             {
169                MemBlock block = (MemBlock)((byte *)array - sizeof(class MemBlock));
170                block._class = class(T);
171             }
172 #endif
173          }
174       }
175    }
176
177    property uint minAllocSize
178    {
179       get { return minAllocSize; }
180       set
181       {
182          if(minAllocSize != value)
183          {
184             if(value > count)
185                array = renew array T[value];
186             minAllocSize = value;
187          }
188 #if !defined(MEMINFO) && defined(MEMTRACKING)
189          if(array)
190          {
191             MemBlock block = (MemBlock)((byte *)array - sizeof(class MemBlock));
192             block._class = class(T);
193          }
194 #endif
195       }
196    }
197
198    virtual void Copy(Container source)
199    {
200       count = source.GetCount();
201       if(count > minAllocSize)
202          array = renew array T[count];
203
204 #if !defined(MEMINFO) && defined(MEMTRACKING)
205          if(array)
206          {
207             MemBlock block = (MemBlock)((byte *)array - sizeof(class MemBlock));
208             block._class = class(T);
209          }
210 #endif
211
212       // TOFIX: Precomp fails on (BuiltInContainer *)
213       if((source._class == class(BuiltInContainer) && ((struct BuiltInContainer *)source)->type.type != structClass ) ||
214          eClass_IsDerived(source._class, class(Array)))
215       {
216          memcpy(array, ((Array)source).array, count * class(T).typeSize);
217       }
218       else
219       {
220          IteratorPointer i;
221          int c;
222          for(c = 0, i = source.GetFirst(); i; i = source.GetNext(i), c++)
223          {
224             D data = source.GetData(i);
225             array[c] = data;
226          }
227       }
228    }
229
230
231    void Free()
232    {
233       int c;
234       for(c = 0; c<count; c++)
235       {
236          T data = array[c];
237          delete data;
238       }
239       delete array;
240       count = 0;
241       minAllocSize = 0;
242    }
243
244    void Delete(IteratorPointer item)
245    {
246       T data = *(T*)item;
247       delete data;
248       Remove(item);
249    }
250 };