# HG changeset patch # User Jacob Carlborg # Date 1286217765 -7200 # Node ID 963b756ed579bcd1480b06b19013a17f1b9dd591 # Parent 8ab9588b92bf8954a3662063cf72f54a121b67cc# Parent 51f05fd6a6262357eaa348ce55517d8c3dcf28a5 Resolved merge conflicts. diff -r 8ab9588b92bf -r 963b756ed579 dsss.conf --- a/dsss.conf Sat Aug 14 17:24:42 2010 +0200 +++ b/dsss.conf Mon Oct 04 20:42:45 2010 +0200 @@ -1,1 +1,1 @@ -[orange] \ No newline at end of file +[main.d] \ No newline at end of file diff -r 8ab9588b92bf -r 963b756ed579 orange/serialization/Serializer.d --- a/orange/serialization/Serializer.d Sat Aug 14 17:24:42 2010 +0200 +++ b/orange/serialization/Serializer.d Mon Oct 04 20:42:45 2010 +0200 @@ -22,8 +22,8 @@ private { alias orange.util.CTFE.contains ctfeContains; - - private enum Mode + + enum Mode { serializing, deserializing @@ -38,7 +38,7 @@ static assert(isArchive!(ArchiveType), format!(`The type "`, ArchiveType, `" does not implement the necessary methods to be an archive.`)); alias ArchiveType.ErrorCallback ErrorCallback; - alias ArchiveType.DataType DataType; + alias ArchiveType.DataType DataType; private { @@ -120,6 +120,14 @@ if (!hasBegunSerializing) hasBegunSerializing = true; + serializeInternal(value, key); + archive.postProcess; + + return archive.data; + } + + private void serializeInternal (T) (T value, DataType key = null) + { if (!key) key = nextKey; @@ -163,8 +171,6 @@ error: throw new SerializationException(format!(`The type "`, T, `" cannot be serialized.`), __FILE__, __LINE__); } - - return archive.data; } private void serializeObject (T) (T value, DataType key) @@ -223,10 +229,10 @@ } private void serializeArray (T) (T value, DataType key) - { + { archive.archive(value, key, { foreach (i, e ; value) - serialize(e, toDataType(i)); + serializeInternal(e, toDataType(i)); }); } @@ -234,7 +240,7 @@ { archive.archive(value, key, { foreach(k, v ; value) - serialize(v, toDataType(k)); + serializeInternal(v, toDataType(k)); }); } @@ -256,7 +262,7 @@ throw new SerializationException(`The value with the key "` ~ to!(string)(key) ~ `"` ~ format!(` of the type "`, T, `" cannot be serialized on its own, either implement orange.serialization.Serializable.isSerializable or register a serializer.`), __FILE__, __LINE__); else - serialize(*value, key); + serializeInternal(*value, key); } }); } @@ -274,7 +280,7 @@ private void serializeTypeDef (T) (T value, DataType key) { archive.archive(value, key, { - serialize!(BaseTypeOfTypeDef!(T))(value, key); + serializeInternal!(BaseTypeOfTypeDef!(T))(value, key); }); } @@ -470,7 +476,7 @@ { alias typeof(T.tupleof[i]) Type; Type v = value.tupleof[i]; - serialize(v, toDataType(field)); + serializeInternal(v, toDataType(field)); } } diff -r 8ab9588b92bf -r 963b756ed579 orange/serialization/archives/Archive.d --- a/orange/serialization/archives/Archive.d Sat Aug 14 17:24:42 2010 +0200 +++ b/orange/serialization/archives/Archive.d Mon Oct 04 20:42:45 2010 +0200 @@ -17,6 +17,21 @@ import orange.serialization.archives.ArchiveException; +struct Slice +{ + size_t length; + void* ptr; + + static Slice opCall (T) (T[] value) + { + Slice slice; + slice.length = value.length; + slice.ptr = value.ptr; + + return slice; + } +} + interface IArchive { void beginArchiving (); @@ -53,5 +68,13 @@ catch (ConversionException e) throw new ArchiveException(e); - } + } + + protected bool isSliceOf (T, U = T) (T[] a, U[] b) + { + void* aPtr = a.ptr; + void* bPtr = b.ptr; + + return aPtr >= bPtr && aPtr + a.length * T.sizeof <= bPtr + b.length * U.sizeof; + } } \ No newline at end of file diff -r 8ab9588b92bf -r 963b756ed579 orange/serialization/archives/XMLArchive.d --- a/orange/serialization/archives/XMLArchive.d Sat Aug 14 17:24:42 2010 +0200 +++ b/orange/serialization/archives/XMLArchive.d Mon Oct 04 20:42:45 2010 +0200 @@ -40,7 +40,8 @@ static const DataType associativeArrayTag = "associativeArray"; static const DataType typedefTag = "typedef"; static const DataType nullTag = "null"; - static const DataType enumTag = "enum"; + static const DataType enumTag = "enum"; + static const DataType sliceTag = "slice"; } private struct Attributes @@ -53,10 +54,48 @@ static const DataType idAttribute = "id"; static const DataType keyTypeAttribute = "keyType"; static const DataType valueTypeAttribute = "valueType"; + static const DataType offsetAttribute = "offset"; } private { + struct ArrayNode + { + XMLDocument!(U).Node parent; + XMLDocument!(U).Node node; + DataType id; + DataType key; + } + + struct Array + { + void* ptr; + size_t length; + size_t elementSize; + + static Array opCall (T) (T[] value) + { + Array array; + array.ptr = value.ptr; + array.length = value.length; + array.elementSize = T.sizeof; + + return array; + } + + bool isSliceOf (Array b) + { + return ptr >= b.ptr && ptr + length * elementSize <= b.ptr + b.length * b.elementSize; + } + } + + struct Slice + { + size_t length; + size_t offset; + DataType id; + } + DataType archiveType = "org.dsource.orange.xml"; DataType archiveVersion = "0.1"; @@ -71,6 +110,9 @@ DataType[void*] archivedReferences; void*[DataType] unarchivedReferences; + ArrayNode[Array] arraysToBeArchived; + void[][DataType] unarchivedSlices; + size_t idCounter; } @@ -228,18 +270,32 @@ } private void archiveString (T) (T value, DataType key) - { - lastElement.element(Tags.stringTag, toDataType(value)) - .attribute(Attributes.typeAttribute, toDataType(BaseTypeOfArray!(T).stringof)) - .attribute(Attributes.keyAttribute, key); + { + archiveArrayImpl(value, key, Tags.stringTag, toDataType(value)); } private void archiveArray (T) (T value, DataType key) - { - lastElement = lastElement.element(Tags.arrayTag) - .attribute(Attributes.typeAttribute, toDataType(BaseTypeOfArray!(T).stringof)) + { + archiveArrayImpl(value, key, Tags.arrayTag); + } + + private void archiveArrayImpl (T) (T value, DataType key, DataType tag, DataType content = null) + { + DataType id = nextId; + auto parent = lastElement; + + if (value.length == 0) + lastElement = lastElement.element(tag); + + else + lastElement = doc.createNode(tag, content); + + lastElement.attribute(Attributes.typeAttribute, toDataType(BaseTypeOfArray!(T).stringof)) .attribute(Attributes.lengthAttribute, toDataType(value.length)) - .attribute(Attributes.keyAttribute, key); + .attribute(Attributes.keyAttribute, key) + .attribute(Attributes.idAttribute, id); + + arraysToBeArchived[Array(value)] = ArrayNode(parent, lastElement, id, key); } private void archiveAssociativeArray (T) (T value, DataType key) @@ -314,7 +370,7 @@ value = unarchiveString!(T)(key); else static if (isArray!(T)) - value = unarchiveArray!(T)(key); + value = unarchiveArray!(T)(key, callDelegate); else static if (isAssociativeArray!(T)) value = unarchiveAssociativeArray!(T)(key); @@ -362,7 +418,7 @@ auto runtimeType = getValueOfAttribute(Attributes.runtimeTypeAttribute); if (!runtimeType) - return T.init; + return T.init; auto name = fromDataType!(string)(runtimeType); id = getValueOfAttribute(Attributes.idAttribute); @@ -370,16 +426,7 @@ if (!id) return T.init; - T result; - - /*static if (is(typeof(T._ctor))) - { - ParameterTupleOf!(typeof(T._ctor)) params; - result = factory!(T, typeof(params))(name, params); - } - - else*/ - result = cast(T) newInstance(name); + T result = cast(T) newInstance(name); addUnarchivedReference(result, id); @@ -398,16 +445,37 @@ private T unarchiveString (T) (DataType key) { + auto slice = unarchiveSlice(key); + + if (auto tmp = getUnarchivedSlice!(T)(slice)) + return *tmp; + auto element = getElement(Tags.stringTag, key); if (!element.isValid) return T.init; - return fromDataType!(T)(element.value); + auto value = fromDataType!(T)(element.value); + slice.id = getValueOfAttribute(Attributes.idAttribute, element); + + if (!slice.id) + return T.init; + + addUnarchivedSlice(value, slice.id); + + return value; } - private T unarchiveArray (T) (DataType key) - { + private T unarchiveArray (T) (DataType key, ref bool callDelegate) + { + auto slice = unarchiveSlice(key); + + if (auto tmp = getUnarchivedSlice!(T)(slice)) + { + callDelegate = false; + return *tmp; + } + T value; auto element = getElement(Tags.arrayTag, key); @@ -422,6 +490,12 @@ return T.init; value.length = fromDataType!(size_t)(length); + slice.id = getValueOfAttribute(Attributes.idAttribute); + + if (!slice.id) + return T.init; + + addUnarchivedSlice(value, slice.id); return value; } @@ -564,12 +638,14 @@ } return doc.Node.invalid; - } + } } - private DataType getValueOfAttribute (DataType attribute) + private DataType getValueOfAttribute (DataType attribute, doc.Node element = doc.Node.invalid) { - auto set = lastElement.query.attribute(attribute); + if (!element.isValid) element = lastElement; + + auto set = element.query.attribute(attribute); if (set.nodes.length == 1) return set.nodes[0].value; @@ -585,8 +661,8 @@ errorCallback(new ArchiveException(`Could not unarchive the value of the attribute "` ~ to!(string)(attribute) ~ `" due to malformed data.`, __FILE__, __LINE__), [attribute]); } } - - return null; + + return null; } private void addArchivedReference (T) (T value, DataType id) @@ -603,6 +679,13 @@ unarchivedReferences[id] = cast(void*) value; } + private void addUnarchivedSlice (T) (T value, DataType id) + { + static assert(isArray!(T) || isString!(T), format!(`The given type "`, T, `" is not a slice type, i.e. array or string.`)); + + unarchivedSlices[id] = value; + } + private DataType getArchivedReference (T) (T value) { if (auto tmp = cast(void*) value in archivedReferences) @@ -619,6 +702,14 @@ return null; } + private T* getUnarchivedSlice (T) (Slice slice) + { + if (auto array = slice.id in unarchivedSlices) + return &(cast(T) *array)[slice.offset .. slice.length + 1]; // dereference the array, cast it to the right type, + // slice it and then return a pointer to the result + return null; + } + private DataType nextId () { return toDataType(idCounter++); @@ -640,6 +731,21 @@ return cast(DataType) null; } + private Slice unarchiveSlice (DataType key) + { + auto element = getElement(Tags.sliceTag, key, Attributes.keyAttribute, false); + + if (element.isValid) + { + auto length = fromDataType!(size_t)(getValueOfAttribute(Attributes.lengthAttribute, element)); + auto offset = fromDataType!(size_t)(getValueOfAttribute(Attributes.offsetAttribute, element)); + + return Slice(length, offset, element.value); + } + + return Slice.init; + } + private struct AssociativeArrayVisitor (Key, Value) { private XMLArchive archive; @@ -677,4 +783,32 @@ return result; } } + + public void postProcess () + { + bool foundSlice = true; + + foreach (slice, sliceNode ; arraysToBeArchived) + { + foreach (array, arrayNode ; arraysToBeArchived) + { + if (slice.isSliceOf(array) && slice != array) + { + sliceNode.parent.element(Tags.sliceTag, arrayNode.id) + .attribute(Attributes.keyAttribute, sliceNode.key) + .attribute(Attributes.offsetAttribute, toDataType((slice.ptr - array.ptr) / slice.elementSize)) + .attribute(Attributes.lengthAttribute, toDataType(slice.length)); + + foundSlice = true; + break; + } + + else + foundSlice = false; + } + + if (!foundSlice) + sliceNode.parent.attach(sliceNode.node); + } + } } \ No newline at end of file diff -r 8ab9588b92bf -r 963b756ed579 orange/xml/XMLDocument.d --- a/orange/xml/XMLDocument.d Sat Aug 14 17:24:42 2010 +0200 +++ b/orange/xml/XMLDocument.d Mon Oct 04 20:42:45 2010 +0200 @@ -24,6 +24,8 @@ version = Phobos; } + +import orange.util.io; template Char (T) { @@ -116,25 +118,32 @@ { private InternalNode node; - version (Phobos) + version (Tango) + { + private static Node opCall (InternalNode node) + { + Node proxy; + proxy.node = node; + + return proxy; + } + } + + else { private bool shouldAddToDoc = true; private bool isRoot = true; - } - - private static Node opCall (InternalNode node, bool shouldAddToDoc = false, bool isRoot = false) - { - Node proxy; - proxy.node = node; - - version (Phobos) - { + + private static Node opCall (InternalNode node, bool shouldAddToDoc = false, bool isRoot = false) + { + Node proxy; + proxy.node = node; proxy.shouldAddToDoc = shouldAddToDoc; proxy.isRoot = isRoot; - } - return proxy; - } + return proxy; + } + } public static Node invalid () { @@ -215,6 +224,12 @@ version (Tango) return *this; else return this; } + + void attach (Node node) + { + version (Tango) this.node.move(node.node); + else this.node.elements ~= node.node; + } } struct QueryProxy @@ -441,4 +456,10 @@ else return doc.prolog ~ "\n" ~ join(doc.pretty(indentation), "\n"); } + + Node createNode (tstring name, tstring value = null) + { + version (Tango) return Node(tree.element(name, value).node.detach); + else return Node(new Element(name, value), false, false); + } } \ No newline at end of file