# HG changeset patch # User Jacob Carlborg # Date 1286308786 -7200 # Node ID 55f0a9d5df8d46892eb81c99592a49cd56389b7f # Parent 947c32ec0ea7eb90fea7672c0f7ce52ea4c329ff First step in refactoring the API. diff -r 947c32ec0ea7 -r 55f0a9d5df8d orange/serialization/archives/Archive.d --- a/orange/serialization/archives/Archive.d Mon Oct 04 20:45:32 2010 +0200 +++ b/orange/serialization/archives/Archive.d Tue Oct 05 21:59:46 2010 +0200 @@ -16,29 +16,102 @@ } import orange.serialization.archives.ArchiveException; +import orange.util.string; + +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; - void* ptr; - - static Slice opCall (T) (T[] value) - { - Slice slice; - slice.length = value.length; - slice.ptr = value.ptr; - - return slice; - } + size_t offset; + size_t id; } interface IArchive { + version (Tango) alias void[] IDataType; + else mixin ("alias immutable(void)[] IDataType;"); + void beginArchiving (); + void beginUnarchiving (IDataType data); + + IDataType data (); + void postProcess (); void reset (); + + void archiveArray (string type, size_t length, size_t elementSize, string key, size_t id); + void archiveAssociativeArray (string keyType, string valueType, size_t length, string key, size_t id); + + void archiveEnum (bool value, string key, size_t id); + void archiveEnum (byte value, string key, size_t id); + void archiveEnum (char value, string key, size_t id); + void archiveEnum (dchar value, string key, size_t id); + void archiveEnum (int value, string key, size_t id); + void archiveEnum (long value, string key, size_t id); + void archiveEnum (short value, string key, size_t id); + void archiveEnum (ubyte value, string key, size_t id); + void archiveEnum (uint value, string key, size_t id); + void archiveEnum (ulong value, string key, size_t id); + void archiveEnum (ushort value, string key, size_t id); + void archiveEnum (wchar value, string key, size_t id); + + void archiveNull (string type, string key); + void archiveObject (string runtimeType, string type, string key, size_t id); + void archivePointer (string key, size_t id); + void archiveReference (string key, size_t id); + //void archiveSlice (size_t length, size_t offset, string key, size_t id); + void archiveStruct (string type, string key, size_t id); + void archiveTypedef (string type, string key, size_t id); + + void archive (string value, string key, size_t id); + void archive (wstring value, string key, size_t id); + void archive (dstring value, string key, size_t id); + void archive (bool value, string key, size_t id); + void archive (byte value, string key, size_t id); + void archive (cdouble value, string key, size_t id); + //void archive (cent value, string key, size_t id); + void archive (cfloat value, string key, size_t id); + void archive (char value, string key, size_t id); + void archive (creal value, string key, size_t id); + void archive (dchar value, string key, size_t id); + void archive (double value, string key, size_t id); + void archive (float value, string key, size_t id); + void archive (idouble value, string key, size_t id); + void archive (ifloat value, string key, size_t id); + void archive (int value, string key, size_t id); + void archive (ireal value, string key, size_t id); + void archive (long value, string key, size_t id); + void archive (real value, string key, size_t id); + void archive (short value, string key, size_t id); + void archive (ubyte value, string key, size_t id); + //void archive (ucent value, string key, size_t id); + void archive (uint value, string key, size_t id); + void archive (ulong value, string key, size_t id); + void archive (ushort value, string key, size_t id); + void archive (wchar value, string key, size_t id); } -abstract class Archive (U) : IArchive +abstract class Archive (U) //: IArchive { version (Tango) alias U[] DataType; else mixin ("alias immutable(U)[] DataType;"); @@ -47,11 +120,6 @@ ErrorCallback errorCallback; - abstract void beginArchiving (); - abstract void beginUnarchiving (DataType data); - abstract DataType data (); - abstract void reset (); - protected DataType toDataType (T) (T value) { try diff -r 947c32ec0ea7 -r 55f0a9d5df8d orange/serialization/archives/XMLArchive.d --- a/orange/serialization/archives/XMLArchive.d Mon Oct 04 20:45:32 2010 +0200 +++ b/orange/serialization/archives/XMLArchive.d Tue Oct 05 21:59:46 2010 +0200 @@ -16,16 +16,8 @@ import orange.util._; import orange.xml.XMLDocument; -private enum ArchiveMode +final class XMLArchive (U = char) : Archive!(U) { - archiving, - unarchiving -} - -class XMLArchive (U = char) : Archive!(U) -{ - static assert (isChar!(U), format!(`The given type "`, U, `" is not a valid type. Valid types are: "char", "wchar" and "dchar".`)); - private struct Tags { static const DataType structTag = "struct"; @@ -59,65 +51,22 @@ 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"; XMLDocument!(U) doc; doc.Node lastElement; - //DocPrinter!(U) printer; - doc.Node lastElementSaved; bool hasBegunArchiving; bool hasBegunUnarchiving; - DataType[void*] archivedReferences; - void*[DataType] unarchivedReferences; - ArrayNode[Array] arraysToBeArchived; void[][DataType] unarchivedSlices; - - size_t idCounter; } - this () + this (ErrorCallback errorCallback) { + this.errorCallback = errorCallback; doc = new XMLDocument!(U); } @@ -135,8 +84,10 @@ } } - public void beginUnarchiving (DataType data) + public void beginUnarchiving (IDataType untypedData) { + auto data = cast(DataType) untypedData; + if (!hasBegunUnarchiving) { doc.parse(data); @@ -161,630 +112,12 @@ } } - public DataType data () + IDataType data () { - /*if (!printer) - printer = new DocPrinter!(U); - - return printer.print(doc);*/ - return doc.toString(); } - public void reset () - { - hasBegunArchiving = false; - hasBegunUnarchiving = false; - idCounter = 0; - doc.reset; - } - - private void begin () - { - lastElementSaved = lastElement; - } - - private void end () - { - lastElement = lastElementSaved; - } - - public void archive (T) (T value, DataType key, void delegate () dg = null) - { - if (!hasBegunArchiving) - beginArchiving(); - - restore(lastElement) in { - bool callDelegate = true; - - static if (isTypeDef!(T)) - archiveTypeDef(value, key); - - else static if (isObject!(T)) - archiveObject(value, key, callDelegate); - - else static if (isStruct!(T)) - archiveStruct(value, key); - - else static if (isString!(T)) - archiveString(value, key); - - else static if (isArray!(T)) - archiveArray(value, key); - - else static if (isAssociativeArray!(T)) - archiveAssociativeArray(value, key); - - else static if (isPrimitive!(T)) - archivePrimitive(value, key); - - else static if (isPointer!(T)) - archivePointer(value, key, callDelegate); - - else static if (isEnum!(T)) - archiveEnum(value, key); - - else - static assert(false, format!(`The type "`, T, `" cannot be archived.`)); - - if (callDelegate && dg) - dg(); - }; - } - - private void archiveObject (T) (T value, DataType key, ref bool callDelegate) - { - if (!value) - { - lastElement.element(Tags.nullTag) - .attribute(Attributes.typeAttribute, toDataType(T.stringof)) - .attribute(Attributes.keyAttribute, key); - callDelegate = false; - } - - else if (auto reference = getArchivedReference(value)) - { - archiveReference(key, reference); - callDelegate = false; - } - - else - { - DataType id = nextId; - - lastElement = lastElement.element(Tags.objectTag) - .attribute(Attributes.runtimeTypeAttribute, toDataType(value.classinfo.name)) - .attribute(Attributes.typeAttribute, toDataType(T.stringof)) - .attribute(Attributes.keyAttribute, key) - .attribute(Attributes.idAttribute, id); - - addArchivedReference(value, id); - } - } - - private void archiveStruct (T) (T value, DataType key) - { - lastElement = lastElement.element(Tags.structTag) - .attribute(Attributes.typeAttribute, toDataType(T.stringof)) - .attribute(Attributes.keyAttribute, key); - } - - private void archiveString (T) (T value, DataType key) - { - archiveArrayImpl(value, key, Tags.stringTag, toDataType(value)); - } - - private void archiveArray (T) (T value, DataType key) - { - 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.idAttribute, id); - - arraysToBeArchived[Array(value)] = ArrayNode(parent, lastElement, id, key); - } - - private void archiveAssociativeArray (T) (T value, DataType key) - { - lastElement = lastElement.element(Tags.associativeArrayTag) - .attribute(Attributes.keyTypeAttribute, toDataType(KeyTypeOfAssociativeArray!(T).stringof)) - .attribute(Attributes.valueTypeAttribute, toDataType(ValueTypeOfAssociativeArray!(T).stringof)) - .attribute(Attributes.lengthAttribute, toDataType(value.length)) - .attribute(Attributes.keyAttribute, key); - } - - private void archivePointer (T) (T value, DataType key, ref bool callDelegate) - { - if (auto reference = getArchivedReference(value)) - { - archiveReference(key, reference); - callDelegate = false; - } - - else - { - DataType id = nextId; - - lastElement = lastElement.element(Tags.pointerTag) - .attribute(Attributes.keyAttribute, key) - .attribute(Attributes.idAttribute, id); - - addArchivedReference(value, id); - } - } - - private void archiveEnum (T) (T value, DataType key) - { - lastElement.element(Tags.enumTag, toDataType(value)) - .attribute(Attributes.typeAttribute, toDataType(T.stringof)) - .attribute(Attributes.keyAttribute, key); - } - - private void archivePrimitive (T) (T value, DataType key) - { - lastElement.element(toDataType(T.stringof), toDataType(value)) - .attribute(Attributes.keyAttribute, key); - } - - private void archiveTypeDef (T) (T value, DataType key) - { - lastElement = lastElement.element(Tags.typedefTag) - .attribute(Attributes.typeAttribute, toDataType(BaseTypeOfTypeDef!(T).stringof)); - .attribute(Attributes.key, key); - } - - public T unarchive (T) (DataType key, T delegate (T) dg = null) - { - if (!hasBegunUnarchiving) - beginUnarchiving(data); - - return restore!(T)(lastElement) in { - T value; - - bool callDelegate = true; - - static if (isTypeDef!(T)) - value = unarchiveTypeDef!(T)(key); - - else static if (isObject!(T)) - value = unarchiveObject!(T)(key, callDelegate); - - else static if (isStruct!(T)) - value = unarchiveStruct!(T)(key); - - else static if (isString!(T)) - value = unarchiveString!(T)(key); - - else static if (isArray!(T)) - value = unarchiveArray!(T)(key, callDelegate); - - else static if (isAssociativeArray!(T)) - value = unarchiveAssociativeArray!(T)(key); - - else static if (isPrimitive!(T)) - value = unarchivePrimitive!(T)(key); - - else static if (isPointer!(T)) - value = unarchivePointer!(T)(key, callDelegate); - - else static if (isEnum!(T)) - value = unarchiveEnum!(T)(key); - - else - static assert(false, format!(`The type "`, T, `" cannot be unarchived.`)); - - if (callDelegate && dg) - return dg(value); - - return value; - }; - } - - private T unarchiveObject (T) (DataType key, ref bool callDelegate) - { - DataType id = unarchiveReference(key); - - if (auto reference = getUnarchivedReference!(T)(id)) - { - callDelegate = false; - return *reference; - } - - auto tmp = getElement(Tags.objectTag, key, Attributes.keyAttribute, false); - - if (!tmp.isValid) - { - lastElement = getElement(Tags.nullTag, key); - callDelegate = false; - return null; - } - - lastElement = tmp; - - auto runtimeType = getValueOfAttribute(Attributes.runtimeTypeAttribute); - - if (!runtimeType) - return T.init; - - auto name = fromDataType!(string)(runtimeType); - id = getValueOfAttribute(Attributes.idAttribute); - - if (!id) - return T.init; - - T result = cast(T) newInstance(name); - - addUnarchivedReference(result, id); - - return result; - } - - private T unarchiveStruct (T) (DataType key) - { - auto element = getElement(Tags.structTag, key); - - if (element.isValid) - lastElement = element; - - return T.init; - } - - 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; - - 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, 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); - - if (!element.isValid) - return T.init; - - lastElement = element; - auto length = getValueOfAttribute(Attributes.lengthAttribute); - - if (!length) - 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; - } - - private T unarchiveAssociativeArray (T) (DataType key) - { - auto element = getElement(Tags.associativeArrayTag, key); - - if (element.isValid) - lastElement = element; - - return T.init; - } - - private T unarchivePointer (T) (DataType key, ref bool callDelegate) - { - DataType id = unarchiveReference(key); - - if (auto reference = getUnarchivedReference!(T)(id)) - { - callDelegate = false; - return *reference; - } - - auto element = getElement(Tags.pointerTag, key); - - if (!element.isValid) - return T.init; - - lastElement = element; - id = getValueOfAttribute(Attributes.idAttribute); - - if (!id) - return T.init; - - T result = new BaseTypeOfPointer!(T); - - addUnarchivedReference(result, id); - - return result; - } - - private T unarchiveEnum (T) (DataType key) - { - auto element = getElement(Tags.enumTag, key); - - if (!element.isValid) - return T.init; - - return fromDataType!(T)(element.value); - } - - private T unarchivePrimitive (T) (DataType key) - { - auto element = getElement(toDataType(T.stringof), key); - - if (!element.isValid) - return T.init; - - return fromDataType!(T)(element.value); - } - - private T unarchiveTypeDef (T) (DataType key) - { - auto element = getElement(Tags.typedefTag, key); - - if (element.isValid) - lastElement = element; - - return T.init; - } - - public AssociativeArrayVisitor!(KeyTypeOfAssociativeArray!(T), ValueTypeOfAssociativeArray!(T)) unarchiveAssociativeArrayVisitor (T) () - { - return AssociativeArrayVisitor!(KeyTypeOfAssociativeArray!(T), ValueTypeOfAssociativeArray!(T))(this); - } - - public void archiveBaseClass (T : Object) (DataType key) - { - lastElement = lastElement.element(Tags.baseTag) - .attribute(Attributes.typeAttribute, toDataType(T.stringof)) - .attribute(Attributes.keyAttribute, key); - } - - public void unarchiveBaseClass (T : Object) (DataType key) - { - auto element = getElement(Tags.baseTag, key); - - if (element.isValid) - lastElement = element; - } - - version (Tango) - { - template errorMessage (ArchiveMode mode = ArchiveMode.archiving) - { - static if (mode == ArchiveMode.archiving) - const errorMessage = "Could not continue archiving due to unrecognized data format: "; - - else static if (mode == ArchiveMode.unarchiving) - const errorMessage = "Could not continue unarchiving due to unrecognized data format: "; - } - } - - else - { - mixin( - `template errorMessage (ArchiveMode mode = ArchiveMode.archiving) - { - static if (mode == ArchiveMode.archiving) - enum errorMessage = "Could not continue archiving due to unrecognized data format: "; - - else static if (mode == ArchiveMode.unarchiving) - enum errorMessage = "Could not continue unarchiving due to unrecognized data format: "; - }` - ); - } - - private doc.Node getElement (DataType tag, DataType key, DataType attribute = Attributes.keyAttribute, bool throwOnError = true) - { - auto set = lastElement.query[tag].attribute((doc.Node node) { - if (node.name == attribute && node.value == key) - return true; - - return false; - }); - - if (set.nodes.length == 1) - return set.nodes[0].parent; - - else - { - if (throwOnError && errorCallback) - { - if (set.nodes.length == 0) - errorCallback(new ArchiveException(`Could not find an element "` ~ to!(string)(tag) ~ `" with the attribute "` ~ to!(string)(Attributes.keyAttribute) ~ `" with the value "` ~ to!(string)(key) ~ `".`, __FILE__, __LINE__), [tag, Attributes.keyAttribute, key]); - - else - errorCallback(new ArchiveException(`Could not unarchive the value with the key "` ~ to!(string)(key) ~ `" due to malformed data.`, __FILE__, __LINE__), [tag, Attributes.keyAttribute, key]); - } - - return doc.Node.invalid; - } - } - - private DataType getValueOfAttribute (DataType attribute, doc.Node element = doc.Node.invalid) - { - if (!element.isValid) element = lastElement; - - auto set = element.query.attribute(attribute); - - if (set.nodes.length == 1) - return set.nodes[0].value; - - else - { - if (errorCallback) - { - if (set.nodes.length == 0) - errorCallback(new ArchiveException(`Could not find the attribute "` ~ to!(string)(attribute) ~ `".`, __FILE__, __LINE__), [attribute]); - - else - errorCallback(new ArchiveException(`Could not unarchive the value of the attribute "` ~ to!(string)(attribute) ~ `" due to malformed data.`, __FILE__, __LINE__), [attribute]); - } - } - - return null; - } - - private void addArchivedReference (T) (T value, DataType id) - { - static assert(isReference!(T), format!(`The given type "`, T, `" is not a reference type, i.e. object or pointer.`)); - - archivedReferences[cast(void*) value] = id; - } - - private void addUnarchivedReference (T) (T value, DataType id) - { - static assert(isReference!(T), format!(`The given type "`, T, `" is not a reference type, i.e. object or pointer.`)); - - 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) - return *tmp; - - return null; - } - - private T* getUnarchivedReference (T) (DataType id) - { - if (auto reference = id in unarchivedReferences) - return cast(T*) reference; - - 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++); - } - - private void archiveReference (DataType key, DataType id) - { - lastElement.element(Tags.referenceTag, id) - .attribute(Attributes.keyAttribute, key); - } - - private DataType unarchiveReference (DataType key) - { - auto element = getElement(Tags.referenceTag, key, Attributes.keyAttribute, false); - - if (element.isValid) - return element.value; - - 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; - - static AssociativeArrayVisitor opCall (XMLArchive archive) - { - AssociativeArrayVisitor aai; - aai.archive = archive; - - return aai; - } - - int opApply(int delegate(ref Key, ref Value) dg) - { - int result; - - foreach (node ; archive.lastElement.children) - { - restore(archive.lastElement) in { - archive.lastElement = node; - - if (node.attributes.exist) - { - Key key = to!(Key)(archive.getValueOfAttribute(Attributes.keyAttribute)); - Value value = to!(Value)(node.value); - - result = dg(key, value); - } - }; - - if (result) - break; - } - - return result; - } - } - - public void postProcess () + void postProcess () { bool foundSlice = true; @@ -810,5 +143,309 @@ 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); } } \ No newline at end of file