876607462583355ed32aa3919cc9e6862b789be6
[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 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 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);
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             // Copy key here
109             if((Tclass.type == systemClass && !Tclass.byValueSystemClass) || Tclass.type == bitClass || Tclass.type == enumClass || Tclass.type == unitClass)
110             {
111                ((void (*)(void *, void *, void *))(void *)Tclass._vTbl[__ecereVMethodID_class_OnCopy])(Tclass, (((byte *)&(uint64)newNode.key) + __ENDIAN_PAD(Tclass.typeSize)),
112                   (((byte *)&(uint64)newNode.key) + __ENDIAN_PAD(Tclass.typeSize)));
113             }
114             else
115                ((void (*)(void *, void *, void *))(void *)Tclass._vTbl[__ecereVMethodID_class_OnCopy])(Tclass, (((byte *)&(uint64)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 *)&(uint64)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;
145       while(node = root)
146       {
147          MapNode<MT, V> n = node;
148
149          // Adjust node pointer for non-standard AVLNode
150          if(class(MT).type == structClass)
151             n = (MapNode<MT, V>)(((byte *) node) + class(MT).structSize - sizeof(node.AVLNode::key));
152
153          delete n.value;
154          Remove(node);
155       }
156    }
157
158    void Delete(MapNode<MT, V> node)
159    {
160       MapNode<MT, V> n = node;
161
162       // Adjust node pointer for non-standard AVLNode
163       if(class(MT).type == structClass)
164          n = (MapNode<MT, V>)(((byte *) node) + class(MT).structSize - sizeof(node.AVLNode::key));
165
166       delete n.value;
167
168       Remove(node);
169    }
170
171    MapNode<MT, V> Find(V value)
172    {
173       return (MapNode<MT, V>)Container::Find(value);
174    }
175
176    MapNode<MT, V> GetAtPosition(MT pos, bool create)
177    {
178       MapNode<MT, V> node = root ? root.Find(class(MT), pos) : null;
179       if(!node && create)
180       {
181          Class Tclass = class(MT);
182          if(class(MT).type == structClass || class(V).type == structClass)
183          {
184             uint size = sizeof(class MapNode<MT, V>);
185             
186             if(class(MT).type == structClass) size += class(MT).typeSize - sizeof(node.AVLNode::key);
187             if(class(V).type == structClass) size += class(V).typeSize - sizeof(*&node.value);
188             node = (MapNode<MT, V>)new0 byte[size];
189          }
190          else
191          {
192             node = MapNode<MT, V> { key = pos };
193          }
194          if((Tclass.type == systemClass && !Tclass.byValueSystemClass) || Tclass.type == bitClass || Tclass.type == enumClass || Tclass.type == unitClass)
195          {
196             ((void (*)(void *, void *, void *))(void *)Tclass._vTbl[__ecereVMethodID_class_OnCopy])(Tclass, (((byte *)&(uint64)node.key) + __ENDIAN_PAD(Tclass.typeSize)),
197               (((byte *)&(uint64)pos) + __ENDIAN_PAD(Tclass.typeSize)));
198          }
199          else
200             ((void (*)(void *, void *, void *))(void *)Tclass._vTbl[__ecereVMethodID_class_OnCopy])(Tclass, (((byte *)&(uint64)node.key) + __ENDIAN_PAD(sizeof(void *))), (void *)pos);
201          CustomAVLTree::Add((T)node);
202       }
203       return node;
204    }
205
206    void Copy(Container<T> source)
207    {
208       IteratorPointer i;
209       RemoveAll();
210       if(!eClass_IsDerived(source._class, class(Map)))
211       {
212          for(i = source.GetFirst(); i; i = source.GetNext(i))
213          {
214             MapNode<MT, V> srcNode = (MapNode<MT, V>)source.GetData(i);
215             MapNode<MT, V> destNode = (MapNode<MT, V>)GetAtPosition(srcNode.key, true);
216             SetData(destNode, srcNode.value);
217          }
218          // ADDED THIS HERE TO FREE BUILTIN CONTAINERS ASSIGNED TO A MAP
219          if(source._class == class(BuiltInContainer))
220             source.Free();
221       }
222    }
223
224    public property Map mapSrc
225    {
226       set
227       {
228          IteratorPointer i;
229          RemoveAll();
230          if(eClass_IsDerived(value._class, class(Map)))
231          {
232             for(i = value.GetFirst(); i; i = value.GetNext(i))
233             {
234                MapNode<MT, V> srcNode = (MapNode<MT, V>)i;
235                MapNode<MT, V> destNode = (MapNode<MT, V>)GetAtPosition(srcNode.key, true);
236                SetData(destNode, GetData(srcNode));
237             }
238          }
239       }
240    }
241
242    void OnSerialize(IOChannel channel)
243    {
244       uint count = GetCount();
245       IteratorPointer i;
246       Class Kclass = class(MT);
247       Class Dclass = class(V);
248       bool kIsNormalClass = Kclass.type == normalClass;
249       bool dIsNormalClass = Dclass.type == normalClass;
250
251       channel.Put(count);
252       for(i = GetFirst(); i; i = GetNext(i))
253       {
254          MapNode<MT, V> srcNode = (MapNode<MT, V>)i;
255          MT key = GetKey((MapNode<KT, V>)srcNode);
256          D data = GetData(srcNode);
257          Class kEclass = dIsNormalClass ? ((Instance)key)._class : Kclass;
258          Class dEclass = dIsNormalClass ? ((Instance)data)._class : Dclass;
259
260          ((void (*)(void *, void *, void *))(void *)kEclass._vTbl[__ecereVMethodID_class_OnSerialize])(kEclass,
261             ((Kclass.type == systemClass && !Kclass.byValueSystemClass) || Kclass.type == bitClass || Kclass.type == enumClass || Kclass.type == unitClass) ? &key : (void *)key, channel);
262          ((void (*)(void *, void *, void *))(void *)dEclass._vTbl[__ecereVMethodID_class_OnSerialize])(dEclass,
263             ((Dclass.type == systemClass && !Dclass.byValueSystemClass) || Dclass.type == bitClass || Dclass.type == enumClass || Dclass.type == unitClass) ? &data : (void *)data, channel);
264       }
265    }
266
267    void OnUnserialize(IOChannel channel)
268    {
269       uint c, count;
270       thisclass container = eInstance_New(_class.fullName);
271       IteratorPointer i;
272       Class Kclass = class(MT);
273       Class Dclass = class(V);
274
275       channel.Get(count);
276       for(c = 0; c < count; c++)
277       {
278          MapNode<MT, V> destNode;
279          MT key;
280          D data;
281          ((void (*)(void *, void *, void *))(void *)Kclass._vTbl[__ecereVMethodID_class_OnUnserialize])(Kclass, &key, channel);
282          ((void (*)(void *, void *, void *))(void *)Dclass._vTbl[__ecereVMethodID_class_OnUnserialize])(Dclass, &data, channel);
283          destNode = (MapNode<MT, V>)container.GetAtPosition(key, true);
284          container.SetData(destNode, data);
285       }
286       this = container;
287    }
288 }