Mercurial > projects > ddata
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 |