ecere/com/Map: Fixed Serialization/Unserialization of Map objects
[sdk] / ecere / src / com / containers / Map.ec
index 8a2aeb7..e3b763b 100644 (file)
@@ -5,6 +5,9 @@ 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<class KT, class V> : private AVLNode<KT>
@@ -105,11 +108,11 @@ public class Map<class MT, class V> : CustomAVLTree<MapNode<MT, V>, I = MT, D =
             // Copy key here
             if(Tclass.type == systemClass || Tclass.type == bitClass || Tclass.type == enumClass || Tclass.type == unitClass)
             {
-               Tclass._vTbl[__ecereVMethodID_class_OnCopy](Tclass, (((byte *)&(uint64)newNode.key) + __ENDIAN_PAD(Tclass.typeSize)),
+               ((void (*)(void *, void *, void *))(void *)Tclass._vTbl[__ecereVMethodID_class_OnCopy])(Tclass, (((byte *)&(uint64)newNode.key) + __ENDIAN_PAD(Tclass.typeSize)),
                   (((byte *)&(uint64)newNode.key) + __ENDIAN_PAD(Tclass.typeSize)));
             }
             else
-               Tclass._vTbl[__ecereVMethodID_class_OnCopy](Tclass, (((byte *)&(uint64)newNode.key) + __ENDIAN_PAD(sizeof(void *))), (void *)newNode.key);
+               ((void (*)(void *, void *, void *))(void *)Tclass._vTbl[__ecereVMethodID_class_OnCopy])(Tclass, (((byte *)&(uint64)newNode.key) + __ENDIAN_PAD(sizeof(void *))), (void *)newNode.key);
 
             CustomAVLTree::Add((T)newNode);
             return newNode;
@@ -125,7 +128,14 @@ public class Map<class MT, class V> : CustomAVLTree<MapNode<MT, V>, I = MT, D =
    void Remove(MapNode<MT, V> node)
    {
       CustomAVLTree::Remove(node);
-      delete node.key;
+      if(class(MT).type == structClass)
+      {
+         // TODO: Make this easier...
+         Class Tclass = class(MT);
+         ((void (*)(void *, void *))(void *)Tclass._vTbl[__ecereVMethodID_class_OnFree])(Tclass, (((byte *)&(uint64)node.key) + __ENDIAN_PAD(sizeof(void *))));
+      }
+      else
+         delete node.key;
       delete node;
    }
 
@@ -134,14 +144,27 @@ public class Map<class MT, class V> : CustomAVLTree<MapNode<MT, V>, I = MT, D =
       MapNode<MT, V> node;
       while(node = root)
       {
-         delete node.value;
+         MapNode<MT, V> n = node;
+
+         // Adjust node pointer for non-standard AVLNode
+         if(class(MT).type == structClass)
+            n = (MapNode<MT, V>)(((byte *) node) + class(MT).structSize - sizeof(node.AVLNode::key));
+
+         delete n.value;
          Remove(node);
       }
    }
 
    void Delete(MapNode<MT, V> node)
    {
-      delete node.value;
+      MapNode<MT, V> n = node;
+
+      // Adjust node pointer for non-standard AVLNode
+      if(class(MT).type == structClass)
+         n = (MapNode<MT, V>)(((byte *) node) + class(MT).structSize - sizeof(node.AVLNode::key));
+
+      delete n.value;
+
       Remove(node);
    }
 
@@ -170,11 +193,11 @@ public class Map<class MT, class V> : CustomAVLTree<MapNode<MT, V>, I = MT, D =
          }
          if(Tclass.type == systemClass || Tclass.type == bitClass || Tclass.type == enumClass || Tclass.type == unitClass)
          {
-            Tclass._vTbl[__ecereVMethodID_class_OnCopy](Tclass, (((byte *)&(uint64)node.key) + __ENDIAN_PAD(Tclass.typeSize)),
+            ((void (*)(void *, void *, void *))(void *)Tclass._vTbl[__ecereVMethodID_class_OnCopy])(Tclass, (((byte *)&(uint64)node.key) + __ENDIAN_PAD(Tclass.typeSize)),
               (((byte *)&(uint64)pos) + __ENDIAN_PAD(Tclass.typeSize)));
          }
          else
-            Tclass._vTbl[__ecereVMethodID_class_OnCopy](Tclass, (((byte *)&(uint64)node.key) + __ENDIAN_PAD(sizeof(void *))), (void *)pos);
+            ((void (*)(void *, void *, void *))(void *)Tclass._vTbl[__ecereVMethodID_class_OnCopy])(Tclass, (((byte *)&(uint64)node.key) + __ENDIAN_PAD(sizeof(void *))), (void *)pos);
          CustomAVLTree::Add((T)node);
       }
       return node;
@@ -215,4 +238,47 @@ public class Map<class MT, class V> : CustomAVLTree<MapNode<MT, V>, I = MT, D =
          }
       }
    }
+
+   void OnSerialize(IOChannel channel)
+   {
+      uint count = GetCount();
+      IteratorPointer i;
+      Class Kclass = class(MT);
+      Class Dclass = class(V);
+
+      channel.Put(count);
+      for(i = GetFirst(); i; i = GetNext(i))
+      {
+         MapNode<MT, V> srcNode = (MapNode<MT, V>)i;
+         MT key = GetKey((MapNode<KT, V>)srcNode);
+         D data = GetData(srcNode);
+
+         ((void (*)(void *, void *, void *))(void *)Kclass._vTbl[__ecereVMethodID_class_OnSerialize])(Kclass,
+            (Kclass.type == systemClass || Kclass.type == bitClass || Kclass.type == enumClass || Kclass.type == unitClass) ? &key : (void *)key, channel);
+         ((void (*)(void *, void *, void *))(void *)Dclass._vTbl[__ecereVMethodID_class_OnSerialize])(Dclass,
+            (Dclass.type == systemClass || 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);
+      IteratorPointer i;
+      Class Kclass = class(MT);
+      Class Dclass = class(V);
+
+      channel.Get(count);
+      for(c = 0; c < count; c++)
+      {
+         MapNode<MT, V> destNode;
+         MT key;
+         D data;
+         ((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<MT, V>)container.GetAtPosition(key, true);
+         container.SetData(destNode, data);
+      }
+      this = container;
+   }
 }