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