# HG changeset patch # User Jacob Carlborg # Date 1290354826 -3600 # Node ID c422ff6477dd912cde207dbef2e695059b469272 # Parent bffcbc8c392bb061109f75a32fd80f5968e86576 Better handling of serializing pointers. diff -r bffcbc8c392b -r c422ff6477dd dsss.conf --- 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 diff -r bffcbc8c392b -r c422ff6477dd orange/serialization/Serializer.d --- 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) diff -r bffcbc8c392b -r c422ff6477dd orange/serialization/archives/Archive.d --- 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 diff -r bffcbc8c392b -r c422ff6477dd orange/serialization/archives/XMLArchive.d --- 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; }