Mercurial > projects > orange
view orange/serialization/archives/XMLArchive.d @ 24:55f0a9d5df8d experimental
First step in refactoring the API.
author | Jacob Carlborg <doob@me.com> |
---|---|
date | Tue, 05 Oct 2010 21:59:46 +0200 |
parents | 963b756ed579 |
children | b51e953f79eb |
line wrap: on
line source
/** * Copyright: Copyright (c) 2010 Jacob Carlborg. * Authors: Jacob Carlborg * Version: Initial created: Jan 26, 2010 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) */ module orange.serialization.archives.XMLArchive; version (Tango) import tango.util.Convert : to; else import std.conv; import orange.serialization.archives._; import orange.util._; import orange.xml.XMLDocument; final class XMLArchive (U = char) : Archive!(U) { private struct Tags { static const DataType structTag = "struct"; static const DataType dataTag = "data"; static const DataType archiveTag = "archive"; static const DataType arrayTag = "array"; static const DataType objectTag = "object"; static const DataType baseTag = "base"; static const DataType stringTag = "string"; static const DataType referenceTag = "reference"; static const DataType pointerTag = "pointer"; static const DataType associativeArrayTag = "associativeArray"; static const DataType typedefTag = "typedef"; static const DataType nullTag = "null"; static const DataType enumTag = "enum"; static const DataType sliceTag = "slice"; } private struct Attributes { static const DataType typeAttribute = "type"; static const DataType versionAttribute = "version"; static const DataType lengthAttribute = "length"; static const DataType keyAttribute = "key"; static const DataType runtimeTypeAttribute = "runtimeType"; static const DataType idAttribute = "id"; static const DataType keyTypeAttribute = "keyType"; static const DataType valueTypeAttribute = "valueType"; static const DataType offsetAttribute = "offset"; } private { DataType archiveType = "org.dsource.orange.xml"; DataType archiveVersion = "0.1"; XMLDocument!(U) doc; doc.Node lastElement; bool hasBegunArchiving; bool hasBegunUnarchiving; ArrayNode[Array] arraysToBeArchived; void[][DataType] unarchivedSlices; } this (ErrorCallback errorCallback) { this.errorCallback = errorCallback; doc = new XMLDocument!(U); } public void beginArchiving () { if (!hasBegunArchiving) { doc.header; lastElement = doc.tree.element(Tags.archiveTag) .attribute(Attributes.typeAttribute, archiveType) .attribute(Attributes.versionAttribute, archiveVersion); lastElement = lastElement.element(Tags.dataTag); hasBegunArchiving = true; } } public void beginUnarchiving (IDataType untypedData) { auto data = cast(DataType) untypedData; if (!hasBegunUnarchiving) { doc.parse(data); hasBegunUnarchiving = true; auto set = doc.query[Tags.archiveTag][Tags.dataTag]; if (set.nodes.length == 1) lastElement = set.nodes[0]; else { if (errorCallback) { if (set.nodes.length == 0) errorCallback(new ArchiveException(errorMessage!(ArchiveMode.unarchiving) ~ `The "` ~ to!(string)(Tags.dataTag) ~ `" tag could not be found.`, __FILE__, __LINE__), [Tags.dataTag]); else errorCallback(new ArchiveException(errorMessage!(ArchiveMode.unarchiving) ~ `There were more than one "` ~ to!(string)(Tags.dataTag) ~ `" tag.`, __FILE__, __LINE__), [Tags.dataTag]); } } } } IDataType data () { return doc.toString(); } 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); } } void reset () { hasBegunArchiving = false; hasBegunUnarchiving = false; doc.reset; } void archiveArray (Array array, string type, string key, size_t id) { internalArchiveArray(type, array, key, id, Tags.arrayTag); } private void internalArchiveArray(string type, Array array, string key, size_t id, DataType tag, DataType content = null) { auto parent = lastElement; if (value.length == 0) lastElement = lastElement.element(tag); else lastElement = doc.createNode(tag, content); lastElement.attribute(Attributes.typeAttribute, toDataType(type)) .attribute(Attributes.lengthAttribute, toDataType(length)) .attribute(Attributes.keyAttribute, toDataType(key)) .attribute(Attributes.idAttribute, toDataType(id)); } void archiveAssociativeArray (string keyType, string valueType, size_t length, string key, size_t id) { lastElement = lastElement.element(Tags.associativeArrayTag) .attribute(Attributes.keyTypeAttribute, toDataType(keyType)) .attribute(Attributes.valueTypeAttribute, toDataType(valueType)) .attribute(Attributes.lengthAttribute, toDataType(length)) .attribute(Attributes.keyAttribute, key); } void archiveEnum (bool value, string key, size_t id) { internalArchiveEnum(value, key, id); } void archiveEnum (byte value, string key, size_t id) { internalArchiveEnum(value, key, id); } void archiveEnum (char value, string key, size_t id) { internalArchiveEnum(value, key, id); } void archiveEnum (dchar value, string key, size_t id) { internalArchiveEnum(value, key, id); } void archiveEnum (int value, string key, size_t id) { internalArchiveEnum(value, key, id); } void archiveEnum (long value, string key, size_t id) { internalArchiveEnum(value, key, id); } void archiveEnum (short value, string key, size_t id) { internalArchiveEnum(value, key, id); } void archiveEnum (ubyte value, string key, size_t id) { internalArchiveEnum(value, key, id); } void archiveEnum (uint value, string key, size_t id) { internalArchiveEnum(value, key, id); } void archiveEnum (ulong value, string key, size_t id) { internalArchiveEnum(value, key, id); } void archiveEnum (ushort value, string key, size_t id) { internalArchiveEnum(value, key, id); } void archiveEnum (wchar value, string key, size_t id) { internalArchiveEnum(value, key, id); } private void internalArchiveEnum (T) (T value, string key, size_t id) { lastElement.element(Tags.enumTag, toDataType(value)) .attribute(Attributes.typeAttribute, toDataType(T.stringof)) .attribute(Attributes.keyAttribute, toDataType(key)); } void archiveNull (string type, string key) { lastElement.element(Tags.nullTag) .attribute(Attributes.typeAttribute, toDataType(T.stringof)) .attribute(Attributes.keyAttribute, key); } void archiveObject (string runtimeType, string type, string key, size_t id) { lastElement = lastElement.element(Tags.objectTag) .attribute(Attributes.runtimeTypeAttribute, toDataType(name)) .attribute(Attributes.typeAttribute, toDataType(type)) .attribute(Attributes.keyAttribute, toDataType(key)) .attribute(Attributes.idAttribute, toDataType(id)); } void archivePointer (string key, size_t id) { lastElement = lastElement.element(Tags.pointerTag) .attribute(Attributes.keyAttribute, toDataType(key)) .attribute(Attributes.idAttribute, toDataType(id)); } void archiveReference (size_t key, size_t id) { lastElement.element(Tags.referenceTag, toDataType(id)) .attribute(Attributes.keyAttribute, toDataType(key)); } /*void archiveSlice (Array array, Array slice) { 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)); }*/ void archiveStruct (string type, size_t key, size_t id) { lastElement = lastElement.element(Tags.structTag) .attribute(Attributes.typeAttribute, toDataType(type)) .attribute(Attributes.keyAttribute, key); } void archiveTypedef (string type, size_t key, size_t id) { lastElement = lastElement.element(Tags.typedefTag) .attribute(Attributes.typeAttribute, toDataType(type)); .attribute(Attributes.key, toDataType(key)); } void archive (string value, string key, size_t id) { archiveString(value, key, id); } void archive (wstring value, string key, size_t id) { archiveString(value, key, id); } void archive (dstring value, string key, size_t id) { archiveString(value, key, id); } private void archiveString (T) (T value, string key, size_t id) { alias BaseTypeOfArray!(T) ArrayBaseType; auto array = Array(value.ptr, value.length, ArrayBaseType.sizeof); internalArchiveArray(ArrayBaseType.stringof, array, key, id, Tags.stringTag, toDataType(value)); } void archive (bool value, string key, size_t id) { archivePrimitive (value, key); } void archive (byte value, string key, size_t id) { archivePrimitive (value, key); } void archive (cdouble value, string key, size_t id) { archivePrimitive (value, key); } /*void archive (cent value, string key, size_t id) { archivePrimitive (value, key); }*/ void archive (cfloat value, string key, size_t id) { archivePrimitive (value, key); } void archive (char value, string key, size_t id) { archivePrimitive (value, key); } void archive (creal value, string key, size_t id) { archivePrimitive (value, key); } void archive (dchar value, string key, size_t id) { archivePrimitive (value, key); } void archive (double value, string key, size_t id) { archivePrimitive (value, key); } void archive (float value, string key, size_t id) { archivePrimitive (value, key); } void archive (idouble value, string key, size_t id) { archivePrimitive (value, key); } void archive (ifloat value, string key, size_t id) { archivePrimitive (value, key); } void archive (int value, string key, size_t id) { archivePrimitive (value, key); } void archive (ireal value, string key, size_t id) { archivePrimitive (value, key); } void archive (long value, string key, size_t id) { archivePrimitive (value, key); } void archive (real value, string key, size_t id) { archivePrimitive (value, key); } void archive (short value, string key, size_t id) { archivePrimitive (value, key); } void archive (ubyte value, string key, size_t id) { archivePrimitive (value, key); } /*void archive (ucent value, string key, size_t id) { archivePrimitive (value, key); }*/ void archive (uint value, string key, size_t id) { archivePrimitive (value, key); } void archive (ulong value, string key, size_t id) { archivePrimitive (value, key); } void archive (ushort value, string key, size_t id) { archivePrimitive (value, key); } void archive (wchar value, string key, size_t id) { archivePrimitive (value, key); } private void archivePrimitive (T) (T value, string key) { lastElement.element(toDataType(T.stringof), toDataType(value)) .attribute(Attributes.keyAttribute, toDataType(key)); } private void addArchivedArray (doc.Node parent, doc.Node lastElement, size_t id, string key, size_t elementSize, ) { arraysToBeArchived[Array(value)] = ArrayNode(parent, lastElement, id, key); } }