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