# HG changeset patch # User Saaa # Date 1252538202 -7200 # Node ID 277bc71a8eaa45d3bf69f106ffe7a7185e7eecce First Post!! diff -r 000000000000 -r 277bc71a8eaa ddata.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ddata.d Thu Sep 10 01:16:42 2009 +0200 @@ -0,0 +1,280 @@ +module ddata.ddata; + +import std.stdio; +import std.string; + +import std2.conv; + +class DDataException : Exception +{ + this(char[] msg) + { + super(msg); + } + this( uint loc, char c, char[] msg) + { + super( format( `parsing failed at string[`, loc-1, `] = '`,c,`'` ,msg)); + } +} + + +private enum TOKEN{ BOF, SQUARE_L, SQUARE_R, COMMA, ECOMMA, VALUE, EOF} + +private template Depth(T: T[]) { const Depth = 1 + Depth!(T); } +private template Depth(T) { const Depth = 0; } + +private template BaseType(T: T[]) { alias BaseType!(T) BaseType; } +private template BaseType(T) { alias T BaseType; } + +private template indexAssign(T: T[]) +{ + void indexAssign(ref T array, BaseType!(T) value, int[] indices) + { + static if( is( typeof(array[0]) == typeof(value))) + { + array[indices[0]] = value; + } + else + { + indexAssign!(T)( array[indices[0]], value, indices[1..$]); + } + } +} + +private string ctToString(int i) +{ + if (!i) return "0"; + string res; + while (i) { + res = "0123456789"[i%10] ~ res; + i /= 10; + } + return res; +} + +private string indexString(int len) +{ + string res; + for (int i = 0; i < len; ++i) + res ~= "[index["~ctToString(i)~"]] "; + return res; +} + +private string casesString(int depth, TOKEN type) +{ + string res; + res ~= `switch( depth ){`; + + for (int i = 0; i < depth; ++i) + { + switch(type) + { + case TOKEN.COMMA: + res ~=`case `~ctToString(i)~`:`~ + `if(temp`~ indexString(i) ~`.length= string.length ) + { + if( last != TOKEN.SQUARE_R) throw new DDataException( `unexpected end`); + if( depth != -1 ) throw new DDataException( `array depth not zero after parsing `); + //throw new DDataException(`EOF before end of parsing`); + return temp; + } + + c = string[loc]; + //debug + //writefln(c); + switch(c) + { + case ' ', '\t', '\v', '\r', '\n', '\f': + if( last == TOKEN.ECOMMA || last == TOKEN.SQUARE_L) + { + if(sLoc2 < 0) + { + sLoc1 = loc + 1; + }else{ + sLoc2 = loc; + last = TOKEN.VALUE; + } + } + break; + + case ',': + index[depth] ++; + + // resize array if necessary + mixin ( casesString(Depth!(T), TOKEN.COMMA ) ); + + if( last == TOKEN.VALUE && depth == Depth!(T)-1 ) + { + index[depth] --; + static if( is(BaseType!(T) == bool) ) + { + indexAssign!(T[])( temp, toBool( string[ sLoc1..sLoc2] ), index); + } + else static if( std2.traits.isNumeric!( BaseType!(T) ) ) + { + indexAssign!(T[])( temp, to!( BaseType!(T) )( string[ sLoc1..sLoc2] ), index); + } + else + { + assert(false); + } + index[depth] ++; + sLoc1 = -1; + sLoc2 = -1; + last = TOKEN.ECOMMA; + }else if( last == TOKEN.SQUARE_R ){ + last = TOKEN.COMMA; + }else{ + throw new DDataException( loc, c, `: Value, ']' or ',' expected.`); + } + break; + + case '[': + if( last != TOKEN.COMMA && last != TOKEN.BOF && last != TOKEN.SQUARE_L ) throw new DDataException( loc, c, `: Beginning, '[' or ',' expected.`); + + depth++; + if(depth > index.length) throw new DDataException( loc, c, `: Array too deep = `~toString(depth)); + mixin ( casesString(Depth!(T), TOKEN.SQUARE_L ) ); + index[depth] = 0; + last = TOKEN.SQUARE_L; + sLoc1 = -1; + sLoc2 = -1; + break; + + case ']': + if( last == TOKEN.VALUE && depth == Depth!(T)-1 && sLoc2 != -1) + { + static if( is(BaseType!(T) == bool) ) + { + indexAssign!(T[])( temp, toBool( string[ sLoc1..sLoc2]), index); + } + else static if( std2.traits.isNumeric!( BaseType!(T) ) ) + { + indexAssign!(T[])( temp, to!( BaseType!(T) )(string[ sLoc1..sLoc2]), index); + } + else + { + assert(false); + } + sLoc1 = -1; + sLoc2 = -1; + index[depth] ++; + } + else if( last == TOKEN.SQUARE_L ) + { + sLoc1 = -1; + sLoc2 = -1; + } + else if( last == TOKEN.SQUARE_R) + { + index[depth] ++; + } + else + { + throw new DDataException( loc, c, `: Value, '[' or ']' expected.`); + } + + // set array length to index[depth] + mixin ( casesString(Depth!(T), TOKEN.SQUARE_R) ); + + index[depth] = 0; + depth--; + last = TOKEN.SQUARE_R; + break; + + default: + if( last == TOKEN.ECOMMA || last == TOKEN.SQUARE_L || last == TOKEN.VALUE) + { + if( sLoc1 < 0 ) + { + sLoc1 = loc; + sLoc2 = loc +1; + } else { + sLoc2 = loc +1; + } + last = TOKEN.VALUE; + break; + } + throw new DDataException( loc, c, `: Out of place char found `); + break; + } + } +} + +void unittests() { + writefln("DData UnitTest..."); + + int[][][] ia = [ [[1,2],[3,4],[5]] , [[6],[],[7,8,9]] , [[]] ]; + + char[] s = to!(char[])(ia); + int[][][] ia2; + + ia2 = toArray!(typeof(ia2))(s); + assert( ia == ia2); + + writefln("Done!"); +} +