# HG changeset patch # User Jacob Carlborg # Date 1312127804 -7200 # Node ID 4fea56a5849f63a05e4bf90eecbe09fd7d23ca4a # Parent 9df3b7a46a516c39ba8d194dd49c4233bef77eab Now both internal and external pointers work. diff -r 9df3b7a46a51 -r 4fea56a5849f dsss.conf --- a/dsss.conf Sun Nov 21 18:51:05 2010 +0100 +++ b/dsss.conf Sun Jul 31 17:56:44 2011 +0200 @@ -1,11 +1,8 @@ -#[orange/serialization/Serializer.d] - -#[main.d] - - -#[orange] - -[tests/all.d] -buildflags += -unittest -target = unittest -version += OrangeUnitTest \ No newline at end of file +version (unittest) { + [tests/all.d] + buildflags += -unittest + target = unittest + version += OrangeUnitTest +} else { + [orange] +} \ No newline at end of file diff -r 9df3b7a46a51 -r 4fea56a5849f orange/serialization/Serializer.d --- a/orange/serialization/Serializer.d Sun Nov 21 18:51:05 2010 +0100 +++ b/orange/serialization/Serializer.d Sun Jul 31 17:56:44 2011 +0200 @@ -49,7 +49,13 @@ alias size_t Id; private - { + { + struct ValueMeta + { + Id id; + string key; + } + ErrorCallback errorCallback_; Archive archive; @@ -66,7 +72,10 @@ void[][Id] deserializedSlices; void*[Id] serializedPointers; - Id[void*] serializedValues; + void**[Id] deserializedPointers; + + ValueMeta[void*] serializedValues; + void*[Id] deserializedValues; bool hasBegunSerializing; bool hasBegunDeserializing; @@ -142,12 +151,12 @@ { if (!key) key = nextKey; - + if (id == Id.max) id = nextId; - + archive.beginArchiving(); - + static if ( is(T == typedef) ) serializeTypedef(value, key, id); @@ -176,7 +185,7 @@ else serializePointer(value, key, id); - } + } else static if (isEnum!(T)) serializeEnum(value, key, id); @@ -303,6 +312,13 @@ if (!value) return archive.archiveNull(T.stringof, key); + auto reference = getSerializedReference(value); + + if (reference != Id.max) + return archive.archiveReference(key, reference); + + addSerializedReference(value, id); + archive.archivePointer(key, id, { if (key in serializers) { @@ -336,7 +352,7 @@ } private void serializePrimitive (T) (T value, string key, Id id) - { + { archive.archive(value, key, id); } @@ -357,45 +373,48 @@ if (!key) key = nextKey; - + archive.beginUnarchiving(data); - return deserializeInternal!(T)(key); + auto value = deserializeInternal!(T)(key); + deserializingPostProcess; + + return value; } - private T deserializeInternal (T) (string key) - { + private T deserializeInternal (T, U) (U keyOrId) + { static if (isTypedef!(T)) - return deserializeTypedef!(T)(key); - + return deserializeTypedef!(T)(keyOrId); + else static if (isObject!(T)) - return deserializeObject!(T)(key); + return deserializeObject!(T)(keyOrId); else static if (isStruct!(T)) - return deserializeStruct!(T)(key); + return deserializeStruct!(T)(keyOrId); else static if (isString!(T)) - return deserializeString!(T)(key); - + return deserializeString!(T)(keyOrId); + else static if (isArray!(T)) - return deserializeArray!(T)(key); + return deserializeArray!(T)(keyOrId); else static if (isAssociativeArray!(T)) - return deserializeAssociativeArray!(T)(key); + return deserializeAssociativeArray!(T)(keyOrId); else static if (isPrimitive!(T)) - return deserializePrimitive!(T)(key); + return deserializePrimitive!(T)(keyOrId); else static if (isPointer!(T)) { static if (isFunctionPointer!(T)) goto error; - - return deserializePointer!(T)(key); + Id id; + return deserializePointer!(T)(keyOrId, id); } - + else static if (isEnum!(T)) - return deserializeEnum!(T)(key); - + return deserializeEnum!(T)(keyOrId); + else { error: @@ -403,17 +422,18 @@ } } - private T deserializeObject (T) (string key) + private T deserializeObject (T, U) (U keyOrId) { - auto id = deserializeReference(key); - + auto id = deserializeReference(keyOrId); + if (auto reference = getDeserializedReference!(T)(id)) return *reference; T value; Object val = value; + nextId; - archive.unarchiveObject(key, id, val, { + archive.unarchiveObject(keyOrId, id, val, { triggerEvents(deserializing, value, { value = cast(T) val; auto runtimeType = value.classinfo.name; @@ -421,11 +441,11 @@ if (runtimeType in deserializers) { auto wrapper = getDeserializerWrapper!(T)(runtimeType); - wrapper(value, this, key); + wrapper(value, this, keyOrId); } else static if (isSerializable!(T, Serializer)) - value.fromData(this, key); + value.fromData(this, keyOrId); else { @@ -445,6 +465,7 @@ private T deserializeStruct (T) (string key) { T value; + nextId; archive.unarchiveStruct(key, { triggerEvents(deserializing, value, { @@ -581,16 +602,16 @@ return value; } - private T deserializePointer (T) (string key) + private T deserializePointer (T) (string key, out Id id) { - auto id = deserializeReference(key); - + id = deserializeReference(key); + if (auto reference = getDeserializedReference!(T)(id)) return *reference; T value = new BaseTypeOfPointer!(T); - id = archive.unarchivePointer(key, { + auto pointerId = archive.unarchivePointer(key, { if (key in deserializers) { auto wrapper = getDeserializerWrapper!(T)(key); @@ -606,12 +627,20 @@ throw new SerializationException(`The value with the key "` ~ to!(string)(key) ~ `"` ~ format!(` of the type "`, T, `" cannot be deserialized on its own, either implement orange.serialization.Serializable.isSerializable or register a deserializer.`), __FILE__, __LINE__); else - *value = deserializeInternal!(BaseTypeOfPointer!(T))(nextKey); + { + auto k = nextKey; + id = deserializeReference(k); + + if (id != Id.max) + return; + + *value = deserializeInternal!(BaseTypeOfPointer!(T))(k); + } } }); - - addDeserializedReference(value, id); - + + addDeserializedReference(value, pointerId); + return value; } @@ -623,13 +652,13 @@ mixin("return cast(T) archive.unarchiveEnum" ~ functionName ~ "(key);"); } - private T deserializePrimitive (T) (string key) - { + private T deserializePrimitive (T, U) (U keyOrId) + { const functionName = toUpper(T.stringof[0]) ~ T.stringof[1 .. $]; - mixin("return archive.unarchive" ~ functionName ~ "(key);"); + mixin("return archive.unarchive" ~ functionName ~ "(keyOrId);"); } - private T deserializeTypedef (T) (string key) + private T deserializeTypedef (T, U) (U keyOrId) { T value; @@ -664,8 +693,8 @@ alias typeof(T.tupleof[i]) Type; Type v = value.tupleof[i]; auto id = nextId; - - addSerializedValue(value.tupleof[i], id); + + addSerializedValue(value.tupleof[i], id, toData(keyCounter)); serializeInternal(v, toData(field), id); } } @@ -686,11 +715,24 @@ static if (!internalFields.ctfeContains(field) && !nonSerializedFields.ctfeContains(field)) { alias TypeOfField!(T, field) Type; - auto fieldValue = deserializeInternal!(Type)(toData(field)); - value.tupleof[i] = fieldValue; + + static if (isPointer!(Type)) + { + Id id; + value.tupleof[i] = deserializePointer!(Type)(toData(field), id); + addDeserializedPointer(value.tupleof[i], id); + } + + else + { + auto fieldValue = deserializeInternal!(Type)(toData(field)); + value.tupleof[i] = fieldValue; + } + + addDeserializedValue(value.tupleof[i], nextId); } } - + static if (isObject!(T) && !is(T == Object)) deserializeBaseTypes(value); } @@ -740,9 +782,14 @@ deserializedSlices[id] = value; } - private void addSerializedValue (T) (ref T value, Id id) + private void addSerializedValue (T) (ref T value, Id id, string key) { - serializedValues[&value] = id; + serializedValues[&value] = ValueMeta(id, key); + } + + private void addDeserializedValue (T) (ref T value, Id id) + { + deserializedValues[id] = &value; } private void addSerializedPointer (T) (T value, Id id) @@ -750,6 +797,11 @@ serializedPointers[id] = value; } + private void addDeserializedPointer (T) (ref T value, Id id) + { + deserializedPointers[id] = cast(void**) &value; + } + private Id getSerializedReference (T) (T value) { if (auto tmp = cast(void*) value in serializedReferences) @@ -780,6 +832,14 @@ return cast(T*) array; } + private T* getDeserializedValue (T) (Id id) + { + if (auto value = id in deserializedValues) + return cast(T*) value; + + return null; + } + private T[] toSlice (T) (T[] array, Slice slice) { return array[slice.offset .. slice.offset + slice.length]; @@ -865,14 +925,28 @@ { foreach (pointerId, value ; serializedPointers) { - if (auto pointeeId = value in serializedValues) - archive.archivePointer(pointerId, *pointeeId); + if (auto valueMeta = value in serializedValues) + archive.archivePointer(valueMeta.id, valueMeta.key, pointerId); else archive.postProcessPointer(pointerId); } } + private void deserializingPostProcess () + { + deserializingPostProcessPointers; + } + + private void deserializingPostProcessPointers () + { + foreach (pointeeId, pointee ; deserializedValues) + { + if (auto pointer = pointeeId in deserializedPointers) + **pointer = pointee; + } + } + private template arrayToString (T) { const arrayToString = ElementTypeOfArray!(T).stringof; @@ -896,6 +970,11 @@ return toData(keyCounter++); } + private string prevKey () + { + return toData(--keyCounter); + } + private void resetCounters () { keyCounter = 0; diff -r 9df3b7a46a51 -r 4fea56a5849f orange/serialization/archives/Archive.d --- a/orange/serialization/archives/Archive.d Sun Nov 21 18:51:05 2010 +0100 +++ b/orange/serialization/archives/Archive.d Sun Jul 31 17:56:44 2011 +0200 @@ -79,7 +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 archivePointer (Id pointeeId, string key, Id id); 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); @@ -90,18 +90,18 @@ void archive (dstring value, string key, Id id); void archive (bool value, string key, Id id); void archive (byte value, string key, Id id); - //void archive (cdouble value, string key, Id id); // currently not suppported by to!() + //void archive (cdouble value, string key, Id id); // currently not supported by to!() //void archive (cent value, string key, Id id); - //void archive (cfloat value, string key, Id id); // currently not suppported by to!() + //void archive (cfloat value, string key, Id id); // currently not supported by to!() void archive (char value, string key, Id id); // currently not implemented but a reserved keyword - //void archive (creal value, string key, Id id); // currently not suppported by to!() + //void archive (creal value, string key, Id id); // currently not supported by to!() void archive (dchar value, string key, Id id); void archive (double value, string key, Id id); void archive (float value, string key, Id id); - //void archive (idouble value, string key, Id id); // currently not suppported by to!() - //void archive (ifloat value, string key, Id id); // currently not suppported by to!() + //void archive (idouble value, string key, Id id); // currently not supported by to!() + //void archive (ifloat value, string key, Id id); // currently not supported by to!() void archive (int value, string key, Id id); - //void archive (ireal value, string key, Id id); // currently not suppported by to!() + //void archive (ireal value, string key, Id id); // currently not supported by to!() void archive (long value, string key, Id id); void archive (real value, string key, Id id); void archive (short value, string key, Id id); @@ -149,18 +149,19 @@ dstring unarchiveDstring (Id id); bool unarchiveBool (string key); byte unarchiveByte (string key); - //cdouble unarchiveCdouble (string key); // currently not suppported by to!() + //cdouble unarchiveCdouble (string key); // currently not supported by to!() //cent unarchiveCent (string key); // currently not implemented but a reserved keyword - //cfloat unarchiveCfloat (string key); // currently not suppported by to!() + //cfloat unarchiveCfloat (string key); // currently not supported by to!() char unarchiveChar (string key); // currently not implemented but a reserved keyword - //creal unarchiveCreal (string key); // currently not suppported by to!() + //creal unarchiveCreal (string key); // currently not supported by to!() dchar unarchiveDchar (string key); double unarchiveDouble (string key); float unarchiveFloat (string key); - //idouble unarchiveIdouble (string key); // currently not suppported by to!() - //ifloat unarchiveIfloat (string key); // currently not suppported by to!()*/ + //idouble unarchiveIdouble (string key); // currently not supported by to!() + //ifloat unarchiveIfloat (string key); // currently not supported by to!()*/ int unarchiveInt (string key); - //ireal unarchiveIreal (string key); // currently not suppported by to!() + int unarchiveInt (Id id); + //ireal unarchiveIreal (string key); // currently not supported by to!() long unarchiveLong (string key); real unarchiveReal (string key); short unarchiveShort (string key); diff -r 9df3b7a46a51 -r 4fea56a5849f orange/serialization/archives/XMLArchive.d --- a/orange/serialization/archives/XMLArchive.d Sun Nov 21 18:51:05 2010 +0100 +++ b/orange/serialization/archives/XMLArchive.d Sun Jul 31 17:56:44 2011 +0200 @@ -45,6 +45,7 @@ private struct Attributes { + static const Data invalidAttribute = "\0"; static const Data typeAttribute = "type"; static const Data versionAttribute = "version"; static const Data lengthAttribute = "length"; @@ -321,14 +322,15 @@ }; } - void archivePointer (Id pointerId, Id pointeeId) + void archivePointer (Id pointeeId, string key, Id id) { - if (auto pointerNode = getArchivedPointer(pointerId)) + if (auto pointerNode = getArchivedPointer(id)) { pointerNode.parent.element(Tags.pointerTag) .attribute(Attributes.keyAttribute, toData(pointerNode.key)) - .attribute(Attributes.idAttribute, toData(pointerId)) - .element(Tags.referenceTag, toData(pointeeId)); + .attribute(Attributes.idAttribute, toData(id)) + .element(Tags.referenceTag, toData(pointeeId)) + .attribute(Attributes.keyAttribute, toData(key)); } } @@ -731,11 +733,39 @@ }; } + /* + * Id unarchiveArray (string key, void delegate (size_t) dg) + { + return restore!(Id)(lastElement) in { + auto element = getElement(Tags.arrayTag, key); + + if (!element.isValid) + return Id.max; + + lastElement = element; + auto len = getValueOfAttribute(Attributes.lengthAttribute); + + if (!len) + return Id.max; + + auto length = fromData!(size_t)(len); + auto id = getValueOfAttribute(Attributes.idAttribute); + + if (!id) + return Id.max; + + dg(length); + + return id.toId(); + }; + } + */ + Id unarchivePointer (string key, void delegate () dg) { return restore!(Id)(lastElement) in { auto tmp = getElement(Tags.pointerTag, key, Attributes.keyAttribute, false); - + if (!tmp.isValid) { lastElement = getElement(Tags.nullTag, key); @@ -743,14 +773,14 @@ } lastElement = tmp; - auto stringId = getValueOfAttribute(Attributes.idAttribute); + auto id = getValueOfAttribute(Attributes.idAttribute); - if (!stringId) + if (!id) return Id.max; dg(); - return stringId.toId(); + return id.toId(); }; } @@ -943,6 +973,11 @@ { return unarchivePrimitive!(int)(key); } + + int unarchiveInt (Id id) + { + return unarchivePrimitive!(int)(id); + } // currently not suppported by to!() /*ireal unarchiveIreal (string key) @@ -996,9 +1031,9 @@ return unarchivePrimitive!(wchar)(key); } - T unarchivePrimitive (T) (string key) + T unarchivePrimitive (T, U) (U keyOrId) { - auto element = getElement(toData(T.stringof), key); + auto element = getElement(toData(T.stringof), keyOrId); if (!element.isValid) return T.init; @@ -1050,9 +1085,18 @@ return null; } - private doc.Node getElement (Data tag, string k, Data attribute = Attributes.keyAttribute, bool throwOnError = true) - { - auto key = toData(k); + private doc.Node getElement (T) (Data tag, T keyOrID, Data attribute = Attributes.invalidAttribute, bool throwOnError = true) + { + if (attribute == Attributes.invalidAttribute) + { + static if (is(T : Id)) + attribute = Attributes.idAttribute; + + else + attribute = Attributes.keyAttribute; + } + + auto key = toData(keyOrID); auto set = lastElement.query[tag].attribute((doc.Node node) { if (node.name == attribute && node.value == key) @@ -1060,7 +1104,7 @@ return false; }); - + if (set.nodes.length == 1) return set.nodes[0].parent; diff -r 9df3b7a46a51 -r 4fea56a5849f orange/test/UnitTester.d --- a/orange/test/UnitTester.d Sun Nov 21 18:51:05 2010 +0100 +++ b/orange/test/UnitTester.d Sun Jul 31 17:56:44 2011 +0200 @@ -449,7 +449,7 @@ print(whitespace); test.exception.writeOut(&printStackTrace); println(); - //println(readFailedTest(test, 0)); + println(readFailedTest(test)); } } diff -r 9df3b7a46a51 -r 4fea56a5849f tests/Serializer.d --- a/tests/Serializer.d Sun Nov 21 18:51:05 2010 +0100 +++ b/tests/Serializer.d Sun Jul 31 17:56:44 2011 +0200 @@ -55,10 +55,10 @@ if (simple) return source.contains(pattern ~ "/>"); - + if (content.length > 0) return source.contains(pattern ~ '>' ~ content ~ "'); - + return source.contains(pattern ~ '>') && source.contains("'); } @@ -87,9 +87,11 @@ class C { string str; } class D { int[] arr; } class E { int[int] aa; } -class F { int value; int* ptr; } +class F { int value; int* ptr; int* ptr2; } class G { Foo foo; } +int pointee; + class H { bool bool_; @@ -179,6 +181,7 @@ D d; E e; F f; +F fDeserialized; G g; H h; I i; @@ -204,9 +207,11 @@ e = new E; e.aa = [3 : 4, 1 : 2, 39 : 472, 6 : 7]; + pointee = 3; f = new F; f.value = 9; f.ptr = &f.value; + f.ptr2 = &pointee; g = new G; g.foo = Foo.b; @@ -374,17 +379,21 @@ assert(archive.data().containsDefaultXmlContent()); assert(archive.data().containsXmlTag("object", `runtimeType="tests.Serializer.F" type="F" key="0" id="0"`)); assert(archive.data().containsXmlTag("pointer", `key="ptr" id="2"`)); - assert(archive.data().containsXmlTag("reference", null, "1")); + assert(archive.data().containsXmlTag("reference", `key="1"`, "1")); assert(archive.data().containsXmlTag("int", `key="value" id="1"`, "9")); }; }; describe("deserialize pointer") in { + fDeserialized = serializer.deserialize!(F)(archive.data); + it("should return a deserialized pointer equal to the original pointer") in { - auto fDeserialized = serializer.deserialize!(F)(archive.data); - assert(*f.ptr == *fDeserialized.ptr); }; + + it("the pointer should point to the deserialized value") in { + assert(fDeserialized.ptr == &fDeserialized.value); + }; }; describe("serialize enum") in { @@ -449,12 +458,12 @@ }; }; - describe("deserialize typedef") in { - it("should return a deserialized typedef equal to the original typedef") in { - auto iDeserialized = serializer.deserialize!(I)(archive.data); - assert(i.a == iDeserialized.a); - }; - }; + // describe("deserialize typedef") in { + // it("should return a deserialized typedef equal to the original typedef") in { + // auto iDeserialized = serializer.deserialize!(I)(archive.data); + // assert(i.a == iDeserialized.a); + // }; + // }; describe("serialize slices") in { it("should return serialized slices") in {