namespace com; import "instance" // TOFIX: This is required to build Debug on Ubuntu 10.04, GCC 4.4.3 import "CustomAVLTree" default: extern int __ecereVMethodID_class_OnCopy; extern int __ecereVMethodID_class_OnFree; extern int __ecereVMethodID_class_OnSerialize; extern int __ecereVMethodID_class_OnUnserialize; private: public class MapNode : private AVLNode { class_fixed public: // public(key) // THIS IS MISSING CODE FOR struct KEYS property const KT key { get { return AVLNode::key; } set { AVLNode::key = value; } }; property V value { get { return this ? this.value : (V)0; } set { this.value = value; } }; V value; // BECAUSE WE'RE PRIVATELY INHERITING, UNTIL public() works property thisclass prev { get { return (MapNode)AVLNode::prev; } } property thisclass next { get { return (MapNode)AVLNode::next; } } property thisclass minimum { get { return (MapNode)AVLNode::minimum; } } property thisclass maximum { get { return (MapNode)AVLNode::maximum; } } } public struct MapIterator : Iterator { property Map map { set { container = (Container)value; } get { return (Map)container; } } property const KT key { get { return ((Map)container).GetKey((MapNode)pointer); } } property V value { get { return container.GetData(pointer); } set { container.SetData(pointer, value); } } }; public class Map : CustomAVLTree, I = MT, D = V, KT = MT> { class_fixed MT GetKey(MapNode node) { if(class(MT).type == structClass) return (MT)(((byte *)&(uint64)node.key) + __ENDIAN_PAD(sizeof(void *))); return node.key; } V GetData(MapNode node) { if(node) { // Adjust node pointer for non-standard AVLNode if(class(MT).type == structClass) node = (MapNode)(((byte *) node) + class(MT).structSize - sizeof(node.AVLNode::key)); return (class(V).type == structClass) ? (MT)&node.value : node.value; } return (MT)0; } bool SetData(MapNode node, MT value) { // Adjust node pointer for non-standard AVLNode if(class(MT).type == structClass) node = (MapNode)(((byte *) node) + class(MT).structSize - sizeof(node.AVLNode::key)); if(class(V).type == structClass) memcpy((void *)&node.value, (void *)value, class(V).structSize); else node.value = value; return true; } MapNode Add(BT _newNode) { MapNode newNode = (MapNode) _newNode; if(class(MT).type == structClass || class(V).type == structClass) { MapNode realNode = (MapNode)GetAtPosition(newNode.key, true, null); SetData(realNode, newNode.value); return newNode; } else { MapNode node = root ? root.Find(class(MT), (T)newNode.key) : null; if(!node) { Class Tclass = class(MT); void (* onCopy)(void *, void *, void *) = Tclass._vTbl[__ecereVMethodID_class_OnCopy]; // Copy key here if((Tclass.type == systemClass && !Tclass.byValueSystemClass) || Tclass.type == bitClass || Tclass.type == enumClass || Tclass.type == unitClass) onCopy(Tclass, (byte *)&newNode.key + __ENDIAN_PAD(Tclass.typeSize), (byte *)&newNode.key + __ENDIAN_PAD(Tclass.typeSize)); else onCopy(Tclass, (byte *)&newNode.key + __ENDIAN_PAD(sizeof(void *)), (void *)newNode.key); CustomAVLTree::Add((T)newNode); return newNode; } else { delete newNode; return null; } } } void FreeKey(MapNode node) { if(class(MT).type == structClass) { // TODO: Make this easier... Class Tclass = class(MT); ((void (*)(void *, void *))(void *)Tclass._vTbl[__ecereVMethodID_class_OnFree])(Tclass, (((byte *)&node.key) + __ENDIAN_PAD(sizeof(void *)))); } else delete node.key; } void RemoveAll() { MapNode node = root; while(node) { if(node.left) { MapNode left = node.left; node.left = null; node = left; } else if(node.right) { MapNode right = node.right; node.right = null; node = right; } else { MapNode parent = node.parent; FreeKey(node); delete node; node = parent; } } root = null; count = 0; } void Remove(MapNode node) { CustomAVLTree::Remove(node); FreeKey(node); delete node; } void Free() { MapNode node = root; while(node) { if(node.left) { MapNode left = node.left; node.left = null; node = left; } else if(node.right) { MapNode right = node.right; node.right = null; node = right; } else { MapNode parent = node.parent; V value = GetData(node); delete value; FreeKey(node); delete node; node = parent; } } root = null; count = 0; } void Delete(MapNode node) { V value = GetData(node); delete value; FreeKey(node); Remove(node); } MapNode Find(V value) { return (MapNode)Container::Find(value); } MapNode GetAtPosition(const MT pos, bool create, bool * justAdded) { AVLNode addNode = null; AddSide addSide = compare; MapNode node = root ? root.FindEx(class(MT), pos, &addNode, &addSide) : null; if(!node && create) { Class Tclass = class(MT); void (* onCopy)(void *, void *, void *) = Tclass._vTbl[__ecereVMethodID_class_OnCopy]; if(class(MT).type == structClass || class(V).type == structClass) { uint size = sizeof(class MapNode); if(class(MT).type == structClass) size += class(MT).typeSize - sizeof(node.AVLNode::key); if(class(V).type == structClass) size += class(V).typeSize - sizeof(uint64); //sizeof(*&node.value); // TODO: Simplify code generation for this sizeof node = (MapNode)new0 byte[size]; } else { node = MapNode { key = pos }; } if((Tclass.type == systemClass && !Tclass.byValueSystemClass) || Tclass.type == bitClass || Tclass.type == enumClass || Tclass.type == unitClass) // onCopy(Tclass, (byte *)&node.key + __ENDIAN_PAD(Tclass.typeSize), (byte *)&pos + __ENDIAN_PAD(Tclass.typeSize)); memcpy((byte *)&node.key + __ENDIAN_PAD(Tclass.typeSize), (byte *)&pos + __ENDIAN_PAD(Tclass.typeSize), Tclass.typeSize); else onCopy(Tclass, (byte *)&node.key + __ENDIAN_PAD(sizeof(void *)), (void *)pos); CustomAVLTree::AddEx((T)(uintptr)node, (T)(uintptr)addNode, addSide); if(justAdded) *justAdded = true; } return node; } void Copy(Container source) { IteratorPointer i; RemoveAll(); if(!eClass_IsDerived(source._class, class(Map))) { for(i = source.GetFirst(); i; i = source.GetNext(i)) { MapNode srcNode = (MapNode)source.GetData(i); MapNode destNode = (MapNode)GetAtPosition(srcNode.key, true, null); SetData(destNode, srcNode.value); } // ADDED THIS HERE TO FREE BUILTIN CONTAINERS ASSIGNED TO A MAP if(source._class == class(BuiltInContainer)) source.Free(); } } public property Map mapSrc { set { IteratorPointer i; RemoveAll(); if(value && eClass_IsDerived(value._class, class(Map))) { for(i = value.GetFirst(); i; i = value.GetNext(i)) { MapNode srcNode = (MapNode)i; MapNode destNode = (MapNode)GetAtPosition(srcNode.key, true, null); SetData(destNode, GetData(srcNode)); } } } } void OnSerialize(IOChannel channel) { uint count = GetCount(); IteratorPointer i; Class Kclass = class(MT); Class Dclass = class(V); bool kIsNormalClass = (Kclass.type == normalClass) && Kclass.structSize; bool dIsNormalClass = (Dclass.type == normalClass) && Dclass.structSize; channel.Put(count); for(i = GetFirst(); i; i = GetNext(i)) { MapNode srcNode = (MapNode)i; MT key = GetKey((MapNode)srcNode); D data = GetData(srcNode); Class kEclass = kIsNormalClass ? ((Instance)key)._class : Kclass; Class dEclass = dIsNormalClass ? ((Instance)data)._class : Dclass; ((void (*)(void *, void *, void *))(void *)kEclass._vTbl[__ecereVMethodID_class_OnSerialize])(kEclass, ((Kclass.type == systemClass && !Kclass.byValueSystemClass) || Kclass.type == bitClass || Kclass.type == enumClass || Kclass.type == unitClass) ? &key : (void *)key, channel); ((void (*)(void *, void *, void *))(void *)dEclass._vTbl[__ecereVMethodID_class_OnSerialize])(dEclass, ((Dclass.type == systemClass && !Dclass.byValueSystemClass) || Dclass.type == bitClass || Dclass.type == enumClass || Dclass.type == unitClass) ? &data : (void *)data, channel); } } void OnUnserialize(IOChannel channel) { uint c, count; thisclass container = eInstance_New(_class.fullName); Class Kclass = class(MT); Class Dclass = class(V); channel.Get(count); for(c = 0; c < count; c++) { MapNode destNode; MT key = (KT)0; D data = (D)0; ((void (*)(void *, void *, void *))(void *)Kclass._vTbl[__ecereVMethodID_class_OnUnserialize])(Kclass, &key, channel); ((void (*)(void *, void *, void *))(void *)Dclass._vTbl[__ecereVMethodID_class_OnUnserialize])(Dclass, &data, channel); destNode = (MapNode)container.GetAtPosition(key, true, null); container.SetData(destNode, data); } this = container; } }