ecere/com/containers/Map: Faster implementation of RemoveAll()
[sdk] / ecere / src / com / containers / Map.ec
1 namespace com;
2
3 import "instance"  // TOFIX: This is required to build Debug on Ubuntu 10.04, GCC 4.4.3
4 import "CustomAVLTree"
5
6 default:
7 extern int __ecereVMethodID_class_OnCopy;
8 extern int __ecereVMethodID_class_OnFree;
9 extern int __ecereVMethodID_class_OnSerialize;
10 extern int __ecereVMethodID_class_OnUnserialize;
11 private:
12
13 public class MapNode<class KT, class V> : private AVLNode<KT>
14 {
15 class_fixed
16
17 public:
18    // public(key)
19    // THIS IS MISSING CODE FOR struct KEYS
20    property const KT key
21    {
22       get { return AVLNode::key; }
23       set { AVLNode::key = value; }
24    };
25    property V value
26    {
27       get { return this ? this.value : (V)0; }
28       set { this.value = value; }
29    };
30    V value;
31
32    // BECAUSE WE'RE PRIVATELY INHERITING, UNTIL public() works
33    property thisclass prev { get { return (MapNode<KT,V>)AVLNode::prev; } }
34    property thisclass next { get { return (MapNode<KT,V>)AVLNode::next; } }
35    property thisclass minimum { get { return (MapNode<KT,V>)AVLNode::minimum; } }
36    property thisclass maximum { get { return (MapNode<KT,V>)AVLNode::maximum; } }
37 }
38
39 public struct MapIterator<class KT, class V> : Iterator<V, IT = KT>
40 {
41    property Map map
42    {
43       set { container = (Container<V, IT>)value; }
44       get { return (Map<KT, V>)container; }
45    }
46    property const KT key
47    {
48       get { return ((Map<KT, V>)container).GetKey((MapNode<KT, V>)pointer); }
49    }
50    property V value
51    {
52       get { return container.GetData(pointer); }
53       set { container.SetData(pointer, value); }
54    }
55 };
56
57 public class Map<class MT, class V> : CustomAVLTree<MapNode<MT, V>, I = MT, D = V, KT = MT>
58 {
59    class_fixed
60
61    MT GetKey(MapNode<KT, V> node)
62    {
63       if(class(MT).type == structClass)
64          return (MT)(((byte *)&(uint64)node.key) + __ENDIAN_PAD(sizeof(void *)));
65       return node.key;
66    }
67
68    V GetData(MapNode<MT, V> node)
69    {
70       if(node)
71       {
72          // Adjust node pointer for non-standard AVLNode
73          if(class(MT).type == structClass)
74             node = (MapNode<MT, V>)(((byte *) node) + class(MT).structSize - sizeof(node.AVLNode::key));
75          return (class(V).type == structClass) ? (MT)&node.value : node.value;
76       }
77       return (MT)0;
78    }
79
80    bool SetData(MapNode<MT, V> node, MT value)
81    {
82       // Adjust node pointer for non-standard AVLNode
83       if(class(MT).type == structClass)
84          node = (MapNode<MT, V>)(((byte *) node) + class(MT).structSize - sizeof(node.AVLNode::key));
85
86       if(class(V).type == structClass)
87          memcpy((void *)&node.value, (void *)value, class(V).structSize);
88       else
89          node.value = value;
90       return true;
91    }
92
93    MapNode<MT, V> Add(BT _newNode)
94    {
95       MapNode<MT, V> newNode = (MapNode<MT, V>) _newNode;
96       if(class(MT).type == structClass || class(V).type == structClass)
97       {
98          MapNode<MT, V> realNode = (MapNode<MT, V>)GetAtPosition(newNode.key, true, null);
99          SetData(realNode, newNode.value);
100          return newNode;
101       }
102       else
103       {
104          MapNode<MT, V> node = root ? root.Find(class(MT), (T)newNode.key) : null;
105          if(!node)
106          {
107             Class Tclass = class(MT);
108             void (* onCopy)(void *, void *, void *) = Tclass._vTbl[__ecereVMethodID_class_OnCopy];
109             // Copy key here
110             if((Tclass.type == systemClass && !Tclass.byValueSystemClass) || Tclass.type == bitClass || Tclass.type == enumClass || Tclass.type == unitClass)
111                onCopy(Tclass, (byte *)&newNode.key + __ENDIAN_PAD(Tclass.typeSize), (byte *)&newNode.key + __ENDIAN_PAD(Tclass.typeSize));
112             else
113                onCopy(Tclass, (byte *)&newNode.key + __ENDIAN_PAD(sizeof(void *)), (void *)newNode.key);
114
115             CustomAVLTree::Add((T)newNode);
116             return newNode;
117          }
118          else
119          {
120             delete newNode;
121             return null;
122          }
123       }
124    }
125
126    void FreeKey(MapNode<MT, V> node)
127    {
128       if(class(MT).type == structClass)
129       {
130          // TODO: Make this easier...
131          Class Tclass = class(MT);
132          ((void (*)(void *, void *))(void *)Tclass._vTbl[__ecereVMethodID_class_OnFree])(Tclass, (((byte *)&node.key) + __ENDIAN_PAD(sizeof(void *))));
133       }
134       else
135          delete node.key;
136    }
137
138    void RemoveAll()
139    {
140       MapNode<MT, V> node = root;
141       while(node)
142       {
143          if(node.left)
144          {
145             MapNode<MT, V> left = node.left;
146             node.left = null;
147             node = left;
148          }
149          else if(node.right)
150          {
151             MapNode<MT, V> right = node.right;
152             node.right = null;
153             node = right;
154          }
155          else
156          {
157             MapNode<MT, V> parent = node.parent;
158             FreeKey(node);
159             delete node;
160
161             node = parent;
162          }
163       }
164       root = null;
165       count = 0;
166    }
167
168    void Remove(MapNode<MT, V> node)
169    {
170       CustomAVLTree::Remove(node);
171       FreeKey(node);
172       delete node;
173    }
174
175    void Free()
176    {
177       MapNode<MT, V> node = root;
178       while(node)
179       {
180          if(node.left)
181          {
182             MapNode<MT, V> left = node.left;
183             node.left = null;
184             node = left;
185          }
186          else if(node.right)
187          {
188             MapNode<MT, V> right = node.right;
189             node.right = null;
190             node = right;
191          }
192          else
193          {
194             MapNode<MT, V> parent = node.parent;
195             V value = GetData(node);
196             delete value;
197             FreeKey(node);
198             delete node;
199
200             node = parent;
201          }
202       }
203       root = null;
204       count = 0;
205    }
206
207    void Delete(MapNode<MT, V> node)
208    {
209       V value = GetData(node);
210       delete value;
211       FreeKey(node);
212       Remove(node);
213    }
214
215    MapNode<MT, V> Find(V value)
216    {
217       return (MapNode<MT, V>)Container::Find(value);
218    }
219
220    MapNode<MT, V> GetAtPosition(const MT pos, bool create, bool * justAdded)
221    {
222       AVLNode addNode = null;
223       AddSide addSide = compare;
224       MapNode<MT, V> node = root ? root.FindEx(class(MT), pos, &addNode, &addSide) : null;
225       if(!node && create)
226       {
227          Class Tclass = class(MT);
228          void (* onCopy)(void *, void *, void *) = Tclass._vTbl[__ecereVMethodID_class_OnCopy];
229          if(class(MT).type == structClass || class(V).type == structClass)
230          {
231             uint size = sizeof(class MapNode<MT, V>);
232
233             if(class(MT).type == structClass) size += class(MT).typeSize - sizeof(node.AVLNode::key);
234             if(class(V).type == structClass)
235                size += class(V).typeSize - sizeof(uint64); //sizeof(*&node.value);  // TODO: Simplify code generation for this sizeof
236             node = (MapNode<MT, V>)new0 byte[size];
237          }
238          else
239          {
240             node = MapNode<MT, V> { key = pos };
241          }
242          if((Tclass.type == systemClass && !Tclass.byValueSystemClass) || Tclass.type == bitClass || Tclass.type == enumClass || Tclass.type == unitClass)
243             // onCopy(Tclass, (byte *)&node.key + __ENDIAN_PAD(Tclass.typeSize), (byte *)&pos + __ENDIAN_PAD(Tclass.typeSize));
244             memcpy((byte *)&node.key + __ENDIAN_PAD(Tclass.typeSize), (byte *)&pos + __ENDIAN_PAD(Tclass.typeSize), Tclass.typeSize);
245          else
246             onCopy(Tclass, (byte *)&node.key + __ENDIAN_PAD(sizeof(void *)), (void *)pos);
247          CustomAVLTree::AddEx((T)(uintptr)node, (T)(uintptr)addNode, addSide);
248          if(justAdded) *justAdded = true;
249       }
250       return node;
251    }
252
253    void Copy(Container<T> source)
254    {
255       IteratorPointer i;
256       RemoveAll();
257       if(!eClass_IsDerived(source._class, class(Map)))
258       {
259          for(i = source.GetFirst(); i; i = source.GetNext(i))
260          {
261             MapNode<MT, V> srcNode = (MapNode<MT, V>)source.GetData(i);
262             MapNode<MT, V> destNode = (MapNode<MT, V>)GetAtPosition(srcNode.key, true, null);
263             SetData(destNode, srcNode.value);
264          }
265          // ADDED THIS HERE TO FREE BUILTIN CONTAINERS ASSIGNED TO A MAP
266          if(source._class == class(BuiltInContainer))
267             source.Free();
268       }
269    }
270
271    public property Map mapSrc
272    {
273       set
274       {
275          IteratorPointer i;
276          RemoveAll();
277          if(value && eClass_IsDerived(value._class, class(Map)))
278          {
279             for(i = value.GetFirst(); i; i = value.GetNext(i))
280             {
281                MapNode<MT, V> srcNode = (MapNode<MT, V>)i;
282                MapNode<MT, V> destNode = (MapNode<MT, V>)GetAtPosition(srcNode.key, true, null);
283                SetData(destNode, GetData(srcNode));
284             }
285          }
286       }
287    }
288
289    void OnSerialize(IOChannel channel)
290    {
291       uint count = GetCount();
292       IteratorPointer i;
293       Class Kclass = class(MT);
294       Class Dclass = class(V);
295       bool kIsNormalClass = (Kclass.type == normalClass) && Kclass.structSize;
296       bool dIsNormalClass = (Dclass.type == normalClass) && Dclass.structSize;
297
298       channel.Put(count);
299       for(i = GetFirst(); i; i = GetNext(i))
300       {
301          MapNode<MT, V> srcNode = (MapNode<MT, V>)i;
302          MT key = GetKey((MapNode<KT, V>)srcNode);
303          D data = GetData(srcNode);
304          Class kEclass = kIsNormalClass ? ((Instance)key)._class : Kclass;
305          Class dEclass = dIsNormalClass ? ((Instance)data)._class : Dclass;
306
307          ((void (*)(void *, void *, void *))(void *)kEclass._vTbl[__ecereVMethodID_class_OnSerialize])(kEclass,
308             ((Kclass.type == systemClass && !Kclass.byValueSystemClass) || Kclass.type == bitClass || Kclass.type == enumClass || Kclass.type == unitClass) ? &key : (void *)key, channel);
309          ((void (*)(void *, void *, void *))(void *)dEclass._vTbl[__ecereVMethodID_class_OnSerialize])(dEclass,
310             ((Dclass.type == systemClass && !Dclass.byValueSystemClass) || Dclass.type == bitClass || Dclass.type == enumClass || Dclass.type == unitClass) ? &data : (void *)data, channel);
311       }
312    }
313
314    void OnUnserialize(IOChannel channel)
315    {
316       uint c, count;
317       thisclass container = eInstance_New(_class.fullName);
318       Class Kclass = class(MT);
319       Class Dclass = class(V);
320
321       channel.Get(count);
322       for(c = 0; c < count; c++)
323       {
324          MapNode<MT, V> destNode;
325          MT key = (KT)0;
326          D data = (D)0;
327          ((void (*)(void *, void *, void *))(void *)Kclass._vTbl[__ecereVMethodID_class_OnUnserialize])(Kclass, &key, channel);
328          ((void (*)(void *, void *, void *))(void *)Dclass._vTbl[__ecereVMethodID_class_OnUnserialize])(Dclass, &data, channel);
329          destNode = (MapNode<MT, V>)container.GetAtPosition(key, true, null);
330          container.SetData(destNode, data);
331       }
332       this = container;
333    }
334 }