ecere/containers: Iterator::Index() now returning false when creating new entry
[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, bool * justAdded)
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          if(justAdded) *justAdded = true;
51       }
52       return ((int)pos < count && array) ? (IteratorPointer)(array + (int)pos) : null;
53    }
54    IteratorPointer Insert(IteratorPointer ip, T value)
55    {
56 /*
57       T * after = (T *)ip;
58       int offset = after ? (after - array) : 0;
59       if(count + 1 > minAllocSize)
60       {
61          array = renew array T[count + 1];
62          if(after) after = array + offset;
63       }
64       memmove(after ? (after + 2) : (array + 1), after ? (after + 1) : array, (count - offset) * class(T).typeSize);
65       if(after)
66          after[1] = value;
67       else
68          array[0] = value;
69       count++;
70       return (IteratorPointer)(after ? (after + 1) : array);
71 */
72       uint tsize = class(T).typeSize;
73       byte * pos = ip ? ((byte *)ip + tsize) : (byte *)array;
74       if(count+1 > minAllocSize)
75       {
76          int offset = pos - (byte *)array;
77          array = renew array T[count + 1];
78          pos = (byte *)array+offset;
79       }
80       memmove(pos + tsize, pos, (byte *)array+(count++) * tsize - pos);
81       *(T*)pos = value;
82       return (IteratorPointer)pos;
83    }
84
85    IteratorPointer Add(T value)
86    {
87       if(count + 1 > minAllocSize)
88          array = renew array T[count + 1];
89       array[count] = value;
90       return (IteratorPointer)(array + (count++));
91    }
92
93    void Remove(IteratorPointer ip)
94    {
95       T * it = (T *)ip;
96       memmove(it, it + 1, (count - (it - array) - 1) * class(T).typeSize);
97       count--;
98       if(count + 1 > minAllocSize)
99          array = renew array T[count];
100    }
101
102    void Move(IteratorPointer ip, IteratorPointer afterIp)
103    {
104       /*
105       T * it = (T *)ip;
106       T * after = (T *)afterIp;
107       */
108    }
109
110    virtual void RemoveAll()
111    {
112       if(minAllocSize && array)
113          array = renew0 array T[minAllocSize];
114       else
115          delete array;
116       count = 0;
117    }
118
119    virtual int GetCount() { return count; }
120
121    property uint size
122    {
123       get { return count; }
124       set
125       {
126          if(count != value)
127          {
128             if(value > minAllocSize)
129                array = renew0 array T[value];
130             else if(value > count)
131                memset(array + count, 0, (value - count) * class(T).typeSize);
132             count = value;
133          }
134       }
135    }
136
137    property uint minAllocSize
138    {
139       get { return minAllocSize; }
140       set
141       {
142          if(minAllocSize != value)
143          {
144             if(value > count)
145                array = renew array T[value];
146             minAllocSize = value;
147          }
148       }
149    }
150
151    virtual void Copy(Container source)
152    {
153       count = source.GetCount();
154       if(count > minAllocSize)
155          array = renew array T[count];
156
157       // TOFIX: Precomp fails on (BuiltInContainer *)
158       if((source._class == class(BuiltInContainer) && ((struct BuiltInContainer *)source)->type.type != structClass ) ||
159          eClass_IsDerived(source._class, class(Array)))
160       {
161          memcpy(array, ((Array)source).array, count * class(T).typeSize);
162       }
163       else
164       {
165          IteratorPointer i;
166          int c;
167          for(c = 0, i = source.GetFirst(); i; i = source.GetNext(i), c++)
168          {
169             D data = source.GetData(i);
170             array[c] = data;
171          }
172       }
173    }
174
175
176    void Free()
177    {
178       int c;
179       for(c = 0; c<count; c++)
180       {
181          T data = array[c];
182          delete data;
183       }
184       delete array;
185       count = 0;
186       minAllocSize = 0;
187    }
188
189    void Delete(IteratorPointer item)
190    {
191       T data = *(T*)item;
192       delete data;
193       Remove(item);
194    }
195 };