changeset 29:c422ff6477dd experimental

Better handling of serializing pointers.
author Jacob Carlborg <doob@me.com>
date Sun, 21 Nov 2010 16:53:46 +0100
parents bffcbc8c392b
children 9d1a8023bb89
files dsss.conf orange/serialization/Serializer.d orange/serialization/archives/Archive.d orange/serialization/archives/XMLArchive.d
diffstat 4 files changed, 93 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/dsss.conf	Fri Nov 19 11:55:04 2010 +0100
+++ b/dsss.conf	Sun Nov 21 16:53:46 2010 +0100
@@ -1,11 +1,11 @@
 #[orange/serialization/Serializer.d]
 
-#[main.d]
+[main.d]
 
 
 #[orange]
 
-[tests/all.d]
-buildflags += -unittest
-target = unittest
-version += OrangeUnitTest
\ No newline at end of file
+#[tests/all.d]
+#buildflags += -unittest
+#target = unittest
+#version += OrangeUnitTest
\ No newline at end of file
--- a/orange/serialization/Serializer.d	Fri Nov 19 11:55:04 2010 +0100
+++ b/orange/serialization/Serializer.d	Sun Nov 21 16:53:46 2010 +0100
@@ -65,6 +65,9 @@
 		Array[Id] serializedArrays;
 		void[][Id] deserializedSlices;
 		
+		Id[void*] serializedPointers;
+		Id[void*] serializedValues;
+		
 		bool hasBegunSerializing;
 		bool hasBegunDeserializing;
 		
@@ -115,6 +118,9 @@
 		serializedArrays = null;
 		deserializedSlices = null;
 		
+		serializedValues = null;
+		serializedPointers = null;
+		
 		hasBegunSerializing = false;
 		hasBegunDeserializing = false;
 		
@@ -298,14 +304,7 @@
 		if (!value)
 			return archive.archiveNull(T.stringof, key);
 		
-		auto reference = getSerializedReference(value);
-		
-		if (reference != Id.max)
-			return archive.archiveReference(key, reference);
-		
 		Id id = nextId;
-
-		addSerializedReference(value, id);
 		
 		archive.archivePointer(key, id, {
 			if (key in serializers)
@@ -326,6 +325,8 @@
 					serializeInternal(*value, nextKey);
 			}
 		});
+		
+		addSerializedPointer(value, id);
 	}
 	
 	private void serializeEnum (T) (T value, string key)
@@ -665,6 +666,8 @@
 			{
 				alias typeof(T.tupleof[i]) Type;				
 				Type v = value.tupleof[i];
+				
+				addSerializedValue(value.tupleof[i], nextId);
 				serializeInternal(v, toData(field));
 			}				
 		}
@@ -739,6 +742,16 @@
 		deserializedSlices[id] = value;
 	}
 	
+	private void addSerializedValue (T) (ref T value, Id id)
+	{
+		serializedValues[&value] = id;
+	}
+	
+	private void addSerializedPointer (T) (T value, Id id)
+	{
+		serializedPointers[value] = id;
+	}
+	
 	private Id getSerializedReference (T) (T value)
 	{
 		if (auto tmp = cast(void*) value in serializedReferences)
@@ -769,6 +782,14 @@
 			return cast(T*) array;
 	}
 	
+	private Id getSerializedPointer (T) (T value)
+	{
+		if (auto tmp = cast(void*) value in serializedPointers)
+			return *tmp;
+		
+		return Id.max;
+	}
+	
 	private T[] toSlice (T) (T[] array, Slice slice)
 	{
 		return array[slice.offset .. slice.offset + slice.length];
@@ -819,6 +840,12 @@
 		serializedArrays[id] = array;
 	}
 	
+	private void postProcess ()
+	{
+		postProcessArrays();
+		postProcessPointers();
+	}
+	
 	private void postProcessArrays ()
 	{
 		bool foundSlice = true;
@@ -844,9 +871,16 @@
 		}
 	}
 	
-	private void postProcess ()
+	private void postProcessPointers ()
 	{
-		postProcessArrays();
+		foreach (key, pointerId ; serializedPointers)
+		{
+			if (auto pointeeId = key in serializedValues)
+				archive.archivePointer(pointerId, *pointeeId);
+			
+			else
+				archive.postProcessPointer(pointerId);
+		}
 	}
 	
 	private template arrayToString (T)
