changeset 26:78e5fef4bbf2 experimental

Third step in refactoring the API. Stating to add unit tests.
author Jacob Carlborg <doob@me.com>
date Tue, 19 Oct 2010 10:22:10 +0200
parents b51e953f79eb
children fc315d786f24
files dsss.conf orange/core/_.d orange/core/io.d orange/core/string.d orange/serialization/RegisterWrapper.d orange/serialization/SerializationException.d orange/serialization/Serializer orange/serialization/Serializer.d orange/serialization/archives/Archive.d orange/serialization/archives/ArchiveException.d orange/serialization/archives/XMLArchive.d orange/test/UnitTester.d orange/util/CTFE.d orange/util/Reflection.d orange/util/Traits.d orange/util/Use.d orange/util/_.d orange/util/io.d orange/util/string.d orange/xml/XMLDocument.d
diffstat 20 files changed, 3069 insertions(+), 1320 deletions(-) [+]
line wrap: on
line diff
--- a/dsss.conf	Wed Oct 06 16:18:02 2010 +0200
+++ b/dsss.conf	Tue Oct 19 10:22:10 2010 +0200
@@ -1,1 +1,3 @@
-[main.d]
\ No newline at end of file
+#[orange/serialization/Serializer.d]
+[main.d]
+#[orange]
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/orange/core/_.d	Tue Oct 19 10:22:10 2010 +0200
@@ -0,0 +1,12 @@
+/**
+ * Copyright: Copyright (c) 2010 Jacob Carlborg. All rights reserved.
+ * Authors: Jacob Carlborg
+ * Version: Initial created: Oct 17, 2010
+ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
+ */
+module orange.core._;
+
+public:
+
+import orange.core.io;
+import orange.core.string;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/orange/core/io.d	Tue Oct 19 10:22:10 2010 +0200
@@ -0,0 +1,66 @@
+/**
+ * Copyright: Copyright (c) 2007-2008 Jacob Carlborg. All rights reserved.
+ * Authors: Jacob Carlborg
+ * Version: Initial created: 2007
+ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
+ * 
+ */
+module orange.core.io;
+
+version (Tango)
+{
+	import tango.io.Stdout;
+	import tango.io.Console;
+	
+	import orange.core.string;
+}
+
+else 
+	import std.stdio;
+
+/**
+ * Print to the standard output
+ * 
+ * Params:
+ *     args = what to print
+ */
+void print (A...)(A args)
+{
+	version (Tango)
+	{
+		const string fmt = "{}{}{}{}{}{}{}{}"
+					        "{}{}{}{}{}{}{}{}"
+					        "{}{}{}{}{}{}{}{}";
+				
+		static assert (A.length <= fmt.length / 2, "mambo.io.print :: too many arguments");
+		
+		Stdout.format(fmt[0 .. args.length * 2], args).flush;
+	}
+		
+	
+	else
+		write(args);
+}
+
+/**
+ * Print to the standard output, adds a new line
+ * 
+ * Params:
+ *     args = what to print
+ */
+void println (A...)(A args)
+{
+	version (Tango)
+	{
+		const string fmt = "{}{}{}{}{}{}{}{}"
+					        "{}{}{}{}{}{}{}{}"
+					        "{}{}{}{}{}{}{}{}";
+
+		static assert (A.length <= fmt.length / 2, "mambo.io.println :: too many arguments");
+		
+		Stdout.formatln(fmt[0 .. args.length * 2], args);
+	}
+
+	else
+		writeln(args);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/orange/core/string.d	Tue Oct 19 10:22:10 2010 +0200
@@ -0,0 +1,888 @@
+/**
+ * Copyright: Copyright (c) 2008-2009 Jacob Carlborg. All rights reserved.
+ * Authors: Jacob Carlborg
+ * Version: Initial created: 2008
+ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
+ * 
+ */
+module orange.core.string;
+
+public import orange.util.collection.Array;
+
+version (Tango)
+{
+	static import tango.stdc.stringz;
+	import tango.text.Unicode : toFold, isDigit;
+	import tango.text.convert.Utf;
+	import tango.text.Util;
+	
+	alias tango.stdc.stringz.toStringz toStringz;
+	alias tango.stdc.stringz.toString16z toString16z;
+	alias tango.stdc.stringz.toString32z toString32z;
+	
+	alias tango.stdc.stringz.fromStringz fromStringz;
+	alias tango.stdc.stringz.fromString16z fromString16z;
+	alias tango.stdc.stringz.fromString32z fromString32z;
+	
+	alias tango.text.convert.Utf.toString16 toString16;
+	alias tango.text.convert.Utf.toString32 toString32;
+}
+
+else
+{	
+	import std.string;
+	import std.utf;
+	import std.ctype : isxdigit;
+	
+	version = Phobos;
+	
+	private alias std.string.tolower toFold;
+	
+	alias std.utf.toUTF8 toString;
+	alias std.utf.toUTF16 toString16;
+	alias std.utf.toUTF32 toString32;
+	
+	alias std.string.toStringz toStringz;
+	alias std.utf.toUTF16z toString16z;
+	
+	alias std.string.toString fromStringz;
+}
+
+version (Tango)
+{
+	/**
+	 * string alias
+	 */
+	alias char[] string;
+
+	/**
+	 * wstring alias
+	 */
+	alias wchar[] wstring;
+
+	/**
+	 * dstring alias
+	 */
+	alias dchar[] dstring;
+}
+
+/**
+ * Compares the $(D_PSYMBOL string) to another $(D_PSYMBOL string), ignoring case
+ * considerations.  Two strings are considered equal ignoring case if they are of the
+ * same length and corresponding characters in the two strings  are equal ignoring case.
+ * 
+ * Params:
+ *     str = The $(D_PSYMBOL string) first string to compare to
+ *     anotherString = The $(D_PSYMBOL string) to compare the first $(D_PSYMBOL string) with
+ *     
+ * Returns: $(D_KEYWORD true) if the arguments is not $(D_KEYWORD null) and it
+ *          represents an equivalent $(D_PSYMBOL string) ignoring case; $(D_KEYWORD false) otherwise
+ *          
+ * Throws: AssertException if the length of any of the strings is 0
+ *          
+ * See_Also: opEquals(Object)
+ */
+bool equalsIgnoreCase (string str, string anotherString)
+in
+{
+	assert(str.length > 0, "mambo.string.equalsIgnoreCase: The length of the first string was 0");
+	assert(anotherString.length > 0, "mambo.string.equalsIgnoreCase: The length of the second string was 0");
+}
+body
+{	
+	if (str == anotherString)
+		return true;
+
+	return toFold(str) == toFold(anotherString);
+}
+
+/**
+ * Compares the $(D_PSYMBOL wstring) to another $(D_PSYMBOL wstring), ignoring case
+ * considerations. Two wstrings are considered equal ignoring case if they are of the
+ * same length and corresponding characters in the two wstrings are equal ignoring case.
+ * 
+ * Params:
+ *     str = The $(D_PSYMBOL wstring) first string to compre to
+ *     anotherString = The $(D_PSYMBOL wstring) to compare the first $(D_PSYMBOL wstring) against
+ *     
+ * Returns: $(D_KEYWORD true) if the argument is not $(D_KEYWORD null) and it
+ *          represents an equivalent $(D_PSYMBOL wstring) ignoring case; (D_KEYWORD
+ *          false) otherwise
+ *          
+ * Throws: AssertException if the length of any of the wstrings is 0
+ *          
+ * See_Also: opEquals(Object)
+ */
+bool equalsIgnoreCase (wstring str, wstring anotherString)
+in
+{
+	assert(str.length > 0, "mambo.string.equalsIgnoreCase: The length of the first string was 0");
+	assert(anotherString.length > 0, "mambo.string.equalsIgnoreCase: The length of the second string was 0");
+}
+body
+{
+	if (str == anotherString)
+		return true;
+
+	version (Tango)
+		return toFold(str) == toFold(anotherString);
+
+	else
+		return toFold(toUTF8(str)) == toFold(toUTF8(anotherString));
+}
+
+/**
+ * Compares the $(D_PSYMBOL dstring) to another $(D_PSYMBOL dstring), ignoring case
+ * considerations. Two wstrings are considered equal ignoring case if they are of the
+ * same length and corresponding characters in the two wstrings are equal ignoring case.
+ * 
+ * Params:
+ *     str = The $(D_PSYMBOL dstring) first string to compare to
+ *     anotherString = The $(D_PSYMBOL wstring) to compare the first $(D_PSYMBOL dstring) against
+ *     
+ * Returns: $(D_KEYWORD true) if the argument is not $(D_KEYWORD null) and it
+ *          represents an equivalent $(D_PSYMBOL dstring) ignoring case; $(D_KEYWORD false) otherwise
+ *          
+ * Throws: AssertException if the length of any of the dstrings are 0
+ *          
+ * See_Also: opEquals(Object)
+ */
+bool equalsIgnoreCase (dstring str, dstring anotherString)
+in
+{
+	assert(str.length > 0, "mambo.string.equalsIgnoreCase: The length of the first string was 0");
+	assert(anotherString.length > 0, "mambo.string.equalsIgnoreCase: The length of the second string was 0");
+}
+body
+{
+	if (str == anotherString)
+		return true;
+
+	version (Tango)
+		return toFold(str) == toFold(anotherString);
+
+	else
+		return toFold(toUTF8(str)) == toFold(toUTF8(anotherString));
+}
+
+/**
+ * Returns the char value at the specified index. An index ranges from 0 to length - 1.
+ * The first $(D_KEYWORD char) value of the sequence is at index 0, the next at index 1,
+ * and so on, as for array indexing.
+ * 
+ * Params:
+ * 	   str = the string to get the $(D_KEYWORD char) from
+ *     index = the index of the $(D_KEYWORD char) value.
+ *     
+ * Returns: the $(D_KEYWORD char) value at the specified index of the string.
+ *          The first $(D_KEYWORD char) value is at index 0.
+ * 
+ * Throws: AssertException if the length of the string is 0
+ * Throws: AssertException if the $(D_CODE index) argument is
+ *         not less than the length of the string.
+ */
+char charAt (string str, size_t index)
+in
+{
+	assert(str.length > 0, "mambo.string.charAt: The length of the string was 0");
+	assert(index <= str.length, "mambo.string.charAt: The index was to greater than the length of the string");
+}
+body
+{
+	return str[index];
+}
+
+/**
+ * Returns the $(D_KEYWORD char) value at the specified index. An index ranges from 0 to
+ * length - 1. The first $(D_KEYWORD char) value of the sequence is at index 0, the next
+ * at index 1, and so on, as for array indexing.
+ * 
+ * Params:
+ * 	   str = the wstring to get the $(D_KEYWORD char) from
+ *     index = the index of the $(D_KEYWORD char) value.
+ *     
+ * Returns: the $(D_KEYWORD char) value at the specified index of the wstring.
+ *          The first $(D_KEYWORD char) value is at index 0.
+ * 
+ * Throws: AssertException if the length of the wstring is 0
+ * Throws: AssertException if the $(D_CODE index) argument is
+ *         not less than the length of the wstring.
+ */
+wchar charAt (wstring str, size_t index)
+in
+{
+	assert(str.length > 0, "mambo.string.charAt: The length of the string was 0");
+	assert(index <= str.length, "mambo.string.charAt: The index was to greater than the length of the string");
+}
+body
+{
+	return str[index];
+}
+
+/**
+ * Returns the $(D_KEYWORD char) value at the specified index. An index ranges from 0 to
+ * length - 1. The first $(D_KEYWORD char) value of the sequence is at index 0, the next
+ * at index 1, and so on, as for array indexing.
+ * 
+ * Params:
+ * 	   str = the dstring to get the $(D_KEYWORD char) from
+ *     index = the index of the $(D_KEYWORD char) value.
+ *     
+ * Returns: the $(D_KEYWORD char) value at the specified index of the dstring.
+ *          The first $(D_KEYWORD char) value is at index 0.
+ * 
+ * Throws: AssertException if the length of the dstring is 0
+ * Throws: AssertException if the $(D_CODE index) argument is
+ *         not less than the length of the dstring.
+ */
+dchar charAt (dstring str, size_t index)
+in
+{
+	assert(str.length > 0, "mambo.string.charAt: The length of the string was 0");
+	assert(index <= str.length, "mambo.string.charAt: The index was to greater than the length of the string");
+}
+body
+{
+	return str[index];
+}
+
+/**
+ * Returns a new string that is a substring of the specified string. The substring begins
+ * at the specified $(D_PARAM beginIndex) and extends to the character at index
+ * $(D_PARAM endIndex) - 1. Thus the length of the substring is $(D_PARAM endIndex - beginIndex).
+ * 
+ * Examples:
+ * ---
+ * "hamburger".substring(4, 8) returns "urge"
+ * "smiles".substring(1, 5) returns "mile"
+ * ---
+ * 
+ * Params:
+ * 	   str = the string to get the substring from
+ *     beginIndex = the beginning index, inclusive.
+ *     endIndex = the ending index, exclusive.
+ *     
+ * Returns: the specified substring.
+ * 
+ * Throws: AssertException if the length of the string is 0
+ * Throws: AssertException if the $(D_PARAM beginIndex) is 
+ * 		   larger than $(D_PARAM endIndex).
+ * Throws: AssertException if $(D_PARAM endIndex) is larger than the 
+ *  	   length of the $(D_PSYMBOL string).
+ */
+string substring (string str, size_t beginIndex, size_t endIndex)
+in
+{
+	assert(str.length > 0, "mambo.string.substring: The length of the string was 0");
+	assert(beginIndex < endIndex, "mambo.string.substring: The first index was greater the second");
+	assert(endIndex <= str.length, "mambo.string.substring: The second index was greater then the length of the string");
+}
+body
+{
+	version (Tango) return str[beginIndex .. endIndex].dup;
+	else return str[beginIndex .. endIndex].idup;
+}
+
+/**
+ * Returns a new string that is a substring of the specified string. The substring begins
+ * at the specified $(D_PARAM beginIndex) and extends to the character at index
+ * $(D_PARAM endIndex) - 1. Thus the length of the substring is $(D_PARAM endIndex - beginIndex).
+ * 
+ * Examples:
+ * ---
+ * "hamburger".substring(4, 8) returns "urge"
+ * "smiles".substring(1, 5) returns "mile"
+ * ---
+ * 
+ * Params:
+ * 	   str = the string to get the substring from
+ *     beginIndex = the beginning index, inclusive.
+ *     endIndex = the ending index, exclusive.
+ *     
+ * Returns: the specified substring.
+ * 
+ * Throws: AssertException if the length of the string is 0
+ * Throws: AssertException if the $(D_PARAM beginIndex) is 
+ * 		   larger than $(D_PARAM endIndex).
+ * Throws: AssertException if $(D_PARAM endIndex) is larger than the 
+ *  	   length of the $(D_PSYMBOL string).
+ */
+wstring substring (wstring str, size_t beginIndex, size_t endIndex)
+in
+{
+	assert(str.length > 0, "mambo.string.substring: The length of the string was 0");
+	assert(beginIndex < endIndex, "mambo.string.substring: The first index was greater the second");
+	assert(endIndex <= str.length, "mambo.string.substring: The second index was greater then the length of the string");
+}
+body
+{
+	version (Tango) return str[beginIndex .. endIndex].dup;
+	else return str[beginIndex .. endIndex].idup;
+}
+
+/**
+ * Returns a new string that is a substring of the specified string. The substring begins
+ * at the specified $(D_PARAM beginIndex) and extends to the character at index
+ * $(D_PARAM endIndex) - 1. Thus the length of the substring is $(D_PARAM endIndex - beginIndex).
+ * 
+ * Examples:
+ * ---
+ * "hamburger".substring(4, 8) returns "urge"
+ * "smiles".substring(1, 5) returns "mile"
+ * ---
+ * 
+ * Params:
+ * 	   str = the string to get the substring from
+ *     beginIndex = the beginning index, inclusive.
+ *     endIndex = the ending index, exclusive.
+ *     
+ * Returns: the specified substring.
+ * 
+ * Throws: AssertException if the length of the string is 0
+ * Throws: AssertException if the $(D_PARAM beginIndex) is 
+ * 		   larger than $(D_PARAM endIndex).
+ * Throws: AssertException if $(D_PARAM endIndex) is larger than the 
+ *  	   length of the $(D_PSYMBOL string).
+ */
+dstring substring (dstring str, size_t beginIndex, size_t endIndex)
+in
+{
+	assert(str.length > 0, "mambo.string.substring: The length of the string was 0");
+	assert(beginIndex < endIndex, "mambo.string.substring: The first index was greater the second");
+	assert(endIndex <= str.length, "mambo.string.substring: The second index was greater then the length of the string");
+}
+body
+{
+	version (Tango) return str[beginIndex .. endIndex].dup;
+	else return str[beginIndex .. endIndex].idup;
+}
+
+/**
+ * Returns a new string that is a substring of the specified string. The substring begins
+ * with the character at the specified index and extends to the end of the string. 
+ * 
+ * Examples:
+ * ---
+ * "unhappy".substring(2) returns "happy"
+ * "Harbison".substring(3) returns "bison"
+ * "emptiness".substring(9) returns "" (an empty string)
+ * ---
+ * 
+ * Params:
+ *     str = the string to get the substring from
+ *     beginIndex = the beginning index, inclusive
+ *     
+ * Returns: the specified substring
+ * 
+ * Throws: AssertException if the length of the string is 0
+ * Throws: AssertException if the $(D_PARAM beginIndex) is 
+ * 		   larger than the length of the string.
+ */
+string substring (string str, size_t index)
+in
+{
+	assert(str.length > 0, "mambo.string.substring: The length of the string was 0");
+	assert(index < str.length, "mambo.string.substring: The index was greater than the length of the string");
+}
+body
+{
+	return str.substring(index, str.length);
+}
+
+/**
+ * Returns a new string that is a substring of the specified string. The substring begins
+ * with the character at the specified index and extends to the end of the string. 
+ * 
+ * Examples:
+ * ---
+ * "unhappy".substring(2) returns "happy"
+ * "Harbison".substring(3) returns "bison"
+ * "emptiness".substring(9) returns "" (an empty string)
+ * ---
+ * 
+ * Params:
+ *     str = the string to get the substring from
+ *     beginIndex = the beginning index, inclusive
+ *     
+ * Returns: the specified substring
+ * 
+ * Throws: AssertException if the length of the string is 0
+ * Throws: AssertException if the $(D_PARAM beginIndex) is 
+ * 		   larger than the length of the string.
+ */
+wstring substring (wstring str, size_t index)
+in
+{
+	assert(str.length > 0, "mambo.string.substring: The length of the string was 0");
+	assert(index < str.length, "mambo.string.substring: The index was greater than the length of the string");
+}
+body
+{
+	return str.substring(index, str.length);
+}
+
+/**
+ * Returns a new string that is a substring of the specified string. The substring begins
+ * with the character at the specified index and extends to the end of the string. 
+ * 
+ * Examples:
+ * ---
+ * "unhappy".substring(2) returns "happy"
+ * "Harbison".substring(3) returns "bison"
+ * "emptiness".substring(9) returns "" (an empty string)
+ * ---
+ * 
+ * Params:
+ *     str = the string to get the substring from
+ *     beginIndex = the beginning index, inclusive
+ *     
+ * Returns: the specified substring
+ * 
+ * Throws: AssertException if the length of the string is 0
+ * Throws: AssertException if the $(D_PARAM beginIndex) is 
+ * 		   larger than the length of the string.
+ */
+dstring substring (dstring str, size_t index)
+in
+{
+	assert(str.length > 0, "mambo.string.substring: The length of the string was 0");
+	assert(index < str.length, "mambo.string.substring: The index was greater than the length of the string");
+}
+body
+{
+	return str.substring(index, str.length);
+}
+
+/**
+ * Returns a new string that is a substring of the given string.
+ * 
+ * This substring is the character sequence that starts at character
+ * position pos and has a length of n characters.
+ * 
+ * Params:
+ *     str = the string to get the substring from
+ *     pos = position of a character in the current string to be used 
+ *     		 as starting character for the substring.
+ *     n = Length of the substring. If this value would make the 
+ *     	   substring to span past the end of the current string content,
+ *     	   only those characters until the end of the string are used. 
+ *     	   size_t.max is the greatest possible value for an element of
+ *     	   type size_t, therefore, when this value is used, all the
+ *     	   characters between pos and the end of the string are used as
+ *     	   the initialization substring.
+ *     
+ * Returns: a string containing a substring of the given string
+ * 
+ * Throws: AssertException if pos is greater than the length of the string
+ */
+string substr (string str, size_t pos = 0, size_t n = size_t.max)
+in
+{
+	assert(pos < str.length, "mambo.string.substr: The given position was greater than the length of the string.");
+}
+body
+{
+	size_t end;
+	
+	if (n == size_t.max)
+		end = str.length;
+	
+	else
+	{
+		end = pos + n;
+		
+		if (end > str.length)
+			end = str.length;
+	}
+	
+	version (Tango) return str[pos .. end].dup;
+	else return str[pos .. end].idup;
+}
+
+/**
+ * Returns a new string that is a substring of the given string.
+ * 
+ * This substring is the character sequence that starts at character
+ * position pos and has a length of n characters.
+ * 
+ * Params:
+ *     str = the string to get the substring from
+ *     pos = position of a character in the current string to be used 
+ *     		 as starting character for the substring.
+ *     n = Length of the substring. If this value would make the 
+ *     	   substring to span past the end of the current string content,
+ *     	   only those characters until the end of the string are used. 
+ *     	   size_t.max is the greatest possible value for an element of
+ *     	   type size_t, therefore, when this value is used, all the
+ *     	   characters between pos and the end of the string are used as
+ *     	   the initialization substring.
+ *     
+ * Returns: a string containing a substring of the given string
+ * 
+ * Throws: AssertException if pos is greater than the length of the string
+ */
+wstring substr (wstring str, size_t pos = 0, size_t n = size_t.max)
+in
+{
+	assert(pos < str.length, "mambo.string.substr: The given position was greater than the length of the string.");
+}
+body
+{
+	size_t end;
+	
+	if (n == size_t.max)
+		end = str.length;
+	
+	else
+	{
+		end = pos + n;
+		
+		if (end > str.length)
+			end = str.length;
+	}
+	
+	version (Tango) return str[pos .. end].dup;
+	else return str[pos .. end].idup;
+}
+
+/**
+ * Returns a new string that is a substring of the given string.
+ * 
+ * This substring is the character sequence that starts at character
+ * position pos and has a length of n characters.
+ * 
+ * Params:
+ *     str = the string to get the substring from
+ *     pos = position of a character in the current string to be used 
+ *     		 as starting character for the substring.
+ *     n = Length of the substring. If this value would make the 
+ *     	   substring to span past the end of the current string content,
+ *     	   only those characters until the end of the string are used. 
+ *     	   size_t.max is the greatest possible value for an element of
+ *     	   type size_t, therefore, when this value is used, all the
+ *     	   characters between pos and the end of the string are used as
+ *     	   the initialization substring.
+ *     
+ * Returns: a string containing a substring of the given string
+ * 
+ * Throws: AssertException if pos is greater than the length of the string
+ */
+dstring substr (dstring str, size_t pos = 0, size_t n = size_t.max)
+in
+{
+	assert(pos < str.length, "mambo.string.substr: The given position was greater than the length of the string.");
+}
+body
+{
+	size_t end;
+	
+	if (n == size_t.max)
+		end = str.length;
+	
+	else
+	{
+		end = pos + n;
+		
+		if (end > str.length)
+			end = str.length;
+	}
+	
+	version (Tango) return str[pos .. end].dup;
+	else return str[pos .. end].idup;
+}
+
+/**
+ * Finds the first occurence of sub in str
+ * 
+ * Params:
+ *     str = the string to find in
+ *     sub = the substring to find
+ *     start = where to start finding
+ *     
+ * Returns: the index of the substring or size_t.max when nothing was found
+ */
+size_t find (string str, string sub)
+{
+	version (Tango)
+	{
+		size_t index = str.locatePattern(sub);
+		
+		if (index == str.length)
+			return size_t.max;
+		
+		return index;
+	}
+	
+	else
+		return std.string.indexOf(str, sub);
+	
+}
+
+/**
+ * Finds the first occurence of sub in str
+ * 
+ * Params:
+ *     str = the string to find in
+ *     sub = the substring to find
+ *     start = where to start finding
+ *     
+ * Returns: the index of the substring or size_t.max when nothing was found
+ */
+size_t find (wstring str, wstring sub)
+{
+	version (Tango)
+	{
+		size_t index = str.locatePattern(sub);
+		
+		if (index == str.length)
+			return size_t.max;
+		
+		return index;
+	}
+	
+	else
+		return std.string.indexOf(str, sub);
+}
+
+/**
+ * Finds the first occurence of sub in str
+ * 
+ * Params:
+ *     str = the string to find in
+ *     sub = the substring to find
+ *     start = where to start finding
+ *     
+ * Returns: the index of the substring or size_t.max when nothing was found
+ */
+size_t find (dstring str, dstring sub)
+{
+	version (Tango)
+	{
+		size_t index = str.locatePattern(sub);
+		
+		if (index == str.length)
+			return size_t.max;
+		
+		return index;
+	}
+	
+	else
+		return std.string.indexOf(str, sub);
+}
+
+/**
+ * Compares to strings, ignoring case differences. Returns 0 if the content
+ * matches, less than zero if a is "less" than b, or greater than zero
+ * where a is "bigger".
+ * 
+ * Params:
+ *     a = the first array 
+ *     b = the second array
+ *     end = the index where the comparision will end
+ *     
+ * Returns: Returns 0 if the content matches, less than zero if a is 
+ * 			"less" than b, or greater than zero where a is "bigger".
+ * 
+ * See_Also: mambo.collection.array.compare
+ */
+int compareIgnoreCase (U = size_t) (string a, string b, U end = U.max)
+{
+	return a.toFold().compare(b.toFold(), end);
+}
+
+/**
+ * Compares to strings, ignoring case differences. Returns 0 if the content
+ * matches, less than zero if a is "less" than b, or greater than zero
+ * where a is "bigger".
+ * 
+ * Params:
+ *     a = the first array 
+ *     b = the second array
+ *     end = the index where the comparision will end
+ *     
+ * Returns: Returns 0 if the content matches, less than zero if a is 
+ * 			"less" than b, or greater than zero where a is "bigger".
+ * 
+ * See_Also: mambo.collection.array.compare
+ */
+int compareIgnoreCase (U = size_t) (wstring a, wstring b, U end = U.max)
+{
+	return a.toFold().compare(b.toFold(), end);
+}
+
+/**
+ * Compares to strings, ignoring case differences. Returns 0 if the content
+ * matches, less than zero if a is "less" than b, or greater than zero
+ * where a is "bigger".
+ * 
+ * Params:
+ *     a = the first array 
+ *     b = the second array
+ *     end = the index where the comparision will end
+ *     
+ * Returns: Returns 0 if the content matches, less than zero if a is 
+ * 			"less" than b, or greater than zero where a is "bigger".
+ * 
+ * See_Also: mambo.collection.array.compare
+ */
+int compareIgnoreCase (U = size_t) (dstring a, dstring b, U end = U.max)
+{
+	return a.toFold().compare(b.toFold(), end);
+}
+
+/**
+ * Compares to strings, ignoring case differences. Returns 0 if the content
+ * matches, less than zero if a is "less" than b, or greater than zero
+ * where a is "bigger".
+ * 
+ * Params:
+ *     a = the first array 
+ *     b = the second array
+ *     end = the index where the comparision will end
+ *     
+ * Returns: Returns 0 if the content matches, less than zero if a is 
+ * 			"less" than b, or greater than zero where a is "bigger".
+ * 
+ * See_Also: mambo.string.compareIgnoreCase
+ */
+alias compareIgnoreCase icompare;
+
+/**
+ * Checks if the given character is a hexdecimal digit character.
+ * Hexadecimal digits are any of: 0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F
+ * 
+ * Params:
+ *     ch = the character to be checked
+ *     
+ * Returns: true if the given character is a hexdecimal digit character otherwise false
+ */
+bool isHexDigit (dchar ch)
+{
+	version (Tango)
+	{
+		switch (ch)
+		{
+			case 'A': return true;				
+			case 'B': return true;
+			case 'C': return true;
+			case 'D': return true;
+			case 'E': return true;
+			case 'F': return true;
+			
+			case 'a': return true;
+			case 'b': return true;
+			case 'c': return true;
+			case 'd': return true;
+			case 'e': return true;
+			case 'f': return true;
+			
+			default: break;
+		}
+		
+		if (isDigit(ch))
+			return true;
+	}
+
+	else
+		if (isxdigit(ch) != 0)
+			return true;
+		
+	return false;
+}
+
+/*version (Tango)
+{
+	string toString (string str)
+	{
+		return str;
+	}
+	
+	string toString (wstring str)
+	{
+		return tango.text.convert.Utf.toString(str);
+	}
+	
+	string toString (dstring str)
+	{
+		return tango.text.convert.Utf.toString(str);
+	}
+}*/
+
+version (Phobos)
+{	
+	/**
+	 * Converts the given string to C-style 0 terminated string.
+	 * 
+	 * Params:
+	 *     str = the string to convert
+	 *     
+	 * Returns: the a C-style 0 terminated string.
+	 */
+	dchar* toString32z (dstring str)
+	{
+		return (str ~ '\0').dup.ptr;
+	}
+	
+	/**
+	 * Converts a C-style 0 terminated string to a wstring
+	 * 
+	 * Params:
+	 *     str = the C-style 0 terminated string
+	 *     
+	 * Returns: the converted wstring
+	 */
+	wstring fromString16z (wchar* str)
+	{
+		return str[0 .. strlen(str)].idup;
+	}
+	
+	/**
+	 * Converts a C-style 0 terminated string to a dstring
+	 * Params:
+	 *     str = the C-style 0 terminated string
+	 *     
+	 * Returns: the converted dstring
+	 */
+	dstring fromString32z (dchar* str)
+	{
+		return str[0 .. strlen(str)].idup;
+	}
+	
+	/**
+	 * Gets the length of the given C-style 0 terminated string
+	 * 
+	 * Params:
+	 *     str = the C-style 0 terminated string to get the length of
+	 *     
+	 * Returns: the length of the string
+	 */
+	size_t strlen (wchar* str)
+	{
+		size_t i = 0;
+		
+		if (str)
+			while(*str++)
+				++i;
+		
+		return i;
+	}
+	
+	/**
+	 * Gets the length of the given C-style 0 terminated string
+	 * 
+	 * Params:
+	 *     str = the C-style 0 terminated string to get the length of
+	 *     
+	 * Returns: the length of the string
+	 */
+	size_t strlen (dchar* str)
+	{
+		size_t i = 0;
+		
+		if (str)
+			while(*str++)
+				++i;
+		
+		return i;
+	}
+}
\ No newline at end of file
--- a/orange/serialization/RegisterWrapper.d	Wed Oct 06 16:18:02 2010 +0200
+++ b/orange/serialization/RegisterWrapper.d	Tue Oct 19 10:22:10 2010 +0200
@@ -6,8 +6,9 @@
  */
 module orange.serialization.RegisterWrapper;
 
-import orange.serialization.archives.Archive;
-import orange.serialization.Serializer;
+//import orange.serialization.archives.Archive;
+//import orange.serialization.Serializer;
+import orange.core.string;
 
 class RegisterBase
 {
@@ -16,22 +17,21 @@
 
 class SerializeRegisterWrapper (T, SerializerType) : RegisterBase
 {
-	private alias SerializerType.DataType DataType;
-	private void delegate (T, SerializerType, DataType) dg;
+	private void delegate (T, SerializerType, string) dg;
 	private bool isDelegate;
 
-	this (void delegate (T, SerializerType, DataType) dg)
+	this (void delegate (T, SerializerType, string) dg)
 	{
 		isDelegate = true;
 		this.dg = dg;
 	}
 
-	this (void function (T, SerializerType, DataType) func)
+	this (void function (T, SerializerType, string) func)
 	{
 		dg.funcptr = func;
 	}
 
-	void opCall (T value, SerializerType archive, DataType key)
+	void opCall (T value, SerializerType archive, string key)
 	{
 		if (dg && isDelegate)
 			dg(value, archive, key);
@@ -43,22 +43,21 @@
 
 class DeserializeRegisterWrapper (T, SerializerType) : RegisterBase
 {
-	private alias SerializerType.DataType DataType;
-	private void delegate (ref T, SerializerType, DataType) dg;
+	private void delegate (ref T, SerializerType, string) dg;
 	private bool isDelegate;
 
-	this (void delegate (ref T, SerializerType, DataType) dg)
+	this (void delegate (ref T, SerializerType, string) dg)
 	{
 		isDelegate = true;
 		this.dg = dg;
 	}
 
-	this (void function (ref T, SerializerType, DataType) func)
+	this (void function (ref T, SerializerType, string) func)
 	{
 		dg.funcptr = func;
 	}
 
-	void opCall (ref T value, SerializerType archive, DataType key)
+	void opCall (ref T value, SerializerType archive, string key)
 	{
 		if (dg && isDelegate)
 			dg(value, archive, key);
--- a/orange/serialization/SerializationException.d	Wed Oct 06 16:18:02 2010 +0200
+++ b/orange/serialization/SerializationException.d	Tue Oct 19 10:22:10 2010 +0200
@@ -6,7 +6,7 @@
  */
 module orange.serialization.SerializationException;
 
-import orange.util.string;
+import orange.core.string;
 
 version (Tango)
 	alias Exception ExceptionBase;
Binary file orange/serialization/Serializer has changed
--- a/orange/serialization/Serializer.d	Wed Oct 06 16:18:02 2010 +0200
+++ b/orange/serialization/Serializer.d	Tue Oct 19 10:22:10 2010 +0200
@@ -15,6 +15,7 @@
 	alias ConvError ConversionException;
 }
 
+import orange.core._;
 import orange.serialization._;
 import orange.serialization.archives._;
 import orange.util._;
@@ -31,37 +32,52 @@
 	
 	alias Mode.serializing serializing;
 	alias Mode.deserializing deserializing;
+	
+	private char toUpper (char c)
+	{
+		if (c >= 'a' && c <= 'z')
+			return c - 32;
+
+		return c;
+	}
 }
 
 class Serializer
 {
-	alias void delegate (ArchiveException exception, IArchive.IDataType data) ErrorCallback;
-	alias IArchive.IDataType DataType;
+	alias void delegate (ArchiveException exception, string[] data) ErrorCallback;
+	alias UntypedData Data;
+	alias size_t Id;
 	
 	private
-	{
+	{		
 		ErrorCallback errorCallback_;		
 		IArchive archive;
 		
 		size_t keyCounter;
-		size_t idCounter;
+		Id idCounter;
 		
 		RegisterBase[string] serializers;
-		RegisterBase[string] deserializers;		
+		RegisterBase[string] deserializers;
+		
+		Id[void*] serializedReferences;
+		void*[Id] deserializedReferences;
+		
+		Array[Id] serializedArrays;
+		void[][Id] deserializedSlices;
 		
 		bool hasBegunSerializing;
 		bool hasBegunDeserializing;
 		
-		void delegate (ArchiveException exception, DataType data) throwOnErrorCallback;		
-		void delegate (ArchiveException exception, DataType data) doNothingOnErrorCallback;
+		void delegate (ArchiveException exception, string[] data) throwOnErrorCallback;		
+		void delegate (ArchiveException exception, string[] data) doNothingOnErrorCallback;
 	}
 	
 	this (IArchive archive)
 	{
 		this.archive = archive;
 		
-		throwOnErrorCallback = (ArchiveException exception, IArchive.IDataType data) { throw exception; };
-		doNothingOnErrorCallback = (ArchiveException exception, IArchive.IDataType data) { /* do nothing */ };
+		throwOnErrorCallback = (ArchiveException exception, string[] data) { throw exception; };
+		doNothingOnErrorCallback = (ArchiveException exception, string[] data) { /* do nothing */ };
 		
 		setThrowOnErrorCallback();
 	}
@@ -86,15 +102,34 @@
 		errorCallback = doNothingOnErrorCallback;
 	}
 	
-	DataType serialize (T) (T value, string key = null)
+	void reset ()
+	{
+		resetCounters();
+		
+		serializers = null;
+		deserializers = null;
+		
+		serializedReferences = null;
+		deserializedReferences = null;
+		
+		serializedArrays = null;
+		deserializedSlices = null;
+		
+		hasBegunSerializing = false;
+		hasBegunDeserializing = false;
+		
+		archive.reset;
+	}
+	
+	Data serialize (T) (T value, string key = null)
 	{
 		if (!hasBegunSerializing)
 			hasBegunSerializing = true;
 		
 		serializeInternal(value, key);
-		archive.postProcess;
+		postProcess;
 
-		return archive.data;
+		return archive.untypedData;
 	}
 	
 	private void serializeInternal (T) (T value, string key = null)
@@ -104,10 +139,10 @@
 		
 		archive.beginArchiving();
 		
-		static if (isTypeDef!(T))
-			serializeTypeDef(value, key);
+		static if ( is(T == typedef) )
+			serializeTypedef(value, key);
 		
-		static if (isObject!(T))
+		else static if (isObject!(T))
 			serializeObject(value, key);
 
 		else static if (isStruct!(T))
@@ -146,10 +181,21 @@
 
 	private void serializeObject (T) (T value, string key)
 	{
-		auto runtimeType = value.classinfo.name; 
+		if (!value)
+			return archive.archiveNull(T.stringof, key);
+		
+		auto reference = getSerializedReference(value);
+		
+		if (reference != Id.max)
+			return archive.archiveReference(key, reference);
 		
-		triggerEvents(serializing, value, {
-			archive.archiveObject(runtimeType, T.stringof, key, nextId, {
+		auto runtimeType = value.classinfo.name;
+		
+		Id id = nextId;
+		addSerializedReference(value, id);
+
+		triggerEvents(serializing, value, {			
+			archive.archiveObject(runtimeType, T.stringof, key, id, {
 				if (runtimeType in serializers)
 				{
 					auto wrapper = getSerializerWrapper!(T)(runtimeType);
@@ -163,19 +209,19 @@
 				{				
 					if (isBaseClass(value))
 						throw new SerializationException(`The object of the static type "` ~ T.stringof ~ `" have a different runtime type (` ~ runtimeType ~ `) and therefore needs to register a serializer for its type "` ~ runtimeType ~ `".`, __FILE__, __LINE__);
-				
+
 					objectStructSerializeHelper(value);
 				}
 			});
 		});
 	}
 	
-	private void serializeStruct (T) (T value, DataType key)
-	{
-		auto type = T.stringof;
+	private void serializeStruct (T) (T value, string key)
+	{			
+		string type = T.stringof;
 		
 		triggerEvents(serializing, value, {
-			archive.archive(type, key, nextId, {				
+			archive.archiveStruct(type, key, nextId, {
 				if (type in serializers)
 				{
 					auto wrapper = getSerializerWrapper!(T)(type);
@@ -196,22 +242,436 @@
 	
 	private void serializeString (T) (T value, string key)
 	{
-		archive.archive(value, key, nextId);
+		auto id = nextId;
+		auto array = Array(value.ptr, value.length, ElementTypeOfArray!(T).sizeof);
+		
+		archive.archive(value, key, id);			
+		addSerializedArray(array, id);
 	}
 	
 	private void serializeArray (T) (T value, string key)
 	{
-		auto array = Array(value.ptr, value.length, BaseTypeOfArray!(T).sizeof);
+		auto array = Array(value.ptr, value.length, ElementTypeOfArray!(T).sizeof);
+		auto id = nextId;
+
+		archive.archiveArray(array, arrayToString!(T), key, id, {
+			foreach (i, e ; value)
+				serializeInternal(e, toData(i));
+		});
+		
+		addSerializedArray(array, id);
+	}
+	
+	private void serializeAssociativeArray (T) (T value, string key)
+	{
+		string keyType = KeyTypeOfAssociativeArray!(T).stringof;
+		string valueType = ValueTypeOfAssociativeArray!(T).stringof;
+		
+		archive.archiveAssociativeArray(keyType, valueType, value.length, key, nextId, {
+			size_t i;
+			
+			foreach(k, v ; value)
+			{
+				archive.archiveAssociativeArrayKey(toData(i), {
+					serializeInternal(k, toData(i));
+				});
+				
+				archive.archiveAssociativeArrayValue(toData(i), {
+					serializeInternal(v, toData(i));
+				});
+				
+				i++;
+			}
+		});
+	}
+	
+	private void serializePointer (T) (T value, string key)
+	{
+		if (!value)
+			return archive.archiveNull(T.stringof, key);
+		
+		auto reference = getSerializedReference(value);
+		
+		if (reference != Id.max)
+			return archive.archiveReference(key, reference);
 		
-		archive.archiveArray(array, arrayToString!(T), key, nextId, {
-			foreach (i, e ; value)
-				serializeInternal(e, toDataType(i));
+		Id id = nextId;
+
+		addSerializedReference(value, id);
+		
+		archive.archivePointer(key, id, {
+			if (key in serializers)
+			{
+				auto wrapper = getSerializerWrapper!(T)(key);
+				wrapper(value, this, key);
+			}
+			
+			else static if (isSerializable!(T, Serializer))
+				value.toData(this, key);
+			
+			else
+			{
+				static if (isVoid!(BaseTypeOfPointer!(T)))
+					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
+					serializeInternal(*value, nextKey);
+			}
+		});
+	}
+	
+	private void serializeEnum (T) (T value, string key)
+	{
+		alias BaseTypeOfEnum!(T) EnumBaseType;
+		auto val = cast(EnumBaseType) value;
+		string type = T.stringof;
+		
+		archive.archiveEnum(val, type, key, nextId);
+	}
+	
+	private void serializePrimitive (T) (T value, string key)
+	{	
+		archive.archive(value, key, nextId);
+	}
+	
+	private void serializeTypedef (T) (T value, string key)
+	{
+		archive.archiveTypedef(T.stringof, key, nextId, {
+			serializeInternal!(BaseTypeOfTypedef!(T))(value, nextKey);
 		});
 	}
 	
-	private void serializePrimitive (T) (T value, string key)
+	T deserialize (T) (Data data, string key = null)
 	{		
-		archive.archive(value, key, nextId);
+		if (hasBegunSerializing && !hasBegunDeserializing)
+			resetCounters();
+		
+		if (!hasBegunDeserializing)
+			hasBegunDeserializing = true;
+		
+		if (!key)
+			key = nextKey;
+		
+		archive.beginUnarchiving(data);
+		return deserializeInternal!(T)(key);
+	}
+	
+	private T deserializeInternal (T) (string key)
+	{
+		static if (isTypedef!(T))
+			return deserializeTypedef!(T)(key);
+		
+		else static if (isObject!(T))
+			return deserializeObject!(T)(key);
+
+		else static if (isStruct!(T))
+			return deserializeStruct!(T)(key);
+
+		else static if (isString!(T))
+			return deserializeString!(T)(key);
+		
+		else static if (isArray!(T))
+			return deserializeArray!(T)(key);
+
+		else static if (isAssociativeArray!(T))
+			return deserializeAssociativeArray!(T)(key);
+
+		else static if (isPrimitive!(T))
+			return deserializePrimitive!(T)(key);
+
+		else static if (isPointer!(T))
+		{			
+			static if (isFunctionPointer!(T))
+				goto error;
+			
+			return deserializePointer!(T)(key);
+		}		
+		
+		else static if (isEnum!(T))
+			return deserializeEnum!(T)(key);
+		
+		else
+		{
+			error:
+			throw new SerializationException(format!(`The type "`, T, `" cannot be deserialized.`), __FILE__, __LINE__);
+		}			
+	}
+	
+	private T deserializeObject (T) (string key)
+	{
+		auto id = deserializeReference(key);
+		
+		if (auto reference = getDeserializedReference!(T)(id))
+			return *reference;
+
+		T value;
+		Object val = value;
+		
+		archive.unarchiveObject(key, id, val, {
+			triggerEvents(deserializing, value, {
+				value = cast(T) val;
+				auto runtimeType = value.classinfo.name;
+				
+				if (runtimeType in deserializers)
+				{
+					auto wrapper = getDeserializerWrapper!(T)(runtimeType);
+					wrapper(value, this, key);
+				}
+				
+				else static if (isSerializable!(T, Serializer))
+					value.fromData(this, key);
+				
+				else
+				{
+					if (isBaseClass(value))
+						throw new SerializationException(`The object of the static type "` ~ T.stringof ~ `" have a different runtime type (` ~ runtimeType ~ `) and therefore needs to register a deserializer for its type "` ~ runtimeType ~ `".`, __FILE__, __LINE__);
+
+					objectStructDeserializeHelper(value);					
+				}
+			});
+		});
+		
+		addDeserializedReference(value, id);
+		
+		return value;
+	}
+	
+	private T deserializeStruct (T) (string key)
+	{
+		T value;
+		
+		archive.unarchiveStruct(key, {			
+			triggerEvents(deserializing, value, {
+				auto type = toData(T.stringof);
+				
+				if (type in deserializers)
+				{
+					auto wrapper = getDeserializerWrapper!(T)(type);
+					wrapper(value, this, key);
+				}
+				
+				else
+				{
+					static if (isSerializable!(T, Serializer))
+						value.fromData(this, key);
+					
+					else
+						objectStructDeserializeHelper(value);
+				}	
+			});
+		});
+		
+		return value;
+	}
+	
+	private T deserializeString (T) (string key)
+	{
+		auto slice = deserializeSlice(key);
+
+		if (auto tmp = getDeserializedSlice!(T)(slice))
+			return *tmp;
+		
+		T value;
+		
+		if (slice.id != size_t.max)
+		{
+			static if (is(T == string))
+				value = archive.unarchiveString(slice.id).toSlice(slice);
+			
+			else static if (is(T == wstring))
+				value = archive.unarchiveWstring(slice.id).toSlice(slice);
+			
+			else static if (is(T == dstring))
+				value = archive.unarchiveDstring(slice.id).toSlice(slice);
+		}
+		
+		else
+		{
+			static if (is(T == string))
+				value = archive.unarchiveString(key, slice.id);
+			
+			else static if (is(T == wstring))
+				value = archive.unarchiveWstring(key, slice.id);
+			
+			else static if (is(T == dstring))
+				value = archive.unarchiveDstring(key, slice.id);
+		}		
+
+		addDeserializedSlice(value, slice.id);
+		
+		return value;
+	}
+	
+	private T deserializeArray (T) (string key)
+	{
+		auto slice = deserializeSlice(key);
+		
+		if (auto tmp = getDeserializedSlice!(T)(slice))
+			return *tmp;
+		
+		T value;
+		
+		auto dg = (size_t length) {
+			value.length = length;
+			
+			foreach (i, ref e ; value)
+				e = deserializeInternal!(typeof(e))(toData(i));
+		};
+		
+		if (slice.id != size_t.max)
+		{
+			archive.unarchiveArray(slice.id, dg);
+			addDeserializedSlice(value, slice.id);
+			
+			return value.toSlice(slice);
+		}			
+		
+		else
+		{
+			slice.id = archive.unarchiveArray(key, dg);
+			
+			if (auto a = slice.id in deserializedSlices)
+				return cast(T) *a;
+			
+			addDeserializedSlice(value, slice.id);
+			
+			return value;
+		}
+	}
+	
+	private T deserializeAssociativeArray (T) (string key)
+	{
+		T value;
+		
+		alias KeyTypeOfAssociativeArray!(T) Key;
+		alias ValueTypeOfAssociativeArray!(T) Value;
+		
+		archive.unarchiveAssociativeArray(key, (size_t length) {
+			for (size_t i = 0; i < length; i++)
+			{
+				Key aaKey;
+				Value aaValue;
+				auto k = toData(i);
+				
+				archive.unarchiveAssociativeArrayKey(k, {
+					aaKey = deserializeInternal!(Key)(k);
+				});
+				
+				archive.unarchiveAssociativeArrayValue(k, {
+					aaValue = deserializeInternal!(Value)(k);
+				});
+				
+				value[aaKey] = aaValue;
+			}
+		});
+		
+		return value;
+	}
+	
+	/*			auto id = deserializeReference(key);
+		
+		if (auto reference = getDeserializedReference!(T)(id))
+			return *reference;
+
+		T value;
+		Object val = value;
+		
+		archive.unarchiveObject(key, id, val, {
+			triggerEvents(deserializing, value, {
+				value = cast(T) val;
+				auto runtimeType = value.classinfo.name;
+				
+				if (runtimeType in deserializers)
+				{
+					auto wrapper = getDeserializerWrapper!(T)(runtimeType);
+					wrapper(value, this, key);
+				}
+				
+				else static if (isSerializable!(T, Serializer))
+					value.fromData(this, key);
+				
+				else
+				{
+					if (isBaseClass(value))
+						throw new SerializationException(`The object of the static type "` ~ T.stringof ~ `" have a different runtime type (` ~ runtimeType ~ `) and therefore needs to register a deserializer for its type "` ~ runtimeType ~ `".`, __FILE__, __LINE__);
+
+					objectStructDeserializeHelper(value);					
+				}
+			});
+		});
+		
+		addDeserializedReference(value, id);
+		
+		return value;
+	 */
+	
+	private T deserializePointer (T) (string key)
+	{
+		auto id = deserializeReference(key);
+		
+		if (auto reference = getDeserializedReference!(T)(id))
+			return *reference;
+		
+		T value = new BaseTypeOfPointer!(T);
+		
+		id = archive.unarchivePointer(key, {
+			if (key in deserializers)
+			{
+				auto wrapper = getDeserializerWrapper!(T)(key);
+				wrapper(value, this, key);
+			}
+			
+			else static if (isSerializable!(T, Serializer))
+				value.fromData(this, key);
+			
+			else
+			{
+				static if (isVoid!(BaseTypeOfPointer!(T)))
+					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);
+			}
+		});
+		
+		addDeserializedReference(value, id);
+		
+		return value;
+	}
+	
+	private T deserializeEnum (T) (string key)
+	{
+		alias BaseTypeOfEnum!(T) Enum;
+
+		const functionName = toUpper(Enum.stringof[0]) ~ Enum.stringof[1 .. $];
+		mixin("return cast(T) archive.unarchiveEnum" ~ functionName ~ "(key);");
+	}
+	
+	private T deserializePrimitive (T) (string key)
+	{		
+		const functionName = toUpper(T.stringof[0]) ~ T.stringof[1 .. $];
+		mixin("return archive.unarchive" ~ functionName ~ "(key);");
+	}
+	
+	private T deserializeTypedef (T) (string key)
+	{
+		T value;
+		
+		archive.unarchiveTypedef!(T)(key, {
+			value = cast(T) deserializeInternal!(BaseTypeOfTypedef!(T))(nextKey);
+		});
+		
+		return value;
+	}
+	
+	private Id deserializeReference (string key)
+	{
+		return archive.unarchiveReference(key);
+	}
+	
+	private Slice deserializeSlice (string key)
+	{
+		return archive.unarchiveSlice(key);
 	}
 	
 	private void objectStructSerializeHelper (T) (ref T value)
@@ -227,7 +687,7 @@
 			{
 				alias typeof(T.tupleof[i]) Type;				
 				Type v = value.tupleof[i];
-				serializeInternal(v, toDataType(field));
+				serializeInternal(v, toData(field));
 			}				
 		}
 		
@@ -247,7 +707,7 @@
 			static if (!internalFields.ctfeContains(field) && !nonSerializedFields.ctfeContains(field))
 			{
 				alias TypeOfField!(T, field) Type;
-				auto fieldValue = deserializeInternal!(Type)(toDataType(field));
+				auto fieldValue = deserializeInternal!(Type)(toData(field));
 				value.tupleof[i] = fieldValue;
 			}			
 		}
@@ -259,7 +719,7 @@
 	private void serializeBaseTypes (T : Object) (T value)
 	{
 		alias BaseTypeTupleOf!(T)[0] Base;
-		
+
 		static if (!is(Base == Object))
 		{
 			archive.archiveBaseClass(Base.stringof, nextKey, nextId);
@@ -278,6 +738,62 @@
 			Base base = value;
 			objectStructDeserializeHelper(base);
 		}
+	}	
+	
+	private void addSerializedReference (T) (T value, Id id)
+	{
+		static assert(isReference!(T), format!(`The given type "`, T, `" is not a reference type, i.e. object or pointer.`));
+		
+		serializedReferences[cast(void*) value] = id;
+	}
+	
+	private void addDeserializedReference (T) (T value, Id id)
+	{
+		static assert(isReference!(T), format!(`The given type "`, T, `" is not a reference type, i.e. object or pointer.`));
+		
+		deserializedReferences[id] = cast(void*) value;
+	}
+	
+	private void addDeserializedSlice (T) (T value, Id id)
+	{
+		static assert(isArray!(T) || isString!(T), format!(`The given type "`, T, `" is not a slice type, i.e. array or string.`));
+
+		deserializedSlices[id] = value;
+	}
+	
+	private Id getSerializedReference (T) (T value)
+	{
+		if (auto tmp = cast(void*) value in serializedReferences)
+			return *tmp;
+		
+		return Id.max;
+	}
+	
+	private T* getDeserializedReference (T) (Id id)
+	{
+		if (auto reference = id in deserializedReferences)
+			return cast(T*) reference;
+		
+		return null;
+	}
+	
+	private T* getDeserializedSlice (T) (Slice slice)
+	{
+		if (auto array = slice.id in deserializedSlices)
+			return &(cast(T) *array)[slice.offset .. slice.offset + slice.length]; // dereference the array, cast it to the right type, 
+																		// slice it and then return a pointer to the result		}
+		return null;		
+	}
+	
+	private T* getDeserializedArray (T) (Id id)
+	{
+		if (auto array = id in deserializedSlices)
+			return cast(T*) array;
+	}
+	
+	private T[] toSlice (T) (T[] array, Slice slice)
+	{
+		return array[slice.offset .. slice.offset + slice.length];
 	}
 	
 	private SerializeRegisterWrapper!(T, Serializer) getSerializerWrapper (T) (string type)
@@ -320,9 +836,44 @@
 		return new DeserializeRegisterWrapper!(T, Serializer)(func);
 	}
 	
+	private void addSerializedArray (Array array, Id id)
+	{
+		serializedArrays[id] = array;
+	}
+	
+	private void postProcessArrays ()
+	{
+		bool foundSlice = true;
+		
+		foreach (sliceKey, slice ; serializedArrays)
+		{
+			foreach (arrayKey, array ; serializedArrays)
+			{
+				if (slice.isSliceOf(array) && slice != array)
+				{
+					auto s = Slice(slice.length, (slice.ptr - array.ptr) / slice.elementSize);
+					archive.archiveSlice(s, sliceKey, arrayKey);
+					foundSlice = true;
+					break;
+				}
+				
+				else
+					foundSlice = false;
+			}
+			
+			if (!foundSlice)
+				archive.postProcessArray(sliceKey);
+		}
+	}
+	
+	private void postProcess ()
+	{
+		postProcessArrays();
+	}
+	
 	private template arrayToString (T)
 	{
-		const arrayToString = BaseTypeOfArray!(T).stringof;
+		const arrayToString = ElementTypeOfArray!(T).stringof;
 	}
 	
 	private bool isBaseClass (T) (T value)
@@ -333,14 +884,14 @@
 		return T.stringof != name[index + 1 .. $];
 	}
 	
-	private size_t nextId ()
+	private Id nextId ()
 	{
 		return idCounter++;
 	}
 	
 	private string nextKey ()
 	{
-		return toDataType(keyCounter++);
+		return toData(keyCounter++);
 	}
 	
 	private void resetCounters ()
@@ -349,7 +900,7 @@
 		idCounter = 0;
 	}
 	
-	private string toDataType (T) (T value)
+	private string toData (T) (T value)
 	{
 		return to!(string)(value);
 	}
@@ -378,9 +929,9 @@
 		
 		else
 			triggerEvent!(onDeserializingField)(value);
-		
+
 		dg();
-		
+
 		if (mode == serializing)
 			triggerEvent!(onSerializedField)(value);
 		
@@ -404,4 +955,355 @@
 		
 		return annotations;
 	}
+}
+
+
+
+debug (OrangeUnitTest)
+{
+	import orange.serialization.archives.XMLArchive;
+
+	enum Foo { a, b, c }
+	typedef int Int;
+	
+	class A {}
+	struct B {}
+	class C { string str; }
+	class D { int[] arr; }
+	class E { int[int] aa; }
+	class F { int value; int* ptr; }
+	class G { Foo foo; }
+	
+	class H
+	{
+		bool bool_;
+		byte byte_;
+		//cdouble cdouble_; // currently not suppported by to!()
+		//cent cent_; // currently not implemented but a reserved keyword
+		//cfloat cfloat_; // currently not suppported by to!()
+		char char_;
+		//creal creal_; // currently not suppported by to!()
+		dchar dchar_;
+		double double_;
+		float float_;
+		//idouble idouble_; // currently not suppported by to!()
+		//ifloat ifloat_; // currently not suppported by to!()
+		int int_;
+		//ireal ireal_;  // currently not suppported by to!()
+		long long_;
+		real real_;
+		short short_;
+		ubyte ubyte_;
+		//ucent ucent_; // currently not implemented but a reserved keyword
+		uint uint_;
+		ulong ulong_;
+		ushort ushort_;
+		wchar wchar_;
+		
+		equals_t opEquals (Object other)
+		{
+			if (auto o =  cast(H) other)
+			{
+				return bool_ == o.bool_ &&
+					   byte_ == o.byte_ &&
+					   //cdouble_ == o.cdouble_ && // currently not suppported by to!()
+					   //cent_ == o.cent_ && // currently not implemented but a reserved keyword
+					   //cfloat_ == o.cfloat_ && // currently not suppported by to!()
+					   char_ == o.char_ &&
+					   //creal_ == o.creal_ && // currently not suppported by to!()
+					   dchar_ == o.dchar_ &&
+					   double_ == o.double_ &&
+					   float_ == o.float_ &&
+					   //idouble_ == o.idouble_ && // currently not suppported by to!()
+					   //ifloat_ == o.ifloat_ && // currently not suppported by to!()
+					   int_ == o.int_ &&
+					   //ireal_ == o.ireal_ &&  // currently not suppported by to!()
+					   long_ == o.long_ &&
+					   real_ == o.real_ &&
+					   short_ == o.short_ &&
+					   ubyte_ == o.ubyte_ &&
+					   //ucent_ == o.ucent_ && // currently not implemented but a reserved keyword
+					   uint_ == o.uint_ &&
+					   ulong_ == o.ulong_ &&
+					   ushort_ == o.ushort_ &&
+					   wchar_ == o.wchar_;
+			}
+			
+			return false;
+		}
+	}
+	
+	class I
+	{
+		Int a;
+	}
+	
+	void main ()
+	{
+		auto archive = new XMLArchive!(char);
+		auto serializer = new Serializer(archive);
+		string data;
+		
+		void serializeObject ()
+		{
+			serializer.reset;
+			data = `<?xml version="1.0" encoding="UTF-8"?>
+<archive type="org.dsource.orange.xml" version="1.0.0">
+    <data>
+        <struct type="B" key="0"/>
+    </data>
+</archive>`;
+				
+			serializer.serialize(B());
+			assert(archive.data == data);
+		}
+		
+		void serializeStruct ()
+		{
+			serializer.reset;
+			data = `<?xml version="1.0" encoding="UTF-8"?>
+<archive type="org.dsource.orange.xml" version="1.0.0">
+    <data>
+        <struct type="B" key="0"/>
+    </data>
+</archive>`;
+				
+			serializer.serialize(B());
+			assert(archive.data == data);
+		}
+		
+		// Struct
+		
+
+		
+		// String
+		
+		serializer.reset;
+		data = `<?xml version="1.0" encoding="UTF-8"?>
+<archive type="org.dsource.orange.xml" version="1.0.0">
+    <data>
+        <object runtimeType="orange.serialization.Serializer.C" type="C" key="0" id="0">
+            <string type="char" length="3" key="str" id="1">foo</string>
+        </object>
+    </data>
+</archive>`;
+		
+		auto c = new C;
+		c.str = "foo";
+		serializer.serialize(c);
+		assert(archive.data == data);
+		
+		// Deserializing
+		
+		auto cDeserialized = serializer.deserialize!(C)(data);
+		assert(c.str == cDeserialized.str);
+			
+		// Array
+	
+		serializer.reset;
+		data = `<?xml version="1.0" encoding="UTF-8"?>
+<archive type="org.dsource.orange.xml" version="1.0.0">
+    <data>
+        <object runtimeType="orange.serialization.Serializer.D" type="D" key="0" id="0">
+            <array type="int" length="6" key="arr" id="1">
+                <int key="0">27</int>
+                <int key="1">382</int>
+                <int key="2">283</int>
+                <int key="3">3820</int>
+                <int key="4">32</int>
+                <int key="5">832</int>
+            </array>
+        </object>
+    </data>
+</archive>`;
+		
+		auto d = new D;
+		d.arr = [27, 382, 283, 3820, 32, 832];
+		serializer.serialize(d);
+		assert(archive.data == data);	
+		
+		// Deserializing
+		
+		auto dDeserialized = serializer.deserialize!(D)(data);
+		assert(d.arr == dDeserialized.arr);
+		
+		// Associative Array
+		
+		serializer.reset();
+		data = `<?xml version="1.0" encoding="UTF-8"?>
+<archive type="org.dsource.orange.xml" version="1.0.0">
+    <data>
+        <object runtimeType="orange.serialization.Serializer.E" type="E" key="0" id="0">
+            <associativeArray keyType="int" valueType="int" length="4" key="aa">
+                <key key="0">
+                    <int key="0">1</int>
+                </key>
+                <value key="0">
+                    <int key="0">2</int>
+                </value>
+                <key key="1">
+                    <int key="1">3</int>
+                </key>
+                <value key="1">
+                    <int key="1">4</int>
+                </value>
+                <key key="2">
+                    <int key="2">6</int>
+                </key>
+                <value key="2">
+                    <int key="2">7</int>
+                </value>
+                <key key="3">
+                    <int key="3">39</int>
+                </key>
+                <value key="3">
+                    <int key="3">472</int>
+                </value>
+            </associativeArray>
+        </object>
+    </data>
+</archive>`;
+		
+		auto e = new E;
+		e.aa = [3 : 4, 1 : 2, 39 : 472, 6 : 7];
+		serializer.serialize(e);
+		assert(archive.data == data);
+		
+		// Deserializing
+		
+		auto eDeserialized = serializer.deserialize!(E)(data);
+		//assert(e.aa == eDeserialized.aa); // cannot compare associative array
+
+		// Pointer
+		
+		serializer.reset();
+		data = `<?xml version="1.0" encoding="UTF-8"?>
+<archive type="org.dsource.orange.xml" version="1.0.0">
+    <data>
+        <object runtimeType="orange.serialization.Serializer.F" type="F" key="0" id="0">
+            <pointer key="ptr" id="2">
+                <int key="1">9</int>
+            </pointer>
+            <int key="value">9</int>
+        </object>
+    </data>
+</archive>`;
+		
+		auto f = new F;
+		f.value = 9;
+		f.ptr = &f.value;
+		serializer.serialize(f);
+		//assert(archive.data == data); // this is not a reliable comparison, the order of int and pointer is not reliable
+		
+		// Deserializing
+		
+		auto fDeserialized = serializer.deserialize!(F)(data);
+		assert(*f.ptr == *fDeserialized.ptr);
+		
+		// Enum
+		
+		serializer.reset();
+		data = `<?xml version="1.0" encoding="UTF-8"?>
+<archive type="org.dsource.orange.xml" version="1.0.0">
+    <data>
+        <object runtimeType="orange.serialization.Serializer.G" type="G" key="0" id="0">
+            <enum type="Foo" baseType="int" key="foo">1</enum>
+        </object>
+    </data>
+</archive>`;
+		
+		auto g = new G;
+		g.foo = Foo.b;
+		serializer.serialize(g);
+		assert(archive.data == data);
+		
+		// Deserializing
+		
+		auto gDeserialized = serializer.deserialize!(G)(data);
+		assert(g.foo == gDeserialized.foo);
+		
+		// Primitives
+		
+		serializer.reset;
+		data = `<?xml version="1.0" encoding="UTF-8"?>
+<archive type="org.dsource.orange.xml" version="1.0.0">
+    <data>
+        <object runtimeType="orange.serialization.Serializer.H" type="H" key="0" id="0">
+            <byte key="byte_">1</byte>
+            <char key="char_">a</char>
+            <dchar key="dchar_">b</dchar>
+            <double key="double_">0</double>
+            <float key="float_">0</float>
+            <int key="int_">1</int>
+            <long key="long_">1</long>
+            <real key="real_">0</real>
+            <short key="short_">1</short>
+            <ubyte key="ubyte_">1</ubyte>
+            <uint key="uint_">1</uint>
+            <ulong key="ulong_">1</ulong>
+            <ushort key="ushort_">1</ushort>
+            <wchar key="wchar_">c</wchar>
+            <bool key="bool_">true</bool>
+        </object>
+    </data>
+</archive>`;
+		
+		auto h = new H;
+		
+		h.bool_ = true;
+		h.byte_ = 1;
+		h.char_ = 'a';
+		//h.cdouble_ = 0.0 + 0.0 * 1.0i; // currently not suppported by to!() 
+		//h.cfloat_ = 0.0f + 0.0f * 1.0i; // currently not suppported by to!() 
+		//h.creal_ = 0.0 + 0.0 * 1.0i; // currently not suppported by to!() 
+		h.dchar_ = 'b';
+		h.double_ = 0.0;
+		h.float_ = 0.0f;
+		//h.idouble_ = 0.0 * 1.0i; // currently not suppported by to!() 
+		//h.ifloat_ = 0.0f * 1.0i; // currently not suppported by to!()
+		h.int_ = 1;
+		//h.ireal_ = 0.0 * 1.0i; // currently not suppported by to!()
+		h.long_ = 1L;
+		h.real_ = 0.0;
+		h.short_ = 1;
+		h.ubyte_ = 1U;
+		h.uint_ = 1U;
+		h.ulong_ = 1LU;
+		h.ushort_ = 1U;
+		h.wchar_ = 'c';
+		
+		serializer.serialize(h);
+		//assert(archive.data == data); // this is not a reliable comparison	
+		
+		// Deserializing
+		
+		auto hDeserialized = serializer.deserialize!(H)(data);
+		assert(h == hDeserialized);
+		
+		// Typedef
+		
+		serializer.reset();
+		data = `<?xml version="1.0" encoding="UTF-8"?>
+<archive type="org.dsource.orange.xml" version="1.0.0">
+    <data>
+        <object runtimeType="orange.serialization.Serializer.I" type="I" key="0" id="0">
+            <typedef type="Int" key="a">
+                <int key="1">1</int>
+            </typedef>
+        </object>
+    </data>
+</archive>`;
+		
+		auto i = new I;
+		i.a = 1;
+		serializer.serialize(i);
+		assert(archive.data == data);
+		
+		// Deserializing
+		
+		auto iDeserialized = serializer.deserialize!(I)(data);
+		assert(i.a == iDeserialized.a);
+
+		println("unit tests successful");
+	}
 }
\ No newline at end of file
--- a/orange/serialization/archives/Archive.d	Wed Oct 06 16:18:02 2010 +0200
+++ b/orange/serialization/archives/Archive.d	Tue Oct 19 10:22:10 2010 +0200
@@ -16,7 +16,11 @@
 }
 
 import orange.serialization.archives.ArchiveException;
-import orange.util.string;
+import orange.serialization.Serializer;
+import orange.core.string;
+
+version (Tango) alias void[] UntypedData;
+else mixin ("alias immutable(void)[] UntypedData;");
 
 private enum ArchiveMode
 {
@@ -40,80 +44,141 @@
 {
 	size_t length;
 	size_t offset;
-	size_t id;
+	size_t id = size_t.max;
 }
 
 interface IArchive
 {
-	version (Tango) alias void[] IDataType;
-	else mixin ("alias immutable(void)[] IDataType;");
+	alias Serializer.Id Id;
 	
 	void beginArchiving ();
-	void beginUnarchiving (IDataType data);
+	void beginUnarchiving (UntypedData data);
 	
-	IDataType data ();
-	void postProcess ();
+	UntypedData untypedData ();
 	void reset ();
 	
-	void archiveArray (Array array, string type, string key, size_t id, void delegate () dg);
-	void archiveAssociativeArray (string keyType, string valueType, size_t length, string key, size_t id, void delegate () dg);
+	void archiveArray (Array array, string type, string key, Id id, void delegate () dg);
+	void archiveAssociativeArray (string keyType, string valueType, size_t length, string key, Id id, void delegate () dg);
+	void archiveAssociativeArrayKey (string key, void delegate () dg);
+	void archiveAssociativeArrayValue (string key, void delegate () dg);
 	
-	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 archiveEnum (bool value, string baseType, string key, Id id);
+	void archiveEnum (byte value, string baseType, string key, Id id);
+	void archiveEnum (char value, string baseType, string key, Id id);
+	void archiveEnum (dchar value, string baseType, string key, Id id);
+	void archiveEnum (int value, string baseType, string key, Id id);
+	void archiveEnum (long value, string baseType, string key, Id id);
+	void archiveEnum (short value, string baseType, string key, Id id);
+	void archiveEnum (ubyte value, string baseType, string key, Id id);
+	void archiveEnum (uint value, string baseType, string key, Id id);
+	void archiveEnum (ulong value, string baseType, string key, Id id);
+	void archiveEnum (ushort value, string baseType, string key, Id id);
+	void archiveEnum (wchar value, string baseType, string key, Id id);
 	
-	void archiveBaseClass (string type, string key, size_t id);
+	void archiveBaseClass (string type, string key, Id id);
 	void archiveNull (string type, string key);
-	void archiveObject (string runtimeType, string type, string key, size_t id, void delegate () dg);
-	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 delegate () dg);
-	void archiveTypedef (string type, string key, size_t id, void delegate () dg);
+	void archiveObject (string runtimeType, string type, string key, Id id, void delegate () dg);
+	void archivePointer (string key, Id id, void delegate () dg);
+	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);
+	void archiveTypedef (string type, string key, Id id, void delegate () dg);
 
-	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);
+	void archive (string value, string key, Id id);
+	void archive (wstring value, string key, Id id);
+	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 (cent value, string key, Id id);
+	//void archive (cfloat value, string key, Id id); // currently not suppported 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 (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 (int value, string key, Id id);
+	//void archive (ireal value, string key, Id id); // currently not suppported 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);
+	void archive (ubyte value, string key, Id id);
+	//void archive (ucent value, string key, Id id); // currently not implemented but a reserved keyword
+	void archive (uint value, string key, Id id);
+	void archive (ulong value, string key, Id id);
+	void archive (ushort value, string key, Id id);
+	void archive (wchar value, string key, Id id);
+	
+	Id unarchiveArray (string key, void delegate (size_t length) dg);
+	void unarchiveArray (Id id, void delegate (size_t length) dg);
+	void unarchiveAssociativeArray (string type, void delegate (size_t length) dg);
+	void unarchiveAssociativeArrayKey (string key, void delegate () dg);
+	void unarchiveAssociativeArrayValue (string key, void delegate () dg);
+	
+	bool unarchiveEnumBool (string key);
+	byte unarchiveEnumByte (string key);
+	char unarchiveEnumChar (string key);
+	dchar unarchiveEnumDchar (string key);
+	int unarchiveEnumInt (string key);
+	long unarchiveEnumLong (string key);
+	short unarchiveEnumShort (string key);
+	ubyte unarchiveEnumUbyte (string key);
+	uint unarchiveEnumUint (string key);
+	ulong unarchiveEnumUlong (string key);
+	ushort unarchiveEnumUshort (string key);
+	wchar unarchiveEnumWchar (string key);
+	
+	// Object unarchiveBaseClass (string key);
+	// void unarchiveNull (string key);
+	void unarchiveObject (string key, out Id id, out Object result, void delegate () dg);
+	Id unarchivePointer (string key, void delegate () dg);
+	Id unarchiveReference (string key);
+	Slice unarchiveSlice (string key);
+	void unarchiveStruct (string key, void delegate () dg);
+	void unarchiveTypedef (string key, void delegate () dg);
+	
+	string unarchiveString (string key, out Id id);
+	wstring unarchiveWstring (string key, out Id id);
+	dstring unarchiveDstring (string key, out Id id);
+	
+	string unarchiveString (Id id);
+	wstring unarchiveWstring (Id id);
+	dstring unarchiveDstring (Id id);
+    bool unarchiveBool (string key);
+    byte unarchiveByte (string key);
+    //cdouble unarchiveCdouble (string key); // currently not suppported by to!()
+    //cent unarchiveCent (string key); // currently not implemented but a reserved keyword
+    //cfloat unarchiveCfloat (string key); // currently not suppported by to!()
+    char unarchiveChar (string key); // currently not implemented but a reserved keyword
+    //creal unarchiveCreal (string key); // currently not suppported 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!()*/
+    int unarchiveInt (string key);
+    //ireal unarchiveIreal (string key); // currently not suppported by to!()
+    long unarchiveLong (string key);
+    real unarchiveReal (string key);
+    short unarchiveShort (string key);
+    ubyte unarchiveUbyte (string key);
+    //ucent unarchiveCcent (string key); // currently not implemented but a reserved keyword
+    uint unarchiveUint (string key);
+    ulong unarchiveUlong (string key);
+    ushort unarchiveUshort (string key);
+    wchar unarchiveWchar (string key);
+	
+	void postProcessArray (Id id);
 }
 
 abstract class Archive (U) : IArchive
 {
-	version (Tango) alias U[] DataType;
-	else mixin ("alias immutable(U)[] DataType;");
+	version (Tango) alias U[] Data;
+	else mixin ("alias immutable(U)[] Data;");
 	
-	alias void delegate (ArchiveException exception, DataType[] data) ErrorCallback;
+	alias void delegate (ArchiveException exception, string[] data) ErrorCallback;
 	
 	protected ErrorCallback errorCallback;
 	
@@ -122,16 +187,16 @@
 		this.errorCallback = errorCallback;
 	}
 	
-	protected DataType toDataType (T) (T value)
+	protected Data toData (T) (T value)
 	{
 		try
-			return to!(DataType)(value);
+			return to!(Data)(value);
 		
 		catch (ConversionException e)
 			throw new ArchiveException(e);
 	}
 	
-	protected T fromDataType (T) (DataType value)
+	protected T fromData (T) (Data value)
 	{
 		try
 			return to!(T)(value);
@@ -140,6 +205,11 @@
 			throw new ArchiveException(e);
 	}
 	
+	protected Id toId (Data value)
+	{
+		return fromData!(Id)(value);
+	}
+	
 	protected bool isSliceOf (T, U = T) (T[] a, U[] b)
 	{
 		void* aPtr = a.ptr;
--- a/orange/serialization/archives/ArchiveException.d	Wed Oct 06 16:18:02 2010 +0200
+++ b/orange/serialization/archives/ArchiveException.d	Tue Oct 19 10:22:10 2010 +0200
@@ -7,7 +7,7 @@
 module orange.serialization.archives.ArchiveException;
 
 import orange.serialization.SerializationException;
-import orange.util.string;
+import orange.core.string;
 
 class ArchiveException : SerializationException
 {	
--- a/orange/serialization/archives/XMLArchive.d	Wed Oct 06 16:18:02 2010 +0200
+++ b/orange/serialization/archives/XMLArchive.d	Tue Oct 19 10:22:10 2010 +0200
@@ -12,57 +12,63 @@
 else
 	import std.conv;
 
+import orange.core._;
 import orange.serialization.archives._;
+import orange.serialization.Serializer;
 import orange.util._;
 import orange.xml.XMLDocument;
 
 final class XMLArchive (U = char) : Archive!(U)
 {
-	private alias IArchive.IDataType IDataType;
+	private alias IArchive.Id Id;
 	
 	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";
+		static const Data structTag = "struct";	
+		static const Data dataTag = "data";
+		static const Data archiveTag = "archive";
+		static const Data arrayTag = "array";
+		static const Data objectTag = "object";
+		static const Data baseTag = "base";
+		static const Data stringTag = "string";
+		static const Data referenceTag = "reference";
+		static const Data pointerTag = "pointer";
+		static const Data associativeArrayTag = "associativeArray";
+		static const Data typedefTag = "typedef";
+		static const Data nullTag = "null";
+		static const Data enumTag = "enum";
+		static const Data sliceTag = "slice";
+		static const Data elementTag = "element";
+		static const Data keyTag = "key";
+		static const Data valueTag = "value";
 	}
 
 	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";
+		static const Data typeAttribute = "type";
+		static const Data versionAttribute = "version";
+		static const Data lengthAttribute = "length";
+		static const Data keyAttribute = "key";
+		static const Data runtimeTypeAttribute = "runtimeType";
+		static const Data idAttribute = "id";
+		static const Data keyTypeAttribute = "keyType";
+		static const Data valueTypeAttribute = "valueType";
+		static const Data offsetAttribute = "offset";
+		static const Data baseTypeAttribute = "baseType";
 	}
 	
 	private struct ArrayNode
 	{
 		XMLDocument!(U).Node parent;
 		XMLDocument!(U).Node node;
-		DataType id;
-		DataType key;
+		Id id;
+		string key;
 	}
 	
 	private
 	{
-		DataType archiveType = "org.dsource.orange.xml";
-		DataType archiveVersion = "0.1";
+		Data archiveType = "org.dsource.orange.xml";
+		Data archiveVersion = "1.0.0";
 		
 		XMLDocument!(U) doc;
 		doc.Node lastElement;
@@ -70,8 +76,8 @@
 		bool hasBegunArchiving;
 		bool hasBegunUnarchiving;
 		
-		ArrayNode[Array] arraysToBeArchived;
-		void[][DataType] unarchivedSlices;
+		ArrayNode[Id] archivedArrays;
+		void[][Data] unarchivedSlices;
 	}
 	
 	this (ErrorCallback errorCallback = null)
@@ -94,9 +100,9 @@
 		}		
 	}
 	
-	public void beginUnarchiving (IDataType untypedData)
+	public void beginUnarchiving (UntypedData untypedData)
 	{
-		auto data = cast(DataType) untypedData;
+		auto data = cast(Data) untypedData;
 		
 		if (!hasBegunUnarchiving)
 		{
@@ -112,47 +118,26 @@
 			{
 				if (errorCallback)
 				{
+					auto dataTag = to!(string)(Tags.dataTag);
+					
 					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]);
+						errorCallback(new ArchiveException(errorMessage!(ArchiveMode.unarchiving) ~ `The "` ~ to!(string)(Tags.dataTag) ~ `" tag could not be found.`, __FILE__, __LINE__), [dataTag]);
 					
 					else
-						errorCallback(new ArchiveException(errorMessage!(ArchiveMode.unarchiving) ~ `There were more than one "` ~ to!(string)(Tags.dataTag) ~ `" tag.`, __FILE__, __LINE__), [Tags.dataTag]);
+						errorCallback(new ArchiveException(errorMessage!(ArchiveMode.unarchiving) ~ `There were more than one "` ~ to!(string)(Tags.dataTag) ~ `" tag.`, __FILE__, __LINE__), [dataTag]);
 				}	
 			}
 		}
 	}
 	
-	IDataType data ()
+	UntypedData untypedData ()
 	{
 		return doc.toString();
 	}
 	
-	void postProcess ()
+	Data data ()
 	{
-		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);
-		}
+		return doc.toString;
 	}
 	
 	void reset ()
@@ -162,13 +147,15 @@
 		doc.reset;
 	}
 	
-	void archiveArray (Array array, string type, string key, size_t id, void delegate () dg)
+	void archiveArray (Array array, string type, string key, Id id, void delegate () dg)
 	{
-		internalArchiveArray(type, array, key, id, Tags.arrayTag);
-		dg();
+		restore(lastElement) in {
+			internalArchiveArray(array, type, key, id, Tags.arrayTag);
+			dg();
+		};
 	}
 	
-	private void internalArchiveArray(string type, Array array, string key, size_t id, DataType tag, DataType content = null)
+	private void internalArchiveArray(Array array, string type, string key, Id id, Data tag, Data content = null)
 	{
 		auto parent = lastElement;
 		
@@ -178,296 +165,893 @@
 		else
 			lastElement = doc.createNode(tag, content);			
 		
-		lastElement.attribute(Attributes.typeAttribute, toDataType(type))
-		.attribute(Attributes.lengthAttribute, toDataType(array.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, void delegate () dg)
-	{
-		lastElement = lastElement.element(Tags.associativeArrayTag)		
-		.attribute(Attributes.keyTypeAttribute, toDataType(keyType))
-		.attribute(Attributes.valueTypeAttribute, toDataType(valueType))
-		.attribute(Attributes.lengthAttribute, toDataType(length))
-		.attribute(Attributes.keyAttribute, key);
+		lastElement.attribute(Attributes.typeAttribute, toData(type))
+		.attribute(Attributes.lengthAttribute, toData(array.length))
+		.attribute(Attributes.keyAttribute, toData(key))
+		.attribute(Attributes.idAttribute, toData(id));
 		
-		dg();
+		addArchivedArray(id, parent, lastElement, key);
 	}
 	
-	void archiveEnum (bool value, string key, size_t id)
+	void archiveAssociativeArray (string keyType, string valueType, size_t length, string key, Id id, void delegate () dg)
 	{
-		internalArchiveEnum(value, key, id);
-	}
-	
-	void archiveEnum (byte value, string key, size_t id)
-	{
-		internalArchiveEnum(value, key, id);
+		restore(lastElement) in {
+			lastElement = lastElement.element(Tags.associativeArrayTag)		
+			.attribute(Attributes.keyTypeAttribute, toData(keyType))
+			.attribute(Attributes.valueTypeAttribute, toData(valueType))
+			.attribute(Attributes.lengthAttribute, toData(length))
+			.attribute(Attributes.keyAttribute, key);
+			
+			dg();
+		};		
 	}
 	
-	void archiveEnum (char value, string key, size_t id)
+	void archiveAssociativeArrayKey (string key, void delegate () dg)
 	{
-		internalArchiveEnum(value, key, id);
+		internalArchiveAAKeyValue(key, Tags.keyTag, dg);
 	}
 	
-	void archiveEnum (dchar value, string key, size_t id)
+	void archiveAssociativeArrayValue (string key, void delegate () dg)
 	{
-		internalArchiveEnum(value, key, id);
+		internalArchiveAAKeyValue(key, Tags.valueTag, dg);
 	}
 	
-	void archiveEnum (int value, string key, size_t id)
+	private void internalArchiveAAKeyValue (string key, Data tag, void delegate () dg)
 	{
-		internalArchiveEnum(value, key, id);
+		restore(lastElement) in {
+			lastElement = lastElement.element(tag)
+			.attribute(Attributes.keyAttribute, toData(key));
+			
+			dg();
+		};
 	}
 	
-	void archiveEnum (long value, string key, size_t id)
+	void archiveEnum (bool value, string type, string key, Id id)
+	{
+		internalArchiveEnum(value, type, key, id);
+	}
+
+	void archiveEnum (byte value, string type, string key, Id id)
 	{
-		internalArchiveEnum(value, key, id);
+		internalArchiveEnum(value, type, key, id);
+	}
+
+	void archiveEnum (char value, string type, string key, Id id)
+	{
+		internalArchiveEnum(value, type, key, id);
 	}
-	
-	void archiveEnum (short value, string key, size_t id)
+
+	void archiveEnum (dchar value, string type, string key, Id id)
 	{
-		internalArchiveEnum(value, key, id);
+		internalArchiveEnum(value, type, key, id);
+	}
+
+	void archiveEnum (int value, string type, string key, Id id)
+	{
+		internalArchiveEnum(value, type, key, id);
+	}
+
+	void archiveEnum (long value, string type, string key, Id id)
+	{
+		internalArchiveEnum(value, type, key, id);
 	}
-	
-	void archiveEnum (ubyte value, string key, size_t id)
+
+	void archiveEnum (short value, string type, string key, Id id)
 	{
-		internalArchiveEnum(value, key, id);
+		internalArchiveEnum(value, type, key, id);
+	}
+
+	void archiveEnum (ubyte value, string type, string key, Id id)
+	{
+		internalArchiveEnum(value, type, key, id);
+	}
+
+	void archiveEnum (uint value, string type, string key, Id id)
+	{
+		internalArchiveEnum(value, type, key, id);
 	}
-	
-	void archiveEnum (uint value, string key, size_t id)
+
+	void archiveEnum (ulong value, string type, string key, Id id)
 	{
-		internalArchiveEnum(value, key, id);
+		internalArchiveEnum(value, type, key, id);
+	}
+
+	void archiveEnum (ushort value, string type, string key, Id id)
+	{
+		internalArchiveEnum(value, type, key, id);
+	}
+
+	void archiveEnum (wchar value, string type, string key, Id id)
+	{
+		internalArchiveEnum(value, type, key, id);
 	}
 	
-	void archiveEnum (ulong value, string key, size_t id)
+	private void internalArchiveEnum (T) (T value, string type, string key, Id id)
 	{
-		internalArchiveEnum(value, key, id);
-	}
-	
-	void archiveEnum (ushort value, string key, size_t id)
-	{
-		internalArchiveEnum(value, key, id);
+		lastElement.element(Tags.enumTag, toData(value))
+		.attribute(Attributes.typeAttribute, toData(type))
+		.attribute(Attributes.baseTypeAttribute, toData(T.stringof))
+		.attribute(Attributes.keyAttribute, toData(key));
 	}
 	
-	void archiveEnum (wchar value, string key, size_t id)
-	{
-		internalArchiveEnum(value, key, id);
-	}
-	
-	private void internalArchiveEnum (T) (T value, string key, size_t id)
+	void archiveBaseClass (string type, string key, Id id)
 	{
-		lastElement.element(Tags.enumTag, toDataType(value))
-		.attribute(Attributes.typeAttribute, toDataType(T.stringof))
-		.attribute(Attributes.keyAttribute, toDataType(key));
-	}
-	
-	void archiveBaseClass (string type, string key, size_t id)
-	{
-		lastElement = lastElement.element(Tags.baseTag)
-		.attribute(Attributes.typeAttribute, toDataType(type))
-		.attribute(Attributes.keyAttribute, toDataType(key)); 
+		restore(lastElement) in {
+			lastElement = lastElement.element(Tags.baseTag)
+			.attribute(Attributes.typeAttribute, toData(type))
+			.attribute(Attributes.keyAttribute, toData(key)); 
+		};
 	}
 	
 	void archiveNull (string type, string key)
 	{
 		lastElement.element(Tags.nullTag)
-		.attribute(Attributes.typeAttribute, toDataType(type))
-		.attribute(Attributes.keyAttribute, toDataType(key));
+		.attribute(Attributes.typeAttribute, toData(type))
+		.attribute(Attributes.keyAttribute, toData(key));
 	}
 	
-	void archiveObject (string runtimeType, string type, string key, size_t id, void delegate () dg)
+	void archiveObject (string runtimeType, string type, string key, Id id, void delegate () dg)
 	{
-		lastElement = lastElement.element(Tags.objectTag)
-		.attribute(Attributes.runtimeTypeAttribute, toDataType(runtimeType))
-		.attribute(Attributes.typeAttribute, toDataType(type))
-		.attribute(Attributes.keyAttribute, toDataType(key))
-		.attribute(Attributes.idAttribute, toDataType(id));
-		
-		dg();
+		restore(lastElement) in {
+			lastElement = lastElement.element(Tags.objectTag)
+			.attribute(Attributes.runtimeTypeAttribute, toData(runtimeType))
+			.attribute(Attributes.typeAttribute, toData(type))
+			.attribute(Attributes.keyAttribute, toData(key))
+			.attribute(Attributes.idAttribute, toData(id));
+			
+			dg();
+		};
 	}
 	
-	void archivePointer (string key, size_t id)
-	{		
-		lastElement = lastElement.element(Tags.pointerTag)
-		.attribute(Attributes.keyAttribute, toDataType(key))
-		.attribute(Attributes.idAttribute, toDataType(id));
-	}
-	
-	void archiveReference (string key, size_t id)
+	void archivePointer (string key, Id id, void delegate () dg)
 	{
-		lastElement.element(Tags.referenceTag, toDataType(id))
-		.attribute(Attributes.keyAttribute, toDataType(key));
+		restore(lastElement) in {
+			lastElement = lastElement.element(Tags.pointerTag)
+			.attribute(Attributes.keyAttribute, toData(key))
+			.attribute(Attributes.idAttribute, toData(id));
+			
+			dg();
+		};
 	}
 	
-	/*void archiveSlice (Array array, Array slice)
+	void archiveReference (string key, Id id)
+	{
+		lastElement.element(Tags.referenceTag, toData(id))
+		.attribute(Attributes.keyAttribute, toData(key));
+	}
+
+	void archiveSlice (Slice slice, Id sliceId, Id arrayId)
 	{
-		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, string key, size_t id, void delegate () dg)
-	{
-		lastElement = lastElement.element(Tags.structTag)
-		.attribute(Attributes.typeAttribute, toDataType(type))
-		.attribute(Attributes.keyAttribute, toDataType(key));
-		
-		dg();
+		if (auto sliceNode = getArchivedArray(sliceId))
+		{
+			if (auto arrayNode = getArchivedArray(arrayId))
+			{
+				sliceNode.parent.element(Tags.sliceTag, toData(arrayNode.id))
+				.attribute(Attributes.keyAttribute, toData(sliceNode.key))
+				.attribute(Attributes.offsetAttribute, toData(slice.offset))
+				.attribute(Attributes.lengthAttribute, toData(slice.length));
+			}
+		}
 	}
 	
-	void archiveTypedef (string type, string key, size_t id, void delegate () dg)
+	void archiveStruct (string type, string key, Id id, void delegate () dg)
 	{
-		lastElement = lastElement.element(Tags.typedefTag)
-		.attribute(Attributes.typeAttribute, toDataType(type))
-		.attribute(Attributes.keyAttribute, toDataType(key));
-		
-		dg();
+		restore(lastElement) in {
+			lastElement = lastElement.element(Tags.structTag)
+			.attribute(Attributes.typeAttribute, toData(type))
+			.attribute(Attributes.keyAttribute, toData(key));
+			
+			dg();
+		};
 	}
 	
-	void archive (string value, string key, size_t id)
+	void archiveTypedef (string type, string key, Id id, void delegate () dg)
+	{
+		restore(lastElement) in {
+			lastElement = lastElement.element(Tags.typedefTag)
+			.attribute(Attributes.typeAttribute, toData(type))
+			.attribute(Attributes.keyAttribute, toData(key));
+			
+			dg();
+		};
+	}
+	
+	void archive (string value, string key, Id id)
+	{
+		archiveString(value, key, id);
+	}
+	
+	void archive (wstring value, string key, Id id)
+	{
+		archiveString(value, key, id);
+	}
+	
+	void archive (dstring value, string key, Id id)
 	{
 		archiveString(value, key, id);
 	}
 	
-	void archive (wstring value, string key, size_t id)
+	private void archiveString (T) (T value, string key, Id id)
 	{
-		archiveString(value, key, id);
+		restore(lastElement) in {
+			alias ElementTypeOfArray!(T) ElementType;
+			auto array = Array(value.ptr, value.length, ElementType.sizeof);
+			
+			internalArchiveArray(array, ElementType.stringof, key, id, Tags.stringTag, toData(value));
+		};
 	}
 	
-	void archive (dstring value, string key, size_t id)
+	void archive (bool value, string key, Id id)
 	{
-		archiveString(value, key, id);
+		archivePrimitive(value, key);
+	}
+	
+	void archive (byte value, string key, Id id)
+	{
+		archivePrimitive(value, key);
 	}
 	
-	private void archiveString (T) (T value, string key, size_t id)
+	// currently not suppported by to!()
+	/*void archive (cdouble value, string key, Id id)
+	{
+		archivePrimitive(value, key);
+	}*/
+	
+	//currently not implemented but a reserved keyword
+	/*void archive (cent value, string key, Id id)
 	{
-		alias BaseTypeOfArray!(T) ArrayBaseType;
-		auto array = Array(value.ptr, value.length, ArrayBaseType.sizeof);
-		
-		internalArchiveArray(ArrayBaseType.stringof, array, key, id, Tags.stringTag, toDataType(value));
+		archivePrimitive(value, key);
+	}*/
+	
+	//currently not suppported by to!()
+	/*void archive (cfloat value, string key, Id id)
+	{
+		archivePrimitive(value, key);
+	}*/
+	
+	void archive (char value, string key, Id id)
+	{
+		archivePrimitive(value, key);
 	}
 	
-	void archive (bool value, string key, size_t id)
+	//currently not suppported by to!()
+	/*void archive (creal value, string key, Id id)
+	{
+		archivePrimitive(value, key);
+	}*/
+	
+	void archive (dchar value, string key, Id id)
 	{
 		archivePrimitive(value, key);
 	}
 	
-	void archive (byte value, string key, size_t id)
+	void archive (double value, string key, Id id)
+	{
+		archivePrimitive(value, key);
+	}
+	
+	void archive (float value, string key, Id id)
+	{
+		archivePrimitive(value, key);
+	}
+	
+	//currently not suppported by to!()
+	/*void archive (idouble value, string key, Id id)
+	{
+		archivePrimitive(value, key);
+	}*/
+	
+	//currently not suppported by to!()
+	/*void archive (ifloat value, string key, Id id)
+	{
+		archivePrimitive(value, key);
+	}*/
+	
+	void archive (int value, string key, Id id)
 	{
 		archivePrimitive(value, key);
 	}
 	
-	/*void archive (cdouble value, string key, size_t id)
+	//currently not suppported by to!()
+	/*void archive (ireal value, string key, Id id)
 	{
 		archivePrimitive(value, key);
 	}*/
 	
-	/*void archive (cent value, string key, size_t id)
+	void archive (long value, string key, Id id)
+	{
+		archivePrimitive(value, key);
+	}
+	
+	void archive (real value, string key, Id id)
+	{
+		archivePrimitive(value, key);
+	}
+	
+	void archive (short value, string key, Id id)
+	{
+		archivePrimitive(value, key);
+	}
+	
+	void archive (ubyte value, string key, Id id)
+	{
+		archivePrimitive(value, key);
+	}
+	
+	//currently not implemented but a reserved keyword
+	/*void archive (ucent value, string key, Id 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)
+	void archive (uint value, string key, Id 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)
+	void archive (ulong value, string key, Id id)
 	{
 		archivePrimitive(value, key);
 	}
 	
-	/*void archive (idouble value, string key, size_t id)
+	void archive (ushort value, string key, Id 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)
+	void archive (wchar value, string key, Id id)
 	{
 		archivePrimitive(value, key);
 	}
 	
-	/*void archive (ireal value, string key, size_t id)
+	private void archivePrimitive (T) (T value, string key)
+	{
+		lastElement.element(toData(T.stringof), toData(value))
+		.attribute(Attributes.keyAttribute, toData(key));
+	}
+	
+	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();
+		};
+	}
+	
+	void unarchiveArray (Id id, void delegate (size_t) dg)
+	{
+		restore(lastElement) in {			
+			auto element = getElement(Tags.arrayTag, to!(string)(id), Attributes.idAttribute);
+			
+			if (!element.isValid)
+				return;
+	
+			lastElement = element;
+			auto len = getValueOfAttribute(Attributes.lengthAttribute);
+			
+			if (!len)
+				return;
+			
+			auto length = fromData!(size_t)(len);
+			auto stringId = getValueOfAttribute(Attributes.idAttribute);	
+			
+			if (!stringId)
+				return;
+			
+			dg(length);
+		};
+	}
+	
+	void unarchiveAssociativeArray (string key, void delegate (size_t length) dg)
 	{
-		archivePrimitive(value, key);
-	}*/
+		restore(lastElement) in {
+			auto element = getElement(Tags.associativeArrayTag, key);
+			
+			if (!element.isValid)
+				return;
+			
+			lastElement = element;
+			auto len = getValueOfAttribute(Attributes.lengthAttribute);
+			
+			if (!len)
+				return;
+			
+			auto length = fromData!(size_t)(len);
+			
+			dg(length);
+		};
+	}
+	
+	void unarchiveAssociativeArrayKey (string key, void delegate () dg)
+	{
+		internalUnarchiveAAKeyValue(key, Tags.keyTag, dg);
+	}
+	
+	void unarchiveAssociativeArrayValue (string key, void delegate () dg)
+	{
+		internalUnarchiveAAKeyValue(key, Tags.valueTag, dg);
+	}
 	
-	void archive (long value, string key, size_t id)
+	private void internalUnarchiveAAKeyValue (string key, Data tag, void delegate () dg)
+	{
+		restore(lastElement) in {
+			auto element = getElement(tag, key);
+			
+			if (!element.isValid)
+				return;
+			
+			lastElement = element;
+			
+			dg();
+		};
+	}
+	
+	bool unarchiveEnumBool (string key)
+	{
+		return unarchiveEnum!(bool)(key);
+	}
+	
+	byte unarchiveEnumByte (string key)
 	{
-		archivePrimitive(value, key);
+		return unarchiveEnum!(byte)(key);
+	}
+	
+	char unarchiveEnumChar (string key)
+	{
+		return unarchiveEnum!(char)(key);
+	}
+	
+	dchar unarchiveEnumDchar (string key)
+	{
+		return unarchiveEnum!(dchar)(key);
+	}
+	
+	int unarchiveEnumInt (string key)
+	{
+		return unarchiveEnum!(int)(key);
+	}
+	
+	long unarchiveEnumLong (string key)
+	{
+		return unarchiveEnum!(long)(key);
+	}
+	
+	short unarchiveEnumShort (string key)
+	{
+		return unarchiveEnum!(short)(key);
 	}
 	
-	void archive (real value, string key, size_t id)
+	ubyte unarchiveEnumUbyte (string key)
+	{
+		return unarchiveEnum!(ubyte)(key);
+	}
+	
+	uint unarchiveEnumUint (string key)
+	{
+		return unarchiveEnum!(uint)(key);
+	}
+	
+	ulong unarchiveEnumUlong (string key)
+	{
+		return unarchiveEnum!(ulong)(key);
+	}
+	
+	ushort unarchiveEnumUshort (string key)
+	{
+		return unarchiveEnum!(ushort)(key);
+	}
+	
+	wchar unarchiveEnumWchar (string key)
+	{
+		return unarchiveEnum!(wchar)(key);
+	}	
+	
+	private T unarchiveEnum (T) (string key)
 	{
-		archivePrimitive(value, key);
+		auto element = getElement(Tags.enumTag, key);
+		
+		if (!element.isValid)
+			return T.init;
+		
+		return fromData!(T)(element.value);
+	}
+	
+	void unarchiveObject (string key, out Id id, out Object result, void delegate () dg)
+	{
+		restore(lastElement) in {
+			auto tmp = getElement(Tags.objectTag, key, Attributes.keyAttribute, false);
+
+			if (!tmp.isValid)
+			{
+				lastElement = getElement(Tags.nullTag, key);
+				return;
+			}
+
+			lastElement = tmp;
+			
+			auto runtimeType = getValueOfAttribute(Attributes.runtimeTypeAttribute);
+
+			if (!runtimeType)
+				return;
+			
+			auto name = fromData!(string)(runtimeType);
+			auto stringId = getValueOfAttribute(Attributes.idAttribute);
+
+			if (!stringId)
+				return;
+
+			id = stringId.toId();
+			result = newInstance(name);
+			dg();
+		};
 	}
 	
-	void archive (short value, string key, size_t id)
+	Id unarchivePointer (string key, void delegate () dg)
 	{
-		archivePrimitive(value, key);
+		return restore!(Id)(lastElement) in {
+			auto tmp = getElement(Tags.pointerTag, key, Attributes.keyAttribute, false);
+			
+			if (!tmp.isValid)
+			{
+				lastElement = getElement(Tags.nullTag, key);
+				return Id.max;
+			}
+			
+			lastElement = tmp;
+			auto stringId = getValueOfAttribute(Attributes.idAttribute);
+
+			if (!stringId)
+				return Id.max;
+			
+			dg();
+			
+			return stringId.toId();
+		};
+	}
+	
+	Id unarchiveReference (string key)
+	{
+		auto element = getElement(Tags.referenceTag, key, Attributes.keyAttribute, false);
+		
+		if (element.isValid)
+			return toId(element.value);
+		
+		return Id.max;
 	}
 	
-	void archive (ubyte value, string key, size_t id)
+	Slice unarchiveSlice (string key)
+	{
+		auto element = getElement(Tags.sliceTag, key, Attributes.keyAttribute, false);
+
+		if (element.isValid)
+		{
+			auto length = fromData!(size_t)(getValueOfAttribute(Attributes.lengthAttribute, element));
+			auto offset = fromData!(size_t)(getValueOfAttribute(Attributes.offsetAttribute, element));
+			auto id = toId(element.value);
+			
+			return Slice(length, offset, id);
+		}
+		
+		return Slice.init;
+	}
+	
+	void unarchiveStruct (string key, void delegate () dg)
 	{
-		archivePrimitive(value, key);
+		restore(lastElement) in {
+			auto element = getElement(Tags.structTag, key);
+		
+			if (!element.isValid)
+				return;
+			
+			lastElement = element;			
+			dg();
+		};
+	}
+	
+	private T unarchiveTypeDef (T) (DataType key)
+	{
+		auto element = getElement(Tags.typedefTag, key);
+		
+		if (element.isValid)
+			lastElement = element;
+		
+		return T.init;
 	}
 	
-	/*void archive (ucent value, string key, size_t id)
+	void unarchiveTypedef (string key, void delegate () dg)
+	{
+		restore(lastElement) in {
+			auto element = getElement(Tags.typedefTag, key);
+			
+			if (!element.isValid)
+				return;
+			
+			lastElement = element;
+			dg();
+		};
+	}
+	
+	string unarchiveString (string key, out Id id)
+	{
+		return internalUnarchiveString!(string)(key, id);
+	}
+	
+	wstring unarchiveWstring (string key, out Id id)
+	{
+		return internalUnarchiveString!(wstring)(key, id);
+	}
+	
+	dstring unarchiveDstring (string key, out Id id)
+	{
+		return internalUnarchiveString!(dstring)(key, id);
+	}
+	
+	private T internalUnarchiveString (T) (string key, out Id id)
 	{
-		archivePrimitive(value, key);
+		auto element = getElement(Tags.stringTag, key);
+		
+		if (!element.isValid)
+			return T.init;
+
+		auto value = fromData!(T)(element.value);
+		auto stringId = getValueOfAttribute(Attributes.idAttribute, element);
+
+		if (!stringId)
+			return T.init;
+
+		id = stringId.toId();
+		return value;
+	}
+	
+	string unarchiveString (Id id)
+	{
+		return internalUnarchiveString!(string)(id);
+	}
+	
+	wstring unarchiveWstring (Id id)
+	{
+		return internalUnarchiveString!(wstring)(id);
+	}
+	
+	dstring unarchiveDstring (Id id)
+	{
+		return internalUnarchiveString!(dstring)(id);
+	}
+	
+	private T internalUnarchiveString (T) (Id id)
+	{
+		auto element = getElement(Tags.stringTag, to!(string)(id), Attributes.idAttribute);
+		
+		if (!element.isValid)
+			return T.init;
+
+		return fromData!(T)(element.value);
+	}
+	
+	bool unarchiveBool (string key)
+	{
+		return unarchivePrimitive!(bool)(key);
+	}
+	
+	byte unarchiveByte (string key)
+	{
+		return unarchivePrimitive!(byte)(key);
+	}
+	
+	//currently not suppported by to!()
+    /*cdouble unarchiveCdouble (string key)
+	{
+		return unarchivePrimitive!(cdouble)(key);
+	}*/
+	 
+	 //currently not implemented but a reserved keyword
+    /*cent unarchiveCent (string key)
+	{
+		return unarchivePrimitive!(cent)(key);
 	}*/
 	
-	void archive (uint value, string key, size_t id)
+	// currently not suppported by to!()
+    /*cfloat unarchiveCfloat (string key)
+	{
+		return unarchivePrimitive!(cfloat)(key);
+	}*/
+	
+	char unarchiveChar (string key)
 	{
-		archivePrimitive(value, key);
+		return unarchivePrimitive!(char)(key);
+	}
+	 
+	 //currently not implemented but a reserved keyword
+	/*creal unarchiveCreal (string key)
+	{
+		return unarchivePrimitive!(creal)(key);
+	}*/
+	
+	dchar unarchiveDchar (string key)
+	{
+		return unarchivePrimitive!(dchar)(key);
 	}
 	
-	void archive (ulong value, string key, size_t id)
+	double unarchiveDouble (string key)
 	{
-		archivePrimitive(value, key);
+		return unarchivePrimitive!(double)(key);
 	}
 	
-	void archive (ushort value, string key, size_t id)
+	float unarchiveFloat (string key)
+	{
+		return unarchivePrimitive!(float)(key);
+	}
+
+	//currently not suppported by to!()
+    /*idouble unarchiveIdouble (string key)
+	{
+		return unarchivePrimitive!(idouble)(key);
+	}*/
+    
+    // currently not suppported by to!()*/
+    /*ifloat unarchiveIfloat (string key)
+	{
+		return unarchivePrimitive!(ifloat)(key);
+	}*/
+
+	int unarchiveInt (string key)
+	{
+		return unarchivePrimitive!(int)(key);
+	}
+
+	// currently not suppported by to!()
+    /*ireal unarchiveIreal (string key)
+	{
+		return unarchivePrimitive!(ireal)(key);
+	}*/
+
+	long unarchiveLong (string key)
+	{
+		return unarchivePrimitive!(long)(key);
+	}
+	
+	real unarchiveReal (string key)
 	{
-		archivePrimitive(value, key);
+		return unarchivePrimitive!(real)(key);
+	}
+	
+	short unarchiveShort (string key)
+	{
+		return unarchivePrimitive!(short)(key);
+	}
+	
+	ubyte unarchiveUbyte (string key)
+	{
+		return unarchivePrimitive!(ubyte)(key);
+	}
+
+	// currently not implemented but a reserved keyword
+    /*ucent unarchiveCcent (string key)
+	{
+		return unarchivePrimitive!(ucent)(key);
+	}*/
+
+	uint unarchiveUint (string key)
+	{
+		return unarchivePrimitive!(uint)(key);
+	}
+	
+	ulong unarchiveUlong (string key)
+	{
+		return unarchivePrimitive!(ulong)(key);
+	}
+	
+	ushort unarchiveUshort (string key)
+	{
+		return unarchivePrimitive!(ushort)(key);
+	}
+	
+	wchar unarchiveWchar (string key)
+	{
+		return unarchivePrimitive!(wchar)(key);
 	}
 	
-	void archive (wchar value, string key, size_t id)
+	T unarchivePrimitive (T) (string key)
+	{
+		auto element = getElement(toData(T.stringof), key);
+
+		if (!element.isValid)
+			return T.init;
+		
+		return fromData!(T)(element.value);
+	}
+	
+	void postProcessArray (Id id)
 	{
-		archivePrimitive(value, key);
-	}	
+		if (auto array = getArchivedArray(id))
+			array.parent.attach(array.node);
+	}
+	
+	private void addArchivedArray (Id id, doc.Node parent, doc.Node element, string key)
+	{
+		archivedArrays[id] = ArrayNode(parent, element, id, key);
+	}
+	
+	private ArrayNode* getArchivedArray (Id id)
+	{
+		if (auto array = id in archivedArrays)
+			return array;
+
+		errorCallback(new ArchiveException(`Could not continue archiving due to no array with the Id "` ~ to!(string)(id) ~ `" was found.`, __FILE__, __LINE__), [to!(string)(id)]);
+		
+		return null;
+	}
 	
-	private void archivePrimitive (T) (T value, string key)
+	private doc.Node getElement (Data tag, string k, Data attribute = Attributes.keyAttribute, bool throwOnError = true)
+	{		
+		auto key = toData(k);
+		
+		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 Data getValueOfAttribute (Data attribute, doc.Node element = doc.Node.invalid)
 	{
-		lastElement.element(toDataType(T.stringof), toDataType(value))
-		.attribute(Attributes.keyAttribute, toDataType(key));
+		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;
 	}
 	
 	version (Tango)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/orange/test/UnitTester.d	Tue Oct 19 10:22:10 2010 +0200
@@ -0,0 +1,177 @@
+/**
+ * Copyright: Copyright (c) 2010 Jacob Carlborg. All rights reserved.
+ * Authors: Jacob Carlborg
+ * Version: Initial created: Oct 17, 2010
+ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
+ */
+module orange.test.UnitTester;
+
+import tango.core.Exception;
+import orange.core._;
+import orange.util._;
+
+class UnitTester
+{	
+	private
+	{
+		struct Test
+		{
+			void delegate () test;
+			string message;
+			AssertException exception;
+			
+			bool failed ()
+			{
+				return !succeeded;
+			}
+			
+			bool succeeded ()
+			{
+				return !exception;
+			}
+			
+			void run ()
+			{
+				if (!isPending)
+					test();
+			}
+			
+			bool isPending ()
+			{
+				return test is null;
+			}
+		}
+		
+		Test[] tests;
+		AssertException[] exceptions;
+		void delegate () pre_;
+		void delegate () post_;
+		size_t failures;
+		size_t pending;
+		size_t lastIndex = size_t.max;
+	}	
+	
+	Use!(void delegate (), string) test (string message)
+	{
+		tests ~= Test(null, message);
+		lastIndex++;
+		
+		Use!(void delegate (), string) use;
+		
+		use.args[0] = &internalTest;		
+		use.args[1] = message;
+		
+		return use;
+	}
+	
+	void run ()
+	{
+		foreach (test ; tests)
+		{
+			if (test.isPending)
+				pending++;
+			
+			try
+			{
+				execute in {
+					test.run();
+				};				
+			}				
+			
+			catch (AssertException e)
+			{
+				exceptions ~= e;
+				failures++;
+			}				
+		}
+		
+		printResult;
+	}
+	
+	void delegate () pre ()
+	{
+		return pre_;
+	}
+	
+	void delegate () pre (void delegate () pre)
+	{
+		return pre_ = pre;
+	}
+	
+	void delegate () post ()
+	{
+		return post_;
+	}
+
+	void delegate () post (void delegate () post)
+	{
+		return post_ = post;
+	}
+	
+	private void internalTest (void delegate () dg, string message)
+	{
+		tests[lastIndex] = Test(dg, message);
+	}
+	
+	private void printResult ()
+	{	
+		if (isAllTestsSuccessful)
+			return printSuccess();
+		
+		foreach (test ; tests)
+		{
+			print("- ", test.message);
+			
+			if (test.isPending)
+				print(" ", "(PENDING: Not Yet Implemented)");
+			
+			println();
+		}
+		
+		print("\n", tests.length, " test, ", failures, " failures");
+		printPending();	
+		println();
+	}
+	
+	private void printPending ()
+	{
+		if (hasPending)
+			print(", ", pending, " pending");
+	}
+	
+	private void printSuccess ()
+	{
+		println("All ", tests.length, " tests passed successfully.");
+	}
+	
+	private bool isAllTestsSuccessful ()
+	{
+		return !hasPending && !hasFailures;
+	}
+	
+	private bool hasPending ()
+	{
+		return pending > 0;
+	}
+	
+	private bool hasFailures ()
+	{
+		return failures > 0;
+	}
+	
+	private Use!(void delegate ()) execute ()
+	{
+		Use!(void delegate ()) use;
+		
+		use.args[0] = &executeImpl;
+		
+		return use;
+	}
+	
+	private void executeImpl (void delegate () dg)
+	{
+		if (pre) pre();
+		if (dg) dg();
+		if (post) post();
+	}
+}
\ No newline at end of file
--- a/orange/util/CTFE.d	Wed Oct 06 16:18:02 2010 +0200
+++ b/orange/util/CTFE.d	Tue Oct 19 10:22:10 2010 +0200
@@ -6,7 +6,7 @@
  */
 module orange.util.CTFE;
 
-import orange.util.string;
+import orange.core.string;
 import orange.util.Traits;
 
 template format (ARGS...)
--- a/orange/util/Reflection.d	Wed Oct 06 16:18:02 2010 +0200
+++ b/orange/util/Reflection.d	Tue Oct 19 10:22:10 2010 +0200
@@ -6,8 +6,8 @@
  */
 module orange.util.Reflection;
 
+import orange.core.string;
 import orange.util.CTFE;
-import orange.util.string;
 
 /**
  * Returns the name of the given function
--- a/orange/util/Traits.d	Wed Oct 06 16:18:02 2010 +0200
+++ b/orange/util/Traits.d	Tue Oct 19 10:22:10 2010 +0200
@@ -123,9 +123,9 @@
 	const bool isReference = isObject!(T) || isPointer!(T);
 }
 
-template isTypeDef (T)
+template isTypedef (T)
 {
-	const bool isTypeDef = is(T == typedef);
+	const bool isTypedef = is(T == typedef);
 }
 
 template isVoid (T)
@@ -133,13 +133,9 @@
 	const bool isVoid = is(T == void);
 }
 
-template BaseTypeOfArray (T)
+template ElementTypeOfArray(T : T[])
 {
-	static if (is(T U : U[]))
-		alias BaseTypeOfArray!(U) BaseTypeOfArray;
-	
-	else
-		alias T BaseTypeOfArray;
+	alias T ElementTypeOfArray;
 }
 
 template BaseTypeOfPointer (T)
@@ -151,13 +147,22 @@
 		alias T BaseTypeOfPointer;
 }
 
-template BaseTypeOfTypeDef (T)
+template BaseTypeOfTypedef (T)
 {
 	static if (is(T U == typedef))
-		alias BaseTypeOfTypeDef!(U) BaseTypeOfTypeDef;
+		alias BaseTypeOfTypedef!(U) BaseTypeOfTypedef;
 	
 	else
-		alias T BaseTypeOfTypeDef;
+		alias T BaseTypeOfTypedef;
+}
+
+template BaseTypeOfEnum (T)
+{
+	static if (is(T U == enum))
+		alias BaseTypeOfEnum!(U) BaseTypeOfEnum;
+	
+	else
+		alias T BaseTypeOfEnum;
 }
 
 template KeyTypeOfAssociativeArray (T)
--- a/orange/util/Use.d	Wed Oct 06 16:18:02 2010 +0200
+++ b/orange/util/Use.d	Tue Oct 19 10:22:10 2010 +0200
@@ -21,7 +21,7 @@
 	alias ParameterTypeTuple ParameterTupleOf;
 }
 
-struct OpInStruct (ARGS...)
+struct Use (ARGS...)
 {
 	static assert (ARGS.length > 0);
 	
--- a/orange/util/_.d	Wed Oct 06 16:18:02 2010 +0200
+++ b/orange/util/_.d	Tue Oct 19 10:22:10 2010 +0200
@@ -9,8 +9,6 @@
 public:
 
 import orange.util.CTFE;
-import orange.util.io;
 import orange.util.Reflection;
-import orange.util.string;
 import orange.util.Traits;
 import orange.util.Use;
\ No newline at end of file
--- a/orange/util/io.d	Wed Oct 06 16:18:02 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/**
- * Copyright: Copyright (c) 2007-2008 Jacob Carlborg. All rights reserved.
- * Authors: Jacob Carlborg
- * Version: Initial created: 2007
- * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
- * 
- */
-module orange.util.io;
-
-version (Tango)
-{
-	import tango.io.Stdout;
-	import tango.io.Console;
-	
-	import orange.util.string;
-}
-
-else 
-	import std.stdio;
-
-/**
- * Print to the standard output
- * 
- * Params:
- *     args = what to print
- */
-void print (A...)(A args)
-{
-	version (Tango)
-	{
-		const string fmt = "{}{}{}{}{}{}{}{}"
-					        "{}{}{}{}{}{}{}{}"
-					        "{}{}{}{}{}{}{}{}";
-				
-		static assert (A.length <= fmt.length / 2, "mambo.io.print :: too many arguments");
-		
-		Stdout.format(fmt[0 .. args.length * 2], args).flush;
-	}
-		
-	
-	else
-		write(args);
-}
-
-/**
- * Print to the standard output, adds a new line
- * 
- * Params:
- *     args = what to print
- */
-void println (A...)(A args)
-{
-	version (Tango)
-	{
-		const string fmt = "{}{}{}{}{}{}{}{}"
-					        "{}{}{}{}{}{}{}{}"
-					        "{}{}{}{}{}{}{}{}";
-
-		static assert (A.length <= fmt.length / 2, "mambo.io.println :: too many arguments");
-		
-		Stdout.formatln(fmt[0 .. args.length * 2], args);
-	}
-
-	else
-		writeln(args);
-}
\ No newline at end of file
--- a/orange/util/string.d	Wed Oct 06 16:18:02 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,888 +0,0 @@
-/**
- * Copyright: Copyright (c) 2008-2009 Jacob Carlborg. All rights reserved.
- * Authors: Jacob Carlborg
- * Version: Initial created: 2008
- * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
- * 
- */
-module orange.util.string;
-
-public import orange.util.collection.Array;
-
-version (Tango)
-{
-	static import tango.stdc.stringz;
-	import tango.text.Unicode : toFold, isDigit;
-	import tango.text.convert.Utf;
-	import tango.text.Util;
-	
-	alias tango.stdc.stringz.toStringz toStringz;
-	alias tango.stdc.stringz.toString16z toString16z;
-	alias tango.stdc.stringz.toString32z toString32z;
-	
-	alias tango.stdc.stringz.fromStringz fromStringz;
-	alias tango.stdc.stringz.fromString16z fromString16z;
-	alias tango.stdc.stringz.fromString32z fromString32z;
-	
-	alias tango.text.convert.Utf.toString16 toString16;
-	alias tango.text.convert.Utf.toString32 toString32;
-}
-
-else
-{	
-	import std.string;
-	import std.utf;
-	import std.ctype : isxdigit;
-	
-	version = Phobos;
-	
-	private alias std.string.tolower toFold;
-	
-	alias std.utf.toUTF8 toString;
-	alias std.utf.toUTF16 toString16;
-	alias std.utf.toUTF32 toString32;
-	
-	alias std.string.toStringz toStringz;
-	alias std.utf.toUTF16z toString16z;
-	
-	alias std.string.toString fromStringz;
-}
-
-version (Tango)
-{
-	/**
-	 * string alias
-	 */
-	alias char[] string;
-
-	/**
-	 * wstring alias
-	 */
-	alias wchar[] wstring;
-
-	/**
-	 * dstring alias
-	 */
-	alias dchar[] dstring;
-}
-
-/**
- * Compares the $(D_PSYMBOL string) to another $(D_PSYMBOL string), ignoring case
- * considerations.  Two strings are considered equal ignoring case if they are of the
- * same length and corresponding characters in the two strings  are equal ignoring case.
- * 
- * Params:
- *     str = The $(D_PSYMBOL string) first string to compare to
- *     anotherString = The $(D_PSYMBOL string) to compare the first $(D_PSYMBOL string) with
- *     
- * Returns: $(D_KEYWORD true) if the arguments is not $(D_KEYWORD null) and it
- *          represents an equivalent $(D_PSYMBOL string) ignoring case; $(D_KEYWORD false) otherwise
- *          
- * Throws: AssertException if the length of any of the strings is 0
- *          
- * See_Also: opEquals(Object)
- */
-bool equalsIgnoreCase (string str, string anotherString)
-in
-{
-	assert(str.length > 0, "mambo.string.equalsIgnoreCase: The length of the first string was 0");
-	assert(anotherString.length > 0, "mambo.string.equalsIgnoreCase: The length of the second string was 0");
-}
-body
-{	
-	if (str == anotherString)
-		return true;
-
-	return toFold(str) == toFold(anotherString);
-}
-
-/**
- * Compares the $(D_PSYMBOL wstring) to another $(D_PSYMBOL wstring), ignoring case
- * considerations. Two wstrings are considered equal ignoring case if they are of the
- * same length and corresponding characters in the two wstrings are equal ignoring case.
- * 
- * Params:
- *     str = The $(D_PSYMBOL wstring) first string to compre to
- *     anotherString = The $(D_PSYMBOL wstring) to compare the first $(D_PSYMBOL wstring) against
- *     
- * Returns: $(D_KEYWORD true) if the argument is not $(D_KEYWORD null) and it
- *          represents an equivalent $(D_PSYMBOL wstring) ignoring case; (D_KEYWORD
- *          false) otherwise
- *          
- * Throws: AssertException if the length of any of the wstrings is 0
- *          
- * See_Also: opEquals(Object)
- */
-bool equalsIgnoreCase (wstring str, wstring anotherString)
-in
-{
-	assert(str.length > 0, "mambo.string.equalsIgnoreCase: The length of the first string was 0");
-	assert(anotherString.length > 0, "mambo.string.equalsIgnoreCase: The length of the second string was 0");
-}
-body
-{
-	if (str == anotherString)
-		return true;
-
-	version (Tango)
-		return toFold(str) == toFold(anotherString);
-
-	else
-		return toFold(toUTF8(str)) == toFold(toUTF8(anotherString));
-}
-
-/**
- * Compares the $(D_PSYMBOL dstring) to another $(D_PSYMBOL dstring), ignoring case
- * considerations. Two wstrings are considered equal ignoring case if they are of the
- * same length and corresponding characters in the two wstrings are equal ignoring case.
- * 
- * Params:
- *     str = The $(D_PSYMBOL dstring) first string to compare to
- *     anotherString = The $(D_PSYMBOL wstring) to compare the first $(D_PSYMBOL dstring) against
- *     
- * Returns: $(D_KEYWORD true) if the argument is not $(D_KEYWORD null) and it
- *          represents an equivalent $(D_PSYMBOL dstring) ignoring case; $(D_KEYWORD false) otherwise
- *          
- * Throws: AssertException if the length of any of the dstrings are 0
- *          
- * See_Also: opEquals(Object)
- */
-bool equalsIgnoreCase (dstring str, dstring anotherString)
-in
-{
-	assert(str.length > 0, "mambo.string.equalsIgnoreCase: The length of the first string was 0");
-	assert(anotherString.length > 0, "mambo.string.equalsIgnoreCase: The length of the second string was 0");
-}
-body
-{
-	if (str == anotherString)
-		return true;
-
-	version (Tango)
-		return toFold(str) == toFold(anotherString);
-
-	else
-		return toFold(toUTF8(str)) == toFold(toUTF8(anotherString));
-}
-
-/**
- * Returns the char value at the specified index. An index ranges from 0 to length - 1.
- * The first $(D_KEYWORD char) value of the sequence is at index 0, the next at index 1,
- * and so on, as for array indexing.
- * 
- * Params:
- * 	   str = the string to get the $(D_KEYWORD char) from
- *     index = the index of the $(D_KEYWORD char) value.
- *     
- * Returns: the $(D_KEYWORD char) value at the specified index of the string.
- *          The first $(D_KEYWORD char) value is at index 0.
- * 
- * Throws: AssertException if the length of the string is 0
- * Throws: AssertException if the $(D_CODE index) argument is
- *         not less than the length of the string.
- */
-char charAt (string str, size_t index)
-in
-{
-	assert(str.length > 0, "mambo.string.charAt: The length of the string was 0");
-	assert(index <= str.length, "mambo.string.charAt: The index was to greater than the length of the string");
-}
-body
-{
-	return str[index];
-}
-
-/**
- * Returns the $(D_KEYWORD char) value at the specified index. An index ranges from 0 to
- * length - 1. The first $(D_KEYWORD char) value of the sequence is at index 0, the next
- * at index 1, and so on, as for array indexing.
- * 
- * Params:
- * 	   str = the wstring to get the $(D_KEYWORD char) from
- *     index = the index of the $(D_KEYWORD char) value.
- *     
- * Returns: the $(D_KEYWORD char) value at the specified index of the wstring.
- *          The first $(D_KEYWORD char) value is at index 0.
- * 
- * Throws: AssertException if the length of the wstring is 0
- * Throws: AssertException if the $(D_CODE index) argument is
- *         not less than the length of the wstring.
- */
-wchar charAt (wstring str, size_t index)
-in
-{
-	assert(str.length > 0, "mambo.string.charAt: The length of the string was 0");
-	assert(index <= str.length, "mambo.string.charAt: The index was to greater than the length of the string");
-}
-body
-{
-	return str[index];
-}
-
-/**
- * Returns the $(D_KEYWORD char) value at the specified index. An index ranges from 0 to
- * length - 1. The first $(D_KEYWORD char) value of the sequence is at index 0, the next
- * at index 1, and so on, as for array indexing.
- * 
- * Params:
- * 	   str = the dstring to get the $(D_KEYWORD char) from
- *     index = the index of the $(D_KEYWORD char) value.
- *     
- * Returns: the $(D_KEYWORD char) value at the specified index of the dstring.
- *          The first $(D_KEYWORD char) value is at index 0.
- * 
- * Throws: AssertException if the length of the dstring is 0
- * Throws: AssertException if the $(D_CODE index) argument is
- *         not less than the length of the dstring.
- */
-dchar charAt (dstring str, size_t index)
-in
-{
-	assert(str.length > 0, "mambo.string.charAt: The length of the string was 0");
-	assert(index <= str.length, "mambo.string.charAt: The index was to greater than the length of the string");
-}
-body
-{
-	return str[index];
-}
-
-/**
- * Returns a new string that is a substring of the specified string. The substring begins
- * at the specified $(D_PARAM beginIndex) and extends to the character at index
- * $(D_PARAM endIndex) - 1. Thus the length of the substring is $(D_PARAM endIndex - beginIndex).
- * 
- * Examples:
- * ---
- * "hamburger".substring(4, 8) returns "urge"
- * "smiles".substring(1, 5) returns "mile"
- * ---
- * 
- * Params:
- * 	   str = the string to get the substring from
- *     beginIndex = the beginning index, inclusive.
- *     endIndex = the ending index, exclusive.
- *     
- * Returns: the specified substring.
- * 
- * Throws: AssertException if the length of the string is 0
- * Throws: AssertException if the $(D_PARAM beginIndex) is 
- * 		   larger than $(D_PARAM endIndex).
- * Throws: AssertException if $(D_PARAM endIndex) is larger than the 
- *  	   length of the $(D_PSYMBOL string).
- */
-string substring (string str, size_t beginIndex, size_t endIndex)
-in
-{
-	assert(str.length > 0, "mambo.string.substring: The length of the string was 0");
-	assert(beginIndex < endIndex, "mambo.string.substring: The first index was greater the second");
-	assert(endIndex <= str.length, "mambo.string.substring: The second index was greater then the length of the string");
-}
-body
-{
-	version (Tango) return str[beginIndex .. endIndex].dup;
-	else return str[beginIndex .. endIndex].idup;
-}
-
-/**
- * Returns a new string that is a substring of the specified string. The substring begins
- * at the specified $(D_PARAM beginIndex) and extends to the character at index
- * $(D_PARAM endIndex) - 1. Thus the length of the substring is $(D_PARAM endIndex - beginIndex).
- * 
- * Examples:
- * ---
- * "hamburger".substring(4, 8) returns "urge"
- * "smiles".substring(1, 5) returns "mile"
- * ---
- * 
- * Params:
- * 	   str = the string to get the substring from
- *     beginIndex = the beginning index, inclusive.
- *     endIndex = the ending index, exclusive.
- *     
- * Returns: the specified substring.
- * 
- * Throws: AssertException if the length of the string is 0
- * Throws: AssertException if the $(D_PARAM beginIndex) is 
- * 		   larger than $(D_PARAM endIndex).
- * Throws: AssertException if $(D_PARAM endIndex) is larger than the 
- *  	   length of the $(D_PSYMBOL string).
- */
-wstring substring (wstring str, size_t beginIndex, size_t endIndex)
-in
-{
-	assert(str.length > 0, "mambo.string.substring: The length of the string was 0");
-	assert(beginIndex < endIndex, "mambo.string.substring: The first index was greater the second");
-	assert(endIndex <= str.length, "mambo.string.substring: The second index was greater then the length of the string");
-}
-body
-{
-	version (Tango) return str[beginIndex .. endIndex].dup;
-	else return str[beginIndex .. endIndex].idup;
-}
-
-/**
- * Returns a new string that is a substring of the specified string. The substring begins
- * at the specified $(D_PARAM beginIndex) and extends to the character at index
- * $(D_PARAM endIndex) - 1. Thus the length of the substring is $(D_PARAM endIndex - beginIndex).
- * 
- * Examples:
- * ---
- * "hamburger".substring(4, 8) returns "urge"
- * "smiles".substring(1, 5) returns "mile"
- * ---
- * 
- * Params:
- * 	   str = the string to get the substring from
- *     beginIndex = the beginning index, inclusive.
- *     endIndex = the ending index, exclusive.
- *     
- * Returns: the specified substring.
- * 
- * Throws: AssertException if the length of the string is 0
- * Throws: AssertException if the $(D_PARAM beginIndex) is 
- * 		   larger than $(D_PARAM endIndex).
- * Throws: AssertException if $(D_PARAM endIndex) is larger than the 
- *  	   length of the $(D_PSYMBOL string).
- */
-dstring substring (dstring str, size_t beginIndex, size_t endIndex)
-in
-{
-	assert(str.length > 0, "mambo.string.substring: The length of the string was 0");
-	assert(beginIndex < endIndex, "mambo.string.substring: The first index was greater the second");
-	assert(endIndex <= str.length, "mambo.string.substring: The second index was greater then the length of the string");
-}
-body
-{
-	version (Tango) return str[beginIndex .. endIndex].dup;
-	else return str[beginIndex .. endIndex].idup;
-}
-
-/**
- * Returns a new string that is a substring of the specified string. The substring begins
- * with the character at the specified index and extends to the end of the string. 
- * 
- * Examples:
- * ---
- * "unhappy".substring(2) returns "happy"
- * "Harbison".substring(3) returns "bison"
- * "emptiness".substring(9) returns "" (an empty string)
- * ---
- * 
- * Params:
- *     str = the string to get the substring from
- *     beginIndex = the beginning index, inclusive
- *     
- * Returns: the specified substring
- * 
- * Throws: AssertException if the length of the string is 0
- * Throws: AssertException if the $(D_PARAM beginIndex) is 
- * 		   larger than the length of the string.
- */
-string substring (string str, size_t index)
-in
-{
-	assert(str.length > 0, "mambo.string.substring: The length of the string was 0");
-	assert(index < str.length, "mambo.string.substring: The index was greater than the length of the string");
-}
-body
-{
-	return str.substring(index, str.length);
-}
-
-/**
- * Returns a new string that is a substring of the specified string. The substring begins
- * with the character at the specified index and extends to the end of the string. 
- * 
- * Examples:
- * ---
- * "unhappy".substring(2) returns "happy"
- * "Harbison".substring(3) returns "bison"
- * "emptiness".substring(9) returns "" (an empty string)
- * ---
- * 
- * Params:
- *     str = the string to get the substring from
- *     beginIndex = the beginning index, inclusive
- *     
- * Returns: the specified substring
- * 
- * Throws: AssertException if the length of the string is 0
- * Throws: AssertException if the $(D_PARAM beginIndex) is 
- * 		   larger than the length of the string.
- */
-wstring substring (wstring str, size_t index)
-in
-{
-	assert(str.length > 0, "mambo.string.substring: The length of the string was 0");
-	assert(index < str.length, "mambo.string.substring: The index was greater than the length of the string");
-}
-body
-{
-	return str.substring(index, str.length);
-}
-
-/**
- * Returns a new string that is a substring of the specified string. The substring begins
- * with the character at the specified index and extends to the end of the string. 
- * 
- * Examples:
- * ---
- * "unhappy".substring(2) returns "happy"
- * "Harbison".substring(3) returns "bison"
- * "emptiness".substring(9) returns "" (an empty string)
- * ---
- * 
- * Params:
- *     str = the string to get the substring from
- *     beginIndex = the beginning index, inclusive
- *     
- * Returns: the specified substring
- * 
- * Throws: AssertException if the length of the string is 0
- * Throws: AssertException if the $(D_PARAM beginIndex) is 
- * 		   larger than the length of the string.
- */
-dstring substring (dstring str, size_t index)
-in
-{
-	assert(str.length > 0, "mambo.string.substring: The length of the string was 0");
-	assert(index < str.length, "mambo.string.substring: The index was greater than the length of the string");
-}
-body
-{
-	return str.substring(index, str.length);
-}
-
-/**
- * Returns a new string that is a substring of the given string.
- * 
- * This substring is the character sequence that starts at character
- * position pos and has a length of n characters.
- * 
- * Params:
- *     str = the string to get the substring from
- *     pos = position of a character in the current string to be used 
- *     		 as starting character for the substring.
- *     n = Length of the substring. If this value would make the 
- *     	   substring to span past the end of the current string content,
- *     	   only those characters until the end of the string are used. 
- *     	   size_t.max is the greatest possible value for an element of
- *     	   type size_t, therefore, when this value is used, all the
- *     	   characters between pos and the end of the string are used as
- *     	   the initialization substring.
- *     
- * Returns: a string containing a substring of the given string
- * 
- * Throws: AssertException if pos is greater than the length of the string
- */
-string substr (string str, size_t pos = 0, size_t n = size_t.max)
-in
-{
-	assert(pos < str.length, "mambo.string.substr: The given position was greater than the length of the string.");
-}
-body
-{
-	size_t end;
-	
-	if (n == size_t.max)
-		end = str.length;
-	
-	else
-	{
-		end = pos + n;
-		
-		if (end > str.length)
-			end = str.length;
-	}
-	
-	version (Tango) return str[pos .. end].dup;
-	else return str[pos .. end].idup;
-}
-
-/**
- * Returns a new string that is a substring of the given string.
- * 
- * This substring is the character sequence that starts at character
- * position pos and has a length of n characters.
- * 
- * Params:
- *     str = the string to get the substring from
- *     pos = position of a character in the current string to be used 
- *     		 as starting character for the substring.
- *     n = Length of the substring. If this value would make the 
- *     	   substring to span past the end of the current string content,
- *     	   only those characters until the end of the string are used. 
- *     	   size_t.max is the greatest possible value for an element of
- *     	   type size_t, therefore, when this value is used, all the
- *     	   characters between pos and the end of the string are used as
- *     	   the initialization substring.
- *     
- * Returns: a string containing a substring of the given string
- * 
- * Throws: AssertException if pos is greater than the length of the string
- */
-wstring substr (wstring str, size_t pos = 0, size_t n = size_t.max)
-in
-{
-	assert(pos < str.length, "mambo.string.substr: The given position was greater than the length of the string.");
-}
-body
-{
-	size_t end;
-	
-	if (n == size_t.max)
-		end = str.length;
-	
-	else
-	{
-		end = pos + n;
-		
-		if (end > str.length)
-			end = str.length;
-	}
-	
-	version (Tango) return str[pos .. end].dup;
-	else return str[pos .. end].idup;
-}
-
-/**
- * Returns a new string that is a substring of the given string.
- * 
- * This substring is the character sequence that starts at character
- * position pos and has a length of n characters.
- * 
- * Params:
- *     str = the string to get the substring from
- *     pos = position of a character in the current string to be used 
- *     		 as starting character for the substring.
- *     n = Length of the substring. If this value would make the 
- *     	   substring to span past the end of the current string content,
- *     	   only those characters until the end of the string are used. 
- *     	   size_t.max is the greatest possible value for an element of
- *     	   type size_t, therefore, when this value is used, all the
- *     	   characters between pos and the end of the string are used as
- *     	   the initialization substring.
- *     
- * Returns: a string containing a substring of the given string
- * 
- * Throws: AssertException if pos is greater than the length of the string
- */
-dstring substr (dstring str, size_t pos = 0, size_t n = size_t.max)
-in
-{
-	assert(pos < str.length, "mambo.string.substr: The given position was greater than the length of the string.");
-}
-body
-{
-	size_t end;
-	
-	if (n == size_t.max)
-		end = str.length;
-	
-	else
-	{
-		end = pos + n;
-		
-		if (end > str.length)
-			end = str.length;
-	}
-	
-	version (Tango) return str[pos .. end].dup;
-	else return str[pos .. end].idup;
-}
-
-/**
- * Finds the first occurence of sub in str
- * 
- * Params:
- *     str = the string to find in
- *     sub = the substring to find
- *     start = where to start finding
- *     
- * Returns: the index of the substring or size_t.max when nothing was found
- */
-size_t find (string str, string sub)
-{
-	version (Tango)
-	{
-		size_t index = str.locatePattern(sub);
-		
-		if (index == str.length)
-			return size_t.max;
-		
-		return index;
-	}
-	
-	else
-		return std.string.indexOf(str, sub);
-	
-}
-
-/**
- * Finds the first occurence of sub in str
- * 
- * Params:
- *     str = the string to find in
- *     sub = the substring to find
- *     start = where to start finding
- *     
- * Returns: the index of the substring or size_t.max when nothing was found
- */
-size_t find (wstring str, wstring sub)
-{
-	version (Tango)
-	{
-		size_t index = str.locatePattern(sub);
-		
-		if (index == str.length)
-			return size_t.max;
-		
-		return index;
-	}
-	
-	else
-		return std.string.indexOf(str, sub);
-}
-
-/**
- * Finds the first occurence of sub in str
- * 
- * Params:
- *     str = the string to find in
- *     sub = the substring to find
- *     start = where to start finding
- *     
- * Returns: the index of the substring or size_t.max when nothing was found
- */
-size_t find (dstring str, dstring sub)
-{
-	version (Tango)
-	{
-		size_t index = str.locatePattern(sub);
-		
-		if (index == str.length)
-			return size_t.max;
-		
-		return index;
-	}
-	
-	else
-		return std.string.indexOf(str, sub);
-}
-
-/**
- * Compares to strings, ignoring case differences. Returns 0 if the content
- * matches, less than zero if a is "less" than b, or greater than zero
- * where a is "bigger".
- * 
- * Params:
- *     a = the first array 
- *     b = the second array
- *     end = the index where the comparision will end
- *     
- * Returns: Returns 0 if the content matches, less than zero if a is 
- * 			"less" than b, or greater than zero where a is "bigger".
- * 
- * See_Also: mambo.collection.array.compare
- */
-int compareIgnoreCase (U = size_t) (string a, string b, U end = U.max)
-{
-	return a.toFold().compare(b.toFold(), end);
-}
-
-/**
- * Compares to strings, ignoring case differences. Returns 0 if the content
- * matches, less than zero if a is "less" than b, or greater than zero
- * where a is "bigger".
- * 
- * Params:
- *     a = the first array 
- *     b = the second array
- *     end = the index where the comparision will end
- *     
- * Returns: Returns 0 if the content matches, less than zero if a is 
- * 			"less" than b, or greater than zero where a is "bigger".
- * 
- * See_Also: mambo.collection.array.compare
- */
-int compareIgnoreCase (U = size_t) (wstring a, wstring b, U end = U.max)
-{
-	return a.toFold().compare(b.toFold(), end);
-}
-
-/**
- * Compares to strings, ignoring case differences. Returns 0 if the content
- * matches, less than zero if a is "less" than b, or greater than zero
- * where a is "bigger".
- * 
- * Params:
- *     a = the first array 
- *     b = the second array
- *     end = the index where the comparision will end
- *     
- * Returns: Returns 0 if the content matches, less than zero if a is 
- * 			"less" than b, or greater than zero where a is "bigger".
- * 
- * See_Also: mambo.collection.array.compare
- */
-int compareIgnoreCase (U = size_t) (dstring a, dstring b, U end = U.max)
-{
-	return a.toFold().compare(b.toFold(), end);
-}
-
-/**
- * Compares to strings, ignoring case differences. Returns 0 if the content
- * matches, less than zero if a is "less" than b, or greater than zero
- * where a is "bigger".
- * 
- * Params:
- *     a = the first array 
- *     b = the second array
- *     end = the index where the comparision will end
- *     
- * Returns: Returns 0 if the content matches, less than zero if a is 
- * 			"less" than b, or greater than zero where a is "bigger".
- * 
- * See_Also: mambo.string.compareIgnoreCase
- */
-alias compareIgnoreCase icompare;
-
-/**
- * Checks if the given character is a hexdecimal digit character.
- * Hexadecimal digits are any of: 0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F
- * 
- * Params:
- *     ch = the character to be checked
- *     
- * Returns: true if the given character is a hexdecimal digit character otherwise false
- */
-bool isHexDigit (dchar ch)
-{
-	version (Tango)
-	{
-		switch (ch)
-		{
-			case 'A': return true;				
-			case 'B': return true;
-			case 'C': return true;
-			case 'D': return true;
-			case 'E': return true;
-			case 'F': return true;
-			
-			case 'a': return true;
-			case 'b': return true;
-			case 'c': return true;
-			case 'd': return true;
-			case 'e': return true;
-			case 'f': return true;
-			
-			default: break;
-		}
-		
-		if (isDigit(ch))
-			return true;
-	}
-
-	else
-		if (isxdigit(ch) != 0)
-			return true;
-		
-	return false;
-}
-
-/*version (Tango)
-{
-	string toString (string str)
-	{
-		return str;
-	}
-	
-	string toString (wstring str)
-	{
-		return tango.text.convert.Utf.toString(str);
-	}
-	
-	string toString (dstring str)
-	{
-		return tango.text.convert.Utf.toString(str);
-	}
-}*/
-
-version (Phobos)
-{	
-	/**
-	 * Converts the given string to C-style 0 terminated string.
-	 * 
-	 * Params:
-	 *     str = the string to convert
-	 *     
-	 * Returns: the a C-style 0 terminated string.
-	 */
-	dchar* toString32z (dstring str)
-	{
-		return (str ~ '\0').dup.ptr;
-	}
-	
-	/**
-	 * Converts a C-style 0 terminated string to a wstring
-	 * 
-	 * Params:
-	 *     str = the C-style 0 terminated string
-	 *     
-	 * Returns: the converted wstring
-	 */
-	wstring fromString16z (wchar* str)
-	{
-		return str[0 .. strlen(str)].idup;
-	}
-	
-	/**
-	 * Converts a C-style 0 terminated string to a dstring
-	 * Params:
-	 *     str = the C-style 0 terminated string
-	 *     
-	 * Returns: the converted dstring
-	 */
-	dstring fromString32z (dchar* str)
-	{
-		return str[0 .. strlen(str)].idup;
-	}
-	
-	/**
-	 * Gets the length of the given C-style 0 terminated string
-	 * 
-	 * Params:
-	 *     str = the C-style 0 terminated string to get the length of
-	 *     
-	 * Returns: the length of the string
-	 */
-	size_t strlen (wchar* str)
-	{
-		size_t i = 0;
-		
-		if (str)
-			while(*str++)
-				++i;
-		
-		return i;
-	}
-	
-	/**
-	 * Gets the length of the given C-style 0 terminated string
-	 * 
-	 * Params:
-	 *     str = the C-style 0 terminated string to get the length of
-	 *     
-	 * Returns: the length of the string
-	 */
-	size_t strlen (dchar* str)
-	{
-		size_t i = 0;
-		
-		if (str)
-			while(*str++)
-				++i;
-		
-		return i;
-	}
-}
\ No newline at end of file
--- a/orange/xml/XMLDocument.d	Wed Oct 06 16:18:02 2010 +0200
+++ b/orange/xml/XMLDocument.d	Tue Oct 19 10:22:10 2010 +0200
@@ -12,7 +12,7 @@
 	import tango.text.xml.Document;
 	import tango.io.Stdout;
 	
-	import orange.util.string;
+	import orange.core.string;
 }
 
 else
@@ -25,7 +25,7 @@
 	version = Phobos;
 }
 
-import orange.util.io;
+import orange.core.io;
 	
 template Char (T)
 {