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