--- a/orange/serialization/archives/Archive.d	Fri Nov 19 11:55:04 2010 +0100
+++ b/orange/serialization/archives/Archive.d	Sun Nov 21 16:53:46 2010 +0100
@@ -79,6 +79,7 @@
 	void archiveNull (string type, string key);
 	void archiveObject (string runtimeType, string type, string key, Id id, void delegate () dg);
 	void archivePointer (string key, Id id, void delegate () dg);
+	void archivePointer (Id pointerId, Id pointeeId);
 	void archiveReference (string key, Id id);
 	void archiveSlice (Slice slice, Id sliceId, Id arrayId);
 	void archiveStruct (string type, string key, Id id, void delegate () dg);
@@ -171,6 +172,7 @@
     wchar unarchiveWchar (string key);
 	
 	void postProcessArray (Id id);
+	void postProcessPointer (Id id);
 }
 
 abstract class Base (U) : Archive
--- a/orange/serialization/archives/XMLArchive.d	Fri Nov 19 11:55:04 2010 +0100
+++ b/orange/serialization/archives/XMLArchive.d	Sun Nov 21 16:53:46 2010 +0100
@@ -57,7 +57,7 @@
 		static const Data baseTypeAttribute = "baseType";
 	}
 	
-	private struct ArrayNode
+	private struct Node
 	{
 		XMLDocument!(U).Node parent;
 		XMLDocument!(U).Node node;
@@ -76,7 +76,8 @@
 		bool hasBegunArchiving;
 		bool hasBegunUnarchiving;
 		
-		ArrayNode[Id] archivedArrays;
+		Node[Id] archivedArrays;
+		Node[Id] archivedPointers;
 		void[][Data] unarchivedSlices;
 	}
 	
@@ -307,14 +308,27 @@
 	void archivePointer (string key, Id id, void delegate () dg)
 	{
 		restore(lastElement) in {
-			lastElement = lastElement.element(Tags.pointerTag)
+			auto parent = lastElement;
+			lastElement = doc.createNode(Tags.pointerTag);
+			
+			lastElement.element(Tags.pointerTag)
 			.attribute(Attributes.keyAttribute, toData(key))
 			.attribute(Attributes.idAttribute, toData(id));
 			
+			addArchivedPointer(id, parent, lastElement, key);			
 			dg();
 		};
 	}
 	
+	void archivePointer (Id pointerId, Id pointeeId)
+	{
+		if (auto pointerNode = getArchivedPointer(pointerId))
+		{
+			pointerNode.parent.element(Tags.referenceTag, toData(pointeeId)).
+			attribute(Attributes.keyAttribute, toData(pointerNode.key));
+		}
+	}
+	
 	void archiveReference (string key, Id id)
 	{
 		lastElement.element(Tags.referenceTag, toData(id))
@@ -992,17 +1006,40 @@
 			array.parent.attach(array.node);
 	}
 	
+	void postProcessPointer (Id id)
+	{
+		if (auto pointer = getArchivedPointer(id))
+			pointer.parent.attach(pointer.node);
+	}
+	
 	private void addArchivedArray (Id id, doc.Node parent, doc.Node element, string key)
 	{
-		archivedArrays[id] = ArrayNode(parent, element, id, key);
+		archivedArrays[id] = Node(parent, element, id, key);
 	}
 	
-	private ArrayNode* getArchivedArray (Id id)
+	private Node* getArchivedArray (Id id)
 	{
 		if (auto array = id in archivedArrays)
 			return array;
 
-		errorCallback(new ArchiveException(`Could not continue archiving due to no array with the Id "` ~ to!(string)(id) ~ `" was found.`, __FILE__, __LINE__), [to!(string)(id)]);
+		if (errorCallback)
+			errorCallback(new ArchiveException(`Could not continue archiving due to no array with the Id "` ~ to!(string)(id) ~ `" was found.`, __FILE__, __LINE__), [to!(string)(id)]);
+		
+		return null;
+	}
+	
+	private void addArchivedPointer (Id id, doc.Node parent, doc.Node element, string key)
+	{
+		archivedPointers[id] = Node(parent, element, id, key);
+	}
+	
+	private Node* getArchivedPointer (Id id)
+	{
+		if (auto pointer = id in archivedPointers)
+			return pointer;
+
+		if (errorCallback)
+			errorCallback(new ArchiveException(`Could not continue archiving due to no pointer with the Id "` ~ to!(string)(id) ~ `" was found.`, __FILE__, __LINE__), [to!(string)(id)]);
 		
 		return null;
 	}