compiler/libec; ecere: (#158, #305) Taking advantage of new DataType Size vs Struct...
[sdk] / ecere / src / com / containers / Array.ec
1 namespace com;
2
3 import "Container"
4
5 public class Array : Container
6 {
7    class_fixed
8
9 public:
10    T * array;
11    uint count;
12    uint minAllocSize;
13
14    ~Array()
15    {
16       delete array;
17    }
18
19    // Generic iterator support
20    IteratorPointer GetFirst() { return (IteratorPointer)array; }
21    IteratorPointer GetLast() { return (IteratorPointer)(array ? (array + (count - 1)) : null); }
22    IteratorPointer GetPrev(IteratorPointer ip)
23    {
24       T * item = (T *)ip;
25       return (IteratorPointer)((item && item > array) ? (item - 1) : null);
26    }
27    IteratorPointer GetNext(IteratorPointer ip)
28    {
29       T * item = (T *)ip;
30       return (IteratorPointer)((item && item < array + count - 1) ? (item + 1) : null);
31    }
32    T GetData(IteratorPointer ip)
33    {
34       T * item = (T *)ip;
35       return *item;
36    }
37    bool SetData(IteratorPointer ip, T value)
38    {
39       T * item = (T *)ip;
40       *item = value;
41       return true;
42    }
43    IteratorPointer GetAtPosition(const I pos, bool create)
44    {
45       if((int)pos > count && create)
46       {
47          if((int)pos + 1 > minAllocSize)
48             array = renew array T[(int)pos + 1];
49          count = (int)pos + 1;
50       }
51       return ((int)pos < count && array) ? (IteratorPointer)(array + (int)pos) : null;
52    }
53    IteratorPointer Insert(IteratorPointer ip, T value)
54    {
55 /*
56       T * after = (T *)ip;
57       int offset = after ? (after - array) : 0;
58       if(count + 1 > minAllocSize)
59       {
60          array = renew array T[count + 1];
61          if(after) after = array + offset;
62       }
63       memmove(after ? (after + 2) : (array + 1), after ? (after + 1) : array, (count - offset) * class(T).typeSize);
64       if(after)
65          after[1] = value;
66       else
67          array[0] = value;
68       count++;
69       return (IteratorPointer)(after ? (after + 1) : array);
70 */
71       uint tsize = class(T).typeSize;
72       byte * pos = ip ? ((byte *)ip + tsize) : (byte *)array;
73       if(count+1 > minAllocSize)
74       {
75          int offset = pos - (byte *)array;
76          array = renew array T[count + 1];
77          pos = (byte *)array+offset;
78       }
79       memmove(pos + tsize, pos, (byte *)array+(count++) * tsize - pos);
80       *(T*)pos = value;
81       return (IteratorPointer)pos;
82    }
83
84    IteratorPointer Add(T value)
85    {
86       if(count + 1 > minAllocSize)
87          array = renew array T[count + 1];
88       array[count] = value;
89       return (IteratorPointer)(array + (count++));
90    }
91
92    void Remove(IteratorPointer ip)
93    {
94       T * it = (T *)ip;
95       memmove(it, it + 1, (count - (it - array) - 1) * class(T).typeSize);
96       count--;
97       if(count + 1 > minAllocSize)
98          array = renew array T[count];
99    }
100
101    void Move(IteratorPointer ip, IteratorPointer afterIp)
102    {
103       /*
104       T * it = (T *)ip;
105       T * after = (T *)afterIp;
106       */
107    }
108
109    virtual void RemoveAll()
110    {
111       if(minAllocSize && array)
112          array = renew0 array T[minAllocSize];
113       else
114          delete array;
115       count = 0;
116    }
117
118    virtual int GetCount() { return count; }
119
120    property uint size
121    {
122       get { return count; }
123       set
124       {
125          if(count != value)
126          {
127             if(value > minAllocSize)
128                array = renew0 array T[value];
129             else if(value > count)
130                memset(array + count, 0, (value - count) * class(T).typeSize);
131             count = value;
132          }
133       }
134    }
135
136    property uint minAllocSize
137    {
138       get { return minAllocSize; }
139       set
140       {
141          if(minAllocSize != value)
142          {
143             if(value > count)
144                array = renew array T[value];
145             minAllocSize = value;
146          }
147       }
148    }
149
150    virtual void Copy(Container source)
151    {
152       count = source.GetCount();
153       if(count > minAllocSize)
154          array = renew array T[count];
155
156       // TOFIX: Precomp fails on (BuiltInContainer *)
157       if((source._class == class(BuiltInContainer) && ((struct BuiltInContainer *)source)->type.type != structClass ) ||
158          eClass_IsDerived(source._class, class(Array)))
159       {
160          memcpy(array, ((Array)source).array, count * class(T).typeSize);
161       }
162       else
163       {
164          IteratorPointer i;
165          int c;
166          for(c = 0, i = source.GetFirst(); i; i = source.GetNext(i), c++)
167          {
168             D data = source.GetData(i);
169             array[c] = data;
170          }
171       }
172    }
173
174
175    void Free()
176    {
177       int c;
178       for(c = 0; c<count; c++)
179       {
180          T data = array[c];
181          delete data;
182       }
183       delete array;
184       count = 0;
185       minAllocSize = 0;
186    }
187
188    void Delete(IteratorPointer item)
189    {
190       T data = *(T*)item;
191       delete data;
192       Remove(item);
193    }
194 };