comparison trunk/ddata.d @ 3:8e3ddf7a3178

moving
author Saaa
date Wed, 07 Oct 2009 14:02:25 +0200
parents
children
comparison
equal deleted inserted replaced
2:ee1232043257 3:8e3ddf7a3178
1 module ddata.ddata;
2
3 //debug
4 //import std.stdio;
5 import std.string;
6
7 import std2.conv : to;
8 import std2.traits : isNumeric;
9
10 class DDataException : Exception
11 {
12 this(char[] msg)
13 {
14 super(msg);
15 }
16 this( uint loc, char c, char[] msg)
17 {
18 super( format( `parsing failed at string[`, loc-1, `] = '`,c,`'` ,msg));
19 }
20 }
21
22
23 private enum TOKEN{ BOF, SQUARE_L, SQUARE_R, COMMA, ECOMMA, VALUE, EOF}
24
25 private template Depth(T: T[]) { const Depth = 1 + Depth!(T); }
26 private template Depth(T) { const Depth = 0; }
27
28 private template BaseType(T: T[]) { alias BaseType!(T) BaseType; }
29 private template BaseType(T) { alias T BaseType; }
30
31 private template indexAssign(T: T[])
32 {
33 void indexAssign(ref T array, BaseType!(T) value, int[] indices)
34 {
35 static if( is( typeof(array[0]) == typeof(value)))
36 {
37 array[indices[0]] = value;
38 }
39 else
40 {
41 indexAssign!(T)( array[indices[0]], value, indices[1..$]);
42 }
43 }
44 }
45
46 private string ctToString(int i)
47 {
48 if (!i) return "0";
49 string res;
50 while (i) {
51 res = "0123456789"[i%10] ~ res;
52 i /= 10;
53 }
54 return res;
55 }
56
57 private string indexString(int len)
58 {
59 string res;
60 for (int i = 0; i < len; ++i)
61 res ~= "[index["~ctToString(i)~"]] ";
62 return res;
63 }
64
65 private string casesString(int depth, TOKEN type)
66 {
67 string res;
68 res ~= `switch( depth ){`;
69
70 for (int i = 0; i < depth; ++i)
71 {
72 switch(type)
73 {
74 case TOKEN.COMMA:
75 res ~=`case `~ctToString(i)~`:`~
76 `if(temp`~ indexString(i) ~`.length<=index[`~ctToString(i)~`] )temp`~ indexString(i) ~`.length=temp`~ indexString(i) ~`.length*2;`~
77 `break;`;
78 break;
79
80 case TOKEN.SQUARE_L:
81 res ~=`case `~ctToString(i)~`:`~
82 `temp`~ indexString(i) ~`.length=4;`~
83 `break;`;
84 break;
85
86 case TOKEN.SQUARE_R:
87 res ~=`case `~ctToString(i)~`:`~
88 `temp`~ indexString(i) ~`.length=index[`~ctToString(i)~`];`~
89 `break;`;
90 break;
91
92 default:
93 assert(false);
94 break;
95 }
96 }
97
98 res ~= `default:assert(false);break;}`;
99 return res;
100 }
101
102
103 bool toBool(char[] s)
104 {
105 if(s == `true`)
106 {
107 return true;
108 }
109 else if(s == `false`)
110 {
111 return false;
112 }
113 else
114 {
115 throw new Exception(`Cannot convert "`~s~`" to bool`);
116 }
117 return false;
118 }
119
120 public T toArray(T:D[],D)(char[] string)
121 {
122 int[ Depth!(T) ] index = 0;
123
124 T temp;
125 char c;
126
127 int depth = -1;
128
129 int sLoc1 = -1, sLoc2 = -1;
130 int loc = -1;
131
132 TOKEN last = TOKEN.BOF;
133
134 while(true)
135 {
136 loc++;
137 //debug
138 //writefln(loc);
139 if( loc >= string.length )
140 {
141 if( last != TOKEN.SQUARE_R) throw new DDataException( `unexpected end`);
142 if( depth != -1 ) throw new DDataException( `array depth not zero after parsing `);
143 //throw new DDataException(`EOF before end of parsing`);
144 return temp;
145 }
146
147 c = string[loc];
148 //debug
149 //writefln(c);
150 switch(c)
151 {
152 case ' ', '\t', '\v', '\r', '\n', '\f':
153 if( last == TOKEN.ECOMMA || last == TOKEN.SQUARE_L)
154 {
155 if(sLoc2 < 0)
156 {
157 sLoc1 = loc + 1;
158 }else{
159 sLoc2 = loc;
160 last = TOKEN.VALUE;
161 }
162 }
163 break;
164
165 case ',':
166 index[depth] ++;
167
168 // resize array if necessary
169 mixin ( casesString(Depth!(T), TOKEN.COMMA ) );
170
171 if( last == TOKEN.VALUE && depth == Depth!(T)-1 )
172 {
173 index[depth] --;
174 static if( is(BaseType!(T) == bool) )
175 {
176 indexAssign!(T[])( temp, toBool( string[ sLoc1..sLoc2] ), index);
177 }
178 else static if( isNumeric!( BaseType!(T) ) )
179 {
180 indexAssign!(T[])( temp, to!( BaseType!(T) )( string[ sLoc1..sLoc2] ), index);
181 }
182 else
183 {
184 assert(false);
185 }
186 index[depth] ++;
187 sLoc1 = -1;
188 sLoc2 = -1;
189 last = TOKEN.ECOMMA;
190 }else if( last == TOKEN.SQUARE_R ){
191 last = TOKEN.COMMA;
192 }else{
193 throw new DDataException( loc, c, `: Value, ']' or ',' expected.`);
194 }
195 break;
196
197 case '[':
198 if( last != TOKEN.COMMA && last != TOKEN.BOF && last != TOKEN.SQUARE_L ) throw new DDataException( loc, c, `: Beginning, '[' or ',' expected.`);
199
200 depth++;
201 if(depth > index.length) throw new DDataException( loc, c, `: Array too deep = `~toString(depth));
202 mixin ( casesString(Depth!(T), TOKEN.SQUARE_L ) );
203 index[depth] = 0;
204 last = TOKEN.SQUARE_L;
205 sLoc1 = -1;
206 sLoc2 = -1;
207 break;
208
209 case ']':
210 if( last == TOKEN.VALUE && depth == Depth!(T)-1 && sLoc2 != -1)
211 {
212 static if( is(BaseType!(T) == bool) )
213 {
214 indexAssign!(T[])( temp, toBool( string[ sLoc1..sLoc2]), index);
215 }
216 else static if( isNumeric!( BaseType!(T) ) )
217 {
218 indexAssign!(T[])( temp, to!( BaseType!(T) )(string[ sLoc1..sLoc2]), index);
219 }
220 else
221 {
222 assert(false);
223 }
224 sLoc1 = -1;
225 sLoc2 = -1;
226 index[depth] ++;
227 }
228 else if( last == TOKEN.SQUARE_L )
229 {
230 sLoc1 = -1;
231 sLoc2 = -1;
232 }
233 else if( last == TOKEN.SQUARE_R)
234 {
235 index[depth] ++;
236 }
237 else
238 {
239 throw new DDataException( loc, c, `: Value, '[' or ']' expected.`);
240 }
241
242 // set array length to index[depth]
243 mixin ( casesString(Depth!(T), TOKEN.SQUARE_R) );
244
245 index[depth] = 0;
246 depth--;
247 last = TOKEN.SQUARE_R;
248 break;
249
250 default:
251 if( last == TOKEN.ECOMMA || last == TOKEN.SQUARE_L || last == TOKEN.VALUE)
252 {
253 if( sLoc1 < 0 )
254 {
255 sLoc1 = loc;
256 sLoc2 = loc +1;
257 } else {
258 sLoc2 = loc +1;
259 }
260 last = TOKEN.VALUE;
261 break;
262 }
263 throw new DDataException( loc, c, `: Out of place char found `);
264 break;
265 }
266 }
267 }
268
269 unittest
270 {
271 writefln("DData UnitTest...");
272
273 int[][][] ia = [ [[1,2],[3,4],[5]] , [[6],[],[7,8,9]] , [[]] ];
274
275 char[] s = to!(char[])(ia);
276 int[][][] ia2;
277
278 ia2 = toArray!(typeof(ia2))(s);
279 assert( ia == ia2);
280
281 writefln("Done!");
282 }
283