ecere/com/containers; samples/gui/OpenRider: Fixed memory leaks
[sdk] / ecere / src / com / containers / Container.ec
1 namespace com;
2
3 import "BuiltInContainer"
4
5 default:
6
7 static __attribute__((unused)) void UnusedFunction()
8 {
9    int a;
10    a.OnCompare(null);
11    a.OnCopy(null);
12    a.OnGetString(null, null, null);
13    a.OnSerialize(null);
14    a.OnUnserialize(null);
15 }
16
17 extern int __ecereVMethodID_class_OnCompare;
18 extern int __ecereVMethodID_class_OnGetString;
19 extern int __ecereVMethodID_class_OnSerialize;
20 extern int __ecereVMethodID_class_OnUnserialize;
21 private:
22
23 // CAUSES PROBLEM WHEN AFTER
24 public struct Iterator<class T, class IT = int>
25 {
26    Container<T, IT> container;
27 // private:
28    IteratorPointer pointer;
29
30 public:
31    property T data
32    {
33       get { return container.GetData(pointer); }
34       set { container.SetData(pointer, value); }
35    }
36
37    bool Prev()
38    {
39       if(pointer && container)
40          pointer = container.GetPrev(pointer);
41       else if(container)
42          pointer = container.GetLast();
43       return pointer != null;
44    }
45
46    bool Next()
47    {
48       if(pointer && container)
49          pointer = container.GetNext(pointer);
50       else if(container)
51          pointer = container.GetFirst();
52       return pointer != null;
53    }
54
55    T GetData()
56    {
57       return container.GetData(pointer);
58    }
59
60    bool SetData(T value)
61    {
62       return container.SetData(pointer, value);
63    };
64
65    bool Find(const T value)
66    {
67       if(container)
68       {
69          Free();
70          pointer = container.Find(value);
71       }
72       return pointer != null;
73    }
74
75    void Remove()
76    {
77       if(container)
78          container.Remove(pointer);
79       pointer = null;
80    }
81
82    void Free()
83    {
84       if(container)
85          container.FreeIterator(pointer);
86    }
87
88    bool Index(const IT index, bool create)
89    {
90       if(container)
91       {
92          bool justAdded = false;
93          Free();
94          pointer = container.GetAtPosition(index, create, &justAdded);
95          return !justAdded && pointer != null;
96       }
97       return false;
98    }
99 };
100
101 public class Container<class T, class I = int, class D = T>
102 {
103 public:
104    class_fixed
105    public property Container<T> copySrc { set { Copy(value); } }
106    property Iterator<T> firstIterator { get { value = { (Container<T>)this, pointer = GetFirst() }; } }
107    property Iterator<T> lastIterator  { get { value = { (Container<T>)this, pointer = GetLast() }; } }
108
109    virtual IteratorPointer GetFirst() { return null; }
110    virtual IteratorPointer GetLast()  { return null; }
111    virtual IteratorPointer GetPrev(IteratorPointer pointer) { return null; }
112    virtual IteratorPointer GetNext(IteratorPointer pointer) { return null; }
113    virtual D GetData(IteratorPointer pointer) { return (D)0; }
114    virtual bool SetData(IteratorPointer pointer, D data);
115    virtual IteratorPointer GetAtPosition(const I pos, bool create, bool * justAdded) { return null; }
116
117    virtual IteratorPointer Insert(IteratorPointer after, T value);
118    virtual IteratorPointer Add(T value);
119    virtual void Remove(IteratorPointer it);
120    virtual void Move(IteratorPointer it, IteratorPointer after);
121
122    virtual void RemoveAll()
123    {
124       IteratorPointer i, next;
125       for(i = GetFirst(), next = i ? GetNext(i) : null; i; i = next, next = i ? GetNext(i) : null)
126          Remove(i);
127    }
128
129    virtual void Copy(Container<T> source)
130    {
131       IteratorPointer i;
132       RemoveAll();
133       for(i = source.GetFirst(); i; i = source.GetNext(i))
134       {
135          D data = source.GetData(i);
136          // WARNING: This doesn't make a new copy of the elements it adds
137          Add(data);
138       }
139    }
140
141    void OnFree()
142    {
143       if(this)
144       {
145          Free();
146          delete this;
147       }
148    }
149
150    void OnCopy(Container<T> source)
151    {
152       if(source)
153       {
154          // BUG IN this = SYNTAX
155          Container<T> container = eInstance_New(source._class);
156          // See WARNING in Copy()
157          container.Copy(source);
158          //*(void **)this = container;
159          this = container;
160       }
161       else
162       {
163          this = null;
164       }
165    }
166
167    virtual IteratorPointer Find(const D value)
168    {
169       IteratorPointer i;
170       Class Dclass = class(D);
171       if(((Dclass.type == systemClass && !Dclass.byValueSystemClass) || Dclass.type == bitClass || Dclass.type == enumClass || Dclass.type == unitClass))
172       {
173          for(i = GetFirst(); i; i = GetNext(i))
174          {
175             D data = GetData(i);
176             int result = ((int (*)(void *, const void *, const void *))(void *)Dclass._vTbl[__ecereVMethodID_class_OnCompare])(Dclass, &value, &data);
177             if(!result)
178                return i;
179          }
180       }
181       else
182       {
183          for(i = GetFirst(); i; i = GetNext(i))
184          {
185             D data = GetData(i);
186             int result = ((int (*)(void *, const void *, const void *))(void *)Dclass._vTbl[__ecereVMethodID_class_OnCompare])(Dclass, (const void *)(uintptr) value, (const void *)(uintptr) data);
187             if(!result)
188                return i;
189          }
190       }
191       return null;
192    }
193
194    virtual void FreeIterator(IteratorPointer it);
195
196    virtual int GetCount()
197    {
198       int count = 0;
199       IteratorPointer i;
200       for(i = GetFirst(); i; i = GetNext(i)) count++;
201       return count;
202    }
203
204    virtual void Free()
205    {
206       IteratorPointer i;
207       while((i = GetFirst()))
208          Delete(i);
209    }
210
211    virtual void Delete(IteratorPointer i)
212    {
213       D data = GetData(i);
214       delete data;
215       Remove(i);
216    }
217
218    const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
219    {
220       if(this)
221       {
222          char itemString[4096];//1024];
223          bool first = true;
224          IteratorPointer i;
225          tempString[0] = '\0';
226          for(i = GetFirst(); i; i = GetNext(i))
227          {
228             Class Dclass = class(D);
229             D data = GetData(i);
230             const char * result;
231
232             itemString[0] = '\0';
233
234             result = ((const char *(*)(void *, void *, char *, void *, bool *))(void *)Dclass._vTbl[__ecereVMethodID_class_OnGetString])(Dclass,
235                ((Dclass.type == systemClass && !Dclass.byValueSystemClass) || Dclass.type == bitClass || Dclass.type == enumClass || Dclass.type == unitClass) ? &data : (void *)data, itemString, null, null);
236             if(!first) strcat(tempString, ", ");
237
238             strcat(tempString, result);
239             first = false;
240          }
241       }
242       else
243          tempString[0] = 0;
244       return tempString;
245    }
246
247    void TakeOut(const D d)
248    {
249       IteratorPointer i = Find(d);
250       if(i) Remove(i);
251    }
252
253    ~Container()
254    {
255       RemoveAll();
256    }
257
258    void OnSerialize(IOChannel channel)
259    {
260       uint count = GetCount();
261       IteratorPointer i;
262       Class Dclass = class(D);
263       bool isNormalClass = (Dclass.type == normalClass) && Dclass.structSize;
264
265       channel.Put(count);
266       for(i = GetFirst(); i; i = GetNext(i))
267       {
268          D data = GetData(i);
269          Class Eclass = isNormalClass ? ((Instance)data)._class : Dclass;
270          ((void (*)(void *, void *, void *))(void *)Eclass._vTbl[__ecereVMethodID_class_OnSerialize])(Eclass,
271             ((Dclass.type == systemClass && !Dclass.byValueSystemClass) || Dclass.type == bitClass || Dclass.type == enumClass || Dclass.type == unitClass) ? &data : (void *)data, channel);
272       }
273    }
274
275    void OnUnserialize(IOChannel channel)
276    {
277       Container container = eInstance_New(_class.fullName);
278       uint count, c;
279       Class Dclass = class(D);
280       D data;
281       bool isStruct = Dclass.type == structClass;
282
283       channel.Get(count);
284       if(isStruct)
285          data = (D)(new byte[Dclass.structSize]);
286       for(c = 0; c < count; c++)
287       {
288          if(isStruct)
289             memset((char *)data, 0, Dclass.structSize);
290          else
291             data = (D)0;
292          ((void (*)(void *, void *, void *))(void *)Dclass._vTbl[__ecereVMethodID_class_OnUnserialize])
293             (Dclass, isStruct ? (void *)data : &data, channel);
294          container.Add(data);
295       }
296       if(isStruct)
297          delete (void *)data;
298       this = container;
299    }
300 }