sdk: Fixed projects output directories, config/platform lib overrides; Fixed 64 bit...
[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 private:
10
11 public class MapNode<class KT, class V> : private AVLNode<KT>
12 {
13 class_fixed
14
15 public:
16    // public(key)
17    // THIS IS MISSING CODE FOR struct KEYS
18    property KT key
19    {
20       get { return AVLNode::key; }
21       set { AVLNode::key = value; }
22    };
23    property V value
24    {
25       get { return this ? this.value : (V)0; }
26       set { this.value = value; }
27    };
28    V value;
29
30    // BECAUSE WE'RE PRIVATELY INHERITING, UNTIL public() works
31    property thisclass prev { get { return (MapNode<KT,V>)AVLNode::prev; } }
32    property thisclass next { get { return (MapNode<KT,V>)AVLNode::next; } }
33    property thisclass minimum { get { return (MapNode<KT,V>)AVLNode::minimum; } }
34    property thisclass maximum { get { return (MapNode<KT,V>)AVLNode::maximum; } }
35 }
36
37 public struct MapIterator<class KT, class V> : Iterator<V, IT = KT>
38 {
39    property Map map
40    {
41       set { container = (Container<V, IT>)value; }
42       get { return (Map<KT, V>)container; }
43    }
44    property KT key
45    {
46       get { return ((Map<KT, V>)container).GetKey((MapNode<KT, V>)pointer); }
47    }
48    property V value
49    {
50       get { return container.GetData(pointer); } 
51       set { container.SetData(pointer, value); }
52    }
53 };
54
55 public class Map<class MT, class V> : CustomAVLTree<MapNode<MT, V>, I = MT, D = V, KT = MT>
56 {
57    class_fixed
58
59    MT GetKey(MapNode<KT, V> node)
60    {
61       if(class(MT).type == structClass)
62          return (MT)(((byte *)&(uint64)node.key) + __ENDIAN_PAD(sizeof(void *)));
63       return node.key;
64    }
65
66    V GetData(MapNode<MT, V> node)
67    {
68       if(node)
69       {
70          // Adjust node pointer for non-standard AVLNode
71          if(class(MT).type == structClass)
72             node = (MapNode<MT, V>)(((byte *) node) + class(MT).structSize - sizeof(node.AVLNode::key));
73          return (class(V).type == structClass) ? (MT)&node.value : node.value;
74       }
75       return (MT)0;
76    }
77
78    bool SetData(MapNode<MT, V> node, MT value)
79    {
80       // Adjust node pointer for non-standard AVLNode
81       if(class(MT).type == structClass)
82          node = (MapNode<MT, V>)(((byte *) node) + class(MT).structSize - sizeof(node.AVLNode::key));
83
84       if(class(V).type == structClass)
85          memcpy((void *)&node.value, (void *)value, class(V).structSize);
86       else
87          node.value = value;
88       return true;
89    }
90
91    MapNode<MT, V> Add(BT _newNode)
92    {
93       MapNode<MT, V> newNode = (MapNode<MT, V>) _newNode;
94       if(class(MT).type == structClass || class(V).type == structClass)
95       {
96          MapNode<MT, V> realNode = (MapNode<MT, V>)GetAtPosition(newNode.key, true);
97          SetData(realNode, newNode.value);
98          return newNode;
99       }
100       else
101       {
102          MapNode<MT, V> node = root ? root.Find(class(MT), (T)newNode.key) : null;
103          if(!node)
104          {
105             Class Tclass = class(MT);
106             // Copy key here
107             if(Tclass.type == systemClass || Tclass.type == bitClass || Tclass.type == enumClass || Tclass.type == unitClass)
108             {
109                ((void (*)(void *, void *, void *))(void *)Tclass._vTbl[__ecereVMethodID_class_OnCopy])(Tclass, (((byte *)&(uint64)newNode.key) + __ENDIAN_PAD(Tclass.typeSize)),
110                   (((byte *)&(uint64)newNode.key) + __ENDIAN_PAD(Tclass.typeSize)));
111             }
112             else
113                ((void (*)(void *, void *, void *))(void *)Tclass._vTbl[__ecereVMethodID_class_OnCopy])(Tclass, (((byte *)&(uint64)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 Remove(MapNode<MT, V> node)
127    {
128       CustomAVLTree::Remove(node);
129       if(class(MT).type == structClass)
130       {
131          // TODO: Make this easier...
132          Class Tclass = class(MT);
133          ((void (*)(void *, void *))(void *)Tclass._vTbl[__ecereVMethodID_class_OnFree])(Tclass, (((byte *)&(uint64)node.key) + __ENDIAN_PAD(sizeof(void *))));
134       }
135       else
136          delete node.key;
137       delete node;
138    }
139
140    void Free()
141    {
142       MapNode<MT, V> node;
143       while(node = root)
144       {
145          MapNode<MT, V> n = node;
146
147          // Adjust node pointer for non-standard AVLNode
148          if(class(MT).type == structClass)
149             n = (MapNode<MT, V>)(((byte *) node) + class(MT).structSize - sizeof(node.AVLNode::key));
150
151          delete n.value;
152          Remove(node);
153       }
154    }
155
156    void Delete(MapNode<MT, V> node)
157    {
158       delete node.value;
159       Remove(node);
160    }
161
162    MapNode<MT, V> Find(V value)
163    {
164       return (MapNode<MT, V>)Container::Find(value);
165    }
166
167    MapNode<MT, V> GetAtPosition(MT pos, bool create)
168    {
169       MapNode<MT, V> node = root ? root.Find(class(MT), pos) : null;
170       if(!node && create)
171       {
172          Class Tclass = class(MT);
173          if(class(MT).type == structClass || class(V).type == structClass)
174          {
175             uint size = sizeof(class MapNode<MT, V>);
176             
177             if(class(MT).type == structClass) size += class(MT).typeSize - sizeof(node.AVLNode::key);
178             if(class(V).type == structClass) size += class(V).typeSize - sizeof(*&node.value);
179             node = (MapNode<MT, V>)new0 byte[size];
180          }
181          else
182          {
183             node = MapNode<MT, V> { key = pos };
184          }
185          if(Tclass.type == systemClass || Tclass.type == bitClass || Tclass.type == enumClass || Tclass.type == unitClass)
186          {
187             ((void (*)(void *, void *, void *))(void *)Tclass._vTbl[__ecereVMethodID_class_OnCopy])(Tclass, (((byte *)&(uint64)node.key) + __ENDIAN_PAD(Tclass.typeSize)),
188               (((byte *)&(uint64)pos) + __ENDIAN_PAD(Tclass.typeSize)));
189          }
190          else
191             ((void (*)(void *, void *, void *))(void *)Tclass._vTbl[__ecereVMethodID_class_OnCopy])(Tclass, (((byte *)&(uint64)node.key) + __ENDIAN_PAD(sizeof(void *))), (void *)pos);
192          CustomAVLTree::Add((T)node);
193       }
194       return node;
195    }
196
197    void Copy(Container<T> source)
198    {
199       IteratorPointer i;
200       RemoveAll();
201       if(!eClass_IsDerived(source._class, class(Map)))
202       {
203          for(i = source.GetFirst(); i; i = source.GetNext(i))
204          {
205             MapNode<MT, V> srcNode = (MapNode<MT, V>)source.GetData(i);
206             MapNode<MT, V> destNode = (MapNode<MT, V>)GetAtPosition(srcNode.key, true);
207             SetData(destNode, srcNode.value);
208          }
209          // ADDED THIS HERE TO FREE BUILTIN CONTAINERS ASSIGNED TO A MAP
210          if(source._class == class(BuiltInContainer))
211             source.Free();
212       }
213    }
214
215    public property Map mapSrc
216    {
217       set
218       {
219          IteratorPointer i;
220          RemoveAll();
221          if(eClass_IsDerived(value._class, class(Map)))
222          {
223             for(i = value.GetFirst(); i; i = value.GetNext(i))
224             {
225                MapNode<MT, V> srcNode = (MapNode<MT, V>)i;
226                MapNode<MT, V> destNode = (MapNode<MT, V>)GetAtPosition(srcNode.key, true);
227                SetData(destNode, GetData(srcNode));
228             }
229          }
230       }
231    }
232 }