# HG changeset patch # User Diggory Hardy # Date 1199990004 0 # Node ID dcb24afa0dcee61710de4469f9a1c1c1b3c2b76c # Parent 76d0adc92f2eca9d3d88c142d96d9f60667a2d1d Some fixes from mde/text/format.d unittests plus a few more fixes. committer: Diggory Hardy diff -r 76d0adc92f2e -r dcb24afa0dce mde/init.d --- a/mde/init.d Sun Jan 06 17:47:11 2008 +0000 +++ b/mde/init.d Thu Jan 10 18:33:24 2008 +0000 @@ -129,12 +129,12 @@ * call isn't going to mess things up. The extra function called by runCleanupFcts won't cause * any harm either. */ static bool initialised = false; + static void cleanup () { initialised = false; } static void init () { initialised = true; Init.addCleanupFct (&cleanup); } - static void cleanup () { initialised = false; } init(); assert (initialised); diff -r 76d0adc92f2e -r dcb24afa0dce mde/mergetag/dataset.d --- a/mde/mergetag/dataset.d Sun Jan 06 17:47:11 2008 +0000 +++ b/mde/mergetag/dataset.d Thu Jan 10 18:33:24 2008 +0000 @@ -196,7 +196,6 @@ //END DATA void addTag (char[] tp, ID id, char[] dt) { /// Supports all standard types. - try { if (tp.length == 0) throw new MTUnknownTypeException; // split list up a bit for performance: if (tp[0] < 'l') { @@ -240,9 +239,7 @@ ~ `else throw new MTUnknownTypeException;` ); } } - } catch (TextParseException) { - throw new MTaddTagParseException; - } + // try-catch block removed (caught by read) } private template addTag_elifIsType_add(T) { const addTag_elifIsType_add = diff -r 76d0adc92f2e -r dcb24afa0dce mde/mergetag/read.d --- a/mde/mergetag/read.d Sun Jan 06 17:47:11 2008 +0000 +++ b/mde/mergetag/read.d Thu Jan 10 18:33:24 2008 +0000 @@ -315,13 +315,16 @@ try { dsec.addTag (type, tagID, data); } - catch (MTaddTagParseException) { + catch (TextParseException) { logger.warn("Above error occured" ~ ErrInFile); // following a parse error } catch (MTUnknownTypeException e) { logger.warn ("Unsupported type \"" ~ type ~ "\" " ~ ErrInFile /*~ ":"*/); //logger.warn (e.msg); needless; the above includes enough details. } + catch (Object e) { + logger.error ("Unknown error occured" ~ ErrInFile); + } } else comment = false; // cancel comment status now } else if (fbuf[pos] == '{') { diff -r 76d0adc92f2e -r dcb24afa0dce mde/text/format.d --- a/mde/text/format.d Sun Jan 06 17:47:11 2008 +0000 +++ b/mde/text/format.d Thu Jan 10 18:33:24 2008 +0000 @@ -60,7 +60,7 @@ } unittest { char[] X = format!(char[][char]) (['a':cast(char[])"animal", 'b':['b','u','s']]); - char[] Y = `['a':"animal",'b':["bus"]]`; + char[] Y = `['a':"animal",'b':"bus"]`; assert (X == Y); } @@ -88,9 +88,9 @@ return format (toUtf8 (val)); } char[] format(T : char[]) (T val) { - char[] ret; ret.length = val.length * 2 + 2; // Initial storage. This should ALWAYS be enough. + char[] ret = new char[val.length * 2 + 2]; // Initial storage. This should ALWAYS be enough. ret[0] = '"'; - uint i = 0; + uint i = 1; for (uint t = 0; t < val.length;) { // process a block of non-escapable characters uint s = t; @@ -111,7 +111,7 @@ char[] format(T : ubyte[]) (T val) { static const char[16] digits = "0123456789abcdef"; - char[val.length * 2] ret = void; // exact length + char[] ret = new char[val.length * 2]; // exact length uint i = 0; foreach (ubyte x; val) { ret[i++] = digits[x >> 4]; @@ -120,13 +120,14 @@ return ret; } unittest { - assert (format!(double[]) ([1.0, 1.0e-10]) == `[1,1e-10]`); // generic array stuff + // generic array stuff: + assert (format!(double[]) ([1.0, 1.0e-10]) == `[1.00000000000000000,0.10000000000000000e-09]`); assert (format!(double[]) (cast(double[]) []) == `[]`); // empty array // char[] conversions, with commas, escape sequences and multichar UTF8 characters: assert (format!(char[][]) ([ ".\""[], [',','\''] ,"!\b€" ]) == `[".\"",",\'","!\b€"]`); - assert (format!(ubyte[]) (cast(ubyte[]) [0x01, 0xF2, 0xAC]) == `01F2AC`); // ubyte[] special notation + assert (format!(ubyte[]) (cast(ubyte[]) [0x01, 0xF2, 0xAC]) == `01f2ac`); // ubyte[] special notation } // Support for outputting a wide char... I reccomend against trying to output these though. @@ -143,7 +144,8 @@ // Note: if (val > 127) "is invalid UTF-8 single char" // However we don't know what this is for, in particular if it will be recombined with other chars later - char[4] ret; // max length for an escaped char + // Can't return reference to static array; making dynamic is cheaper than copying. + char[] ret = new char[4]; // max length for an escaped char ret[0] = '\''; if (!isEscapableChar (val)) { @@ -159,7 +161,7 @@ assert (false); } unittest { - assert (format!(char) ('\'') == '\''); + assert (format!(char) ('\'') == "\'\\\'\'"); } char[] format(T : bool) (T val) { @@ -194,28 +196,30 @@ return formatLong (val); } unittest { - assert (format!(byte) (cast(byte) -5)) == "-5"; + assert (format!(byte) (cast(byte) -5) == "-5"); // annoyingly, octal syntax differs from D (blame tango): - assert (format!(uint[]) ([0b0100u,0724,0xFa59c,0xFFFFFFFF,0]) == "[0b100,0o724,0xFa59c,0xFFFFFFFF,0]"); + assert (format!(uint[]) ([0b0100u,0724,0xFa59c,0xFFFFFFFF,0]) == "[4,468,1025436,4294967295,0]"); } +// Old calculation (not used): +// t.dig+2+4+3 // should be sufficient length (mant + (neg, dot, e, exp neg) + exp (3,4,5 for float,double,real resp.)) char[] format(T : float) (T val) { - // t.dig+2+4+3 // should be sufficient length (mant + (neg, dot, e, exp neg) + exp (3,4,5 for float,double,real resp.)) - char[32] ret; // minimum allowed by assert in format - return cFloat.format (ret, val, T.dig+2, true); // from old C++ tests, T.dig+2 gives best(?) accuracy + char[] ret = new char[32]; // minimum allowed by assert in format + return cFloat.format (ret, val, T.dig+2, 1); // from old C++ tests, T.dig+2 gives best(?) accuracy } char[] format(T : double) (T val) { - char[32] ret; - return cFloat.format (ret, val, T.dig+2, true); + char[] ret = new char[32]; + return cFloat.format (ret, val, T.dig+2, 1); } char[] format(T : real) (T val) { - char[32] ret; - return cFloat.format (ret, val, T.dig+2, true); + char[] ret = new char[32]; + return cFloat.format (ret, val, T.dig+2, 1); } unittest { - assert (format!(float) (0.0f) == "0"); - assert (format!(double) (-1e25) == "-1e25"); - assert (format!(real) (cast(real) 5.24e-269) == "5.24e-269"); + // NOTE: these numbers are not particularly meaningful. + assert (format!(float) (0.0f) == "0.00000000"); + assert (format!(double) (-1e25) == "-1.00000000000000000e+25"); + assert (format!(real) (cast(real) 4.918e300) == "4.91800000000000000000e+300"); } //END Convert templates @@ -231,7 +235,7 @@ //BEGIN Utility funcs private char[] formatLong (long val) { - try return cInt.toString (val, cInt.Style.Unsigned, cInt.Flags.Throw); + try return cInt.toString (val, cInt.Style.Signed, cInt.Flags.Throw); catch (Exception e) throwException (e.msg); } private bool isEscapableChar (char c) { diff -r 76d0adc92f2e -r dcb24afa0dce mde/text/parse.d --- a/mde/text/parse.d Sun Jan 06 17:47:11 2008 +0000 +++ b/mde/text/parse.d Thu Jan 10 18:33:24 2008 +0000 @@ -42,10 +42,11 @@ //BEGIN parse templates // Associative arrays +const char[] AA_ERR = "Invalid associative array: "; T[S] parse(T : T[S], S) (char[] src) { src = Util.trim(src); if (src.length < 2 || src[0] != '[' || src[$-1] != ']') - throwException ("Invalid associative array: not [a:x, ..., c:z]"); + throwException (AA_ERR ~ "not [ ... ]"); // bad braces. T[S] ret; foreach (char[] pair; split (src[1..$-1])) { @@ -56,17 +57,22 @@ if (c == '\'' || c == '"') { // string or character ++i; while (i < pair.length && pair[i] != c) { - if (pair[i] == '\\') ++i; // escape seq. + if (pair[i] == '\\') { + if (i+2 >= pair.length) throwException (AA_ERR ~ "unfinished escape sequence within string/char"); + ++i; // escape seq. + } ++i; - } // Doesn't throw if no terminal quote at end of pair (in this case an error is thrown anyway) + } + if (i == pair.length) { + debug logger.warn ("Pair is: " ~ pair); + throwException (AA_ERR ~ "encountered [ ... KEY] (missing :DATA)"); + } } ++i; } if (i == pair.length) { - debug logger.trace ("In pair: " ~ pair); - throwException ("Invalid key:value pair in associative array literal"); + throwException (AA_ERR ~ "encountered [ ... KEY:] (missing DATA)"); } - debug logger.trace ("pair is: " ~ pair[0..i] ~ " : " ~ pair[i+1..$]); ret[parse!(S) (pair[0..i])] = parse!(T) (pair[i+1..$]); } return ret; @@ -108,7 +114,7 @@ // process a block of escaped characters while (t < src.length && src[t] == '\\') { t++; - if (t == src.length) throwException (`Warning: string ends \" !`); // next char is " + if (t == src.length) throwException ("Invalid string: ends \\\" !"); // next char is " ret[i++] = replaceEscapedChar (src[t++]); // throws if it's invalid } }