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