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