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