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