Mercurial > projects > ddata
view ddata/ddata.d @ 6:dbdf26e3662b default tip
try again
author | Saaa |
---|---|
date | Wed, 07 Oct 2009 14:41:23 +0200 |
parents | |
children |
line wrap: on
line source
module ddata.ddata; //debug //import std.stdio; import std.string; import std2.conv : to; import std2.traits : isNumeric; 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<=index[`~ctToString(i)~`] )temp`~ indexString(i) ~`.length=temp`~ indexString(i) ~`.length*2;`~ `break;`; break; case TOKEN.SQUARE_L: res ~=`case `~ctToString(i)~`:`~ `temp`~ indexString(i) ~`.length=4;`~ `break;`; break; case TOKEN.SQUARE_R: res ~=`case `~ctToString(i)~`:`~ `temp`~ indexString(i) ~`.length=index[`~ctToString(i)~`];`~ `break;`; break; default: assert(false); break; } } res ~= `default:assert(false);break;}`; return res; } bool toBool(char[] s) { if(s == `true`) { return true; } else if(s == `false`) { return false; } else { throw new Exception(`Cannot convert "`~s~`" to bool`); } return false; } public T toArray(T:D[],D)(char[] string) { int[ Depth!(T) ] index = 0; T temp; char c; int depth = -1; int sLoc1 = -1, sLoc2 = -1; int loc = -1; TOKEN last = TOKEN.BOF; while(true) { loc++; //debug //writefln(loc); if( loc >= 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( 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( 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; } } } unittest { 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!"); }