comparison ddata.d @ 0:277bc71a8eaa

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