changeset 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 947c32ec0ea7
children b51e953f79eb
files orange/serialization/archives/Archive.d orange/serialization/archives/XMLArchive.d
diffstat 2 files changed, 396 insertions(+), 691 deletions(-) [+]
line wrap: on
line diff
--- 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
--- 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