# HG changeset patch # User Jacob Carlborg # Date 1287476530 -7200 # Node ID 78e5fef4bbf2ce72ad86dd9b674dc97af407d4dc # Parent b51e953f79eb882ec89363b72e6f855bc28eb1bc Third step in refactoring the API. Stating to add unit tests. diff -r b51e953f79eb -r 78e5fef4bbf2 dsss.conf --- 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 diff -r b51e953f79eb -r 78e5fef4bbf2 orange/core/_.d --- /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 diff -r b51e953f79eb -r 78e5fef4bbf2 orange/core/io.d --- /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 diff -r b51e953f79eb -r 78e5fef4bbf2 orange/core/string.d --- /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 diff -r b51e953f79eb -r 78e5fef4bbf2 orange/serialization/RegisterWrapper.d --- 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); diff -r b51e953f79eb -r 78e5fef4bbf2 orange/serialization/SerializationException.d --- 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; diff -r b51e953f79eb -r 78e5fef4bbf2 orange/serialization/Serializer Binary file orange/serialization/Serializer has changed diff -r b51e953f79eb -r 78e5fef4bbf2 orange/serialization/Serializer.d --- 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 = ` + + + + +`; + + serializer.serialize(B()); + assert(archive.data == data); + } + + void serializeStruct () + { + serializer.reset; + data = ` + + + + +`; + + serializer.serialize(B()); + assert(archive.data == data); + } + + // Struct + + + + // String + + serializer.reset; + data = ` + + + + foo + + +`; + + 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 = ` + + + + + 27 + 382 + 283 + 3820 + 32 + 832 + + + +`; + + 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 = ` + + + + + + 1 + + + 2 + + + 3 + + + 4 + + + 6 + + + 7 + + + 39 + + + 472 + + + + +`; + + 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 = ` + + + + + 9 + + 9 + + +`; + + 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 = ` + + + + 1 + + +`; + + 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 = ` + + + + 1 + a + b + 0 + 0 + 1 + 1 + 0 + 1 + 1 + 1 + 1 + 1 + c + true + + +`; + + 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 = ` + + + + + 1 + + + +`; + + 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 diff -r b51e953f79eb -r 78e5fef4bbf2 orange/serialization/archives/Archive.d --- 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; diff -r b51e953f79eb -r 78e5fef4bbf2 orange/serialization/archives/ArchiveException.d --- 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 { diff -r b51e953f79eb -r 78e5fef4bbf2 orange/serialization/archives/XMLArchive.d --- 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) diff -r b51e953f79eb -r 78e5fef4bbf2 orange/test/UnitTester.d --- /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 diff -r b51e953f79eb -r 78e5fef4bbf2 orange/util/CTFE.d --- 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...) diff -r b51e953f79eb -r 78e5fef4bbf2 orange/util/Reflection.d --- 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 diff -r b51e953f79eb -r 78e5fef4bbf2 orange/util/Traits.d --- 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) diff -r b51e953f79eb -r 78e5fef4bbf2 orange/util/Use.d --- 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); diff -r b51e953f79eb -r 78e5fef4bbf2 orange/util/_.d --- 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 diff -r b51e953f79eb -r 78e5fef4bbf2 orange/util/io.d --- 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 diff -r b51e953f79eb -r 78e5fef4bbf2 orange/util/string.d --- 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 diff -r b51e953f79eb -r 78e5fef4bbf2 orange/xml/XMLDocument.d --- 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) {