Mercurial > projects > mde
comparison mde/mergetag/dataset.d @ 2:78eb491bd642
mergetag: partially redesigned dataset and text reader classes. Changed text format.
committer: Diggory Hardy <diggory.hardy@gmail.com>
author | Diggory Hardy <diggory.hardy@gmail.com> |
---|---|
date | Sat, 03 Nov 2007 15:15:43 +0000 |
parents | 18491334a525 |
children | 9a990644948c |
comparison
equal
deleted
inserted
replaced
1:18491334a525 | 2:78eb491bd642 |
---|---|
1 /// This module contains a minimal definition of a MergeTag DataSet. | 1 /// This module contains a minimal definition of a MergeTag DataSet. |
2 module mde.mergetag.dataset; | 2 module mde.mergetag.dataset; |
3 | 3 |
4 // package imports | 4 // package imports |
5 import mde.mergetag.parse; | |
6 import mde.mergetag.exception; | 5 import mde.mergetag.exception; |
6 | |
7 // other mde imports | |
8 import mde.text.util; | |
9 import mde.text.parse; | |
10 import mde.text.exception : TextParseException; | |
7 | 11 |
8 // tango imports | 12 // tango imports |
9 import Util = tango.text.Util; | 13 import Util = tango.text.Util; |
10 import tango.util.log.Log : Log, Logger; | 14 import tango.util.log.Log : Log, Logger; |
11 | 15 |
31 } | 35 } |
32 | 36 |
33 private Logger logger; | 37 private Logger logger; |
34 static this () { | 38 static this () { |
35 logger = Log.getLogger ("mde.mergetag.dataset"); | 39 logger = Log.getLogger ("mde.mergetag.dataset"); |
40 } | |
41 | |
42 struct TextTag { | |
43 TextTag opCall (char[] _tp, ID _id, char[] _dt) { | |
44 TextTag ret; | |
45 ret.tp = _tp; | |
46 ret.id = _id; | |
47 ret.dt = _dt; | |
48 return ret; | |
49 } | |
50 char[] tp, dt; | |
51 ID id; | |
36 } | 52 } |
37 | 53 |
38 /************************************************************************************************** | 54 /************************************************************************************************** |
39 * Data class; contains a DataSection class instance for each loaded section of a file. | 55 * Data class; contains a DataSection class instance for each loaded section of a file. |
40 * | 56 * |
78 * format except for user-defined types. | 94 * format except for user-defined types. |
79 * | 95 * |
80 * Another idea for a DataSection class: | 96 * Another idea for a DataSection class: |
81 * Use a void*[ID] variable to store all data (may also need a type var for each item). | 97 * Use a void*[ID] variable to store all data (may also need a type var for each item). |
82 * addTag should call a templated function which calls parse then casts to a void* and stores the data. | 98 * addTag should call a templated function which calls parse then casts to a void* and stores the data. |
83 * Use a templated get(T)(ID) method which checks the type and casts to T. Small issue with this: storing | 99 * Use a templated get(T)(ID) method which checks the type and casts to T. |
84 * data in the file with an incorrect type could cause a lot of errors to be thrown in other code. | |
85 */ | 100 */ |
86 interface DataSection | 101 interface DataSection |
87 { | 102 { |
88 /** Handles parsing of data items. | 103 /** Handles parsing of data items. |
89 * | 104 * |
90 * Should throw an MTUnknownTypeException for unsupported types, after logging to logger. | 105 * Should throw an MTUnknownTypeException for unsupported types, after logging to logger. |
91 */ | 106 */ |
92 void addTag (char[],ID,char[]); | 107 void addTag (TypeInfo,ID,char[]); |
93 //void writeAll (Print!(char)); /// TBD | 108 //void writeAll (Print!(char)); /// TBD |
94 } | 109 } |
95 | 110 |
96 /** | 111 /** |
97 * Default DataSection class. | 112 * Default DataSection class. |
98 * | 113 * |
99 * Supports all the basic types currently supported and array versions of | 114 * Supports all the basic types currently supported and array versions of |
100 * each (except no arrays of binary or string types; these are already arrays). | 115 * each (except no arrays of binary or string types; these are already arrays). |
101 */ | 116 */ |
117 /* Due to a failure to use generic programming techniques for most of this (maybe because it's not | |
118 * possible or maybe just because I don't know how to use templates properly) a lot of this code is | |
119 * really horrible and has to refer to EVERY data member. | |
120 * Be really careful if you add any items to this class. | |
121 * | |
122 * I really don't like having to do things like this, but it provides a lot of benefits such as no | |
123 * need to store types and no need to check an argument's type for every access (this could be done | |
124 * by throwing errors, but then an incorrect (perhaps hand-edited) data file could cause a lot of | |
125 * errors to be thrown). | |
126 */ | |
102 class DefaultData : DataSection | 127 class DefaultData : DataSection |
103 { | 128 { |
104 //BEGIN DATA | 129 //BEGIN DATA |
105 /** Data members for direct access. */ | 130 /** Data Members |
106 bool [ID] Bool; | 131 * |
107 byte [ID] Byte; /// ditto | 132 * These names are available for direct access. |
108 short [ID] Short; /// ditto | 133 * |
109 int [ID] Int; /// ditto | 134 * An alternative access method is to use the provided templates: |
110 long [ID] Long; /// ditto | 135 * -------------------- |
111 ubyte [ID] UByte; /// ditto | 136 * template Arg(T) { |
112 ushort [ID] UShort; /// ditto | 137 * alias Name Arg; |
113 uint [ID] UInt; /// ditto | 138 * } |
114 ulong [ID] ULong; /// ditto | 139 * -------------------- |
115 | 140 * |
116 bool[] [ID] BoolA; /// ditto | 141 * Use with a mixin or directly: |
117 byte[] [ID] ByteA; /// ditto | 142 * -------------------- |
118 short[] [ID] ShortA; /// ditto | 143 * mixin Arg!(type); |
119 int[] [ID] IntA; /// ditto | 144 * auto x = Arg; |
120 long[] [ID] LongA; /// ditto | 145 * |
121 ubyte[] [ID] UByteA; /// ditto | 146 * type y = Arg!(type).Arg; |
122 ushort[] [ID] UShortA;/// ditto | 147 * -------------------- |
123 uint[] [ID] UIntA; /// ditto | 148 * Note: trying to use Arg!(type) to implicitly refer to Arg!(type).Arg causes compiler errors due to |
124 ulong[] [ID] ULongA; /// ditto | 149 * --- alias Name Arg; --- |
125 | 150 * actually being a mixin. |
126 float [ID] Float; /// ditto | 151 */ |
127 double [ID] Double; /// ditto | 152 |
128 real [ID] Real; /// ditto | 153 bool [ID] _bool; |
129 float[] [ID] FloatA; /// ditto | 154 byte [ID] _byte; /// ditto |
130 double[] [ID] DoubleA;/// ditto | 155 short [ID] _short; /// ditto |
131 real[] [ID] RealA; /// ditto | 156 int [ID] _int; /// ditto |
132 | 157 long [ID] _long; /// ditto |
133 char [ID] Char; /// ditto | 158 ubyte [ID] _ubyte; /// ditto |
134 char[] [ID] CharA; /// ditto | 159 ushort [ID] _ushort; /// ditto |
160 uint [ID] _uint; /// ditto | |
161 ulong [ID] _ulong; /// ditto | |
162 | |
163 char [ID] _char; /// ditto | |
164 | |
165 float [ID] _float; /// ditto | |
166 double [ID] _double; /// ditto | |
167 real [ID] _real; /// ditto | |
168 | |
169 bool[] [ID] _boolA; /// ditto | |
170 byte[] [ID] _byteA; /// ditto | |
171 short[] [ID] _shortA; /// ditto | |
172 int[] [ID] _intA; /// ditto | |
173 long[] [ID] _longA; /// ditto | |
174 ubyte[] [ID] _ubyteA; /// ditto | |
175 ushort[] [ID] _ushortA; /// ditto | |
176 uint[] [ID] _uintA; /// ditto | |
177 ulong[] [ID] _ulongA; /// ditto | |
178 | |
179 char[] [ID] _charA; /// ditto | |
180 | |
181 float[] [ID] _floatA; /// ditto | |
182 double[] [ID] _doubleA; /// ditto | |
183 real[] [ID] _realA; /// ditto | |
135 | 184 |
136 /** Alias names */ | 185 /** Alias names */ |
137 alias CharA String; | 186 alias _ubyteA _binary; |
138 alias UByteA Binary; /// ditto | 187 alias _charA _string; /// ditto |
139 //END DATA | 188 //END DATA |
140 | 189 |
141 /+ Could use this: | 190 void addTag (TypeInfo ti, ID id, char[] dt) { /// for adding tags |
142 private template addTagTp(alias Var, T) (ID id, char[] dt) { | |
143 Var[id] = parse!(T) (dt); | |
144 } | |
145 or a mixin. | |
146 +/ | |
147 // Unfortunately, I think each case needs to be mentioned explicitly to tie it to the correct | |
148 // data member. | |
149 void addTag (char[] tp, ID id, char[] dt) { /// for adding tags | |
150 try { | 191 try { |
151 postTrim (tp); | 192 // crazy way of only writing one parameter on each line: |
152 // parse tp, then use if statements to replace the following switch | 193 mixin ( `if (ti == typeid(bool)) addTag_add!(bool) (id, dt);` |
153 | 194 ~ addTag_elifIsType_add!(byte) |
154 switch(Util.trim(tp)) { | 195 ~ addTag_elifIsType_add!(short) |
155 case "1": | 196 ~ addTag_elifIsType_add!(int) |
156 case "bool": | 197 ~ addTag_elifIsType_add!(long) |
157 Arg!(bool)[id] = parse!(bool) (dt); | 198 ~ addTag_elifIsType_add!(ubyte) |
158 break; | 199 ~ addTag_elifIsType_add!(ushort) |
159 case "s8": | 200 ~ addTag_elifIsType_add!(uint) |
160 case "byte": | 201 ~ addTag_elifIsType_add!(ulong) |
161 addTagTp!(byte) (id, dt); | 202 ~ addTag_elifIsType_add!(char) |
162 break; | 203 ~ addTag_elifIsType_add!(float) |
163 case "s16": | 204 ~ addTag_elifIsType_add!(double) |
164 case "short": | 205 ~ addTag_elifIsType_add!(real) |
165 Short[id] = parse!(short) (dt); | 206 ~ addTag_elifIsType_add!(bool[]) |
166 break; | 207 ~ addTag_elifIsType_add!(byte[]) |
167 case "s32": | 208 ~ addTag_elifIsType_add!(short[]) |
168 case "int": | 209 ~ addTag_elifIsType_add!(int[]) |
169 Arg!(int)[id] = parse!(int) (dt); | 210 ~ addTag_elifIsType_add!(long[]) |
170 break; | 211 ~ addTag_elifIsType_add!(ubyte[]) |
171 case "s64": | 212 ~ addTag_elifIsType_add!(ushort[]) |
172 case "long": | 213 ~ addTag_elifIsType_add!(uint[]) |
173 Long[id] = parse!(long) (dt); | 214 ~ addTag_elifIsType_add!(ulong[]) |
174 break; | 215 ~ addTag_elifIsType_add!(char[]) |
175 case "u8": | 216 ~ addTag_elifIsType_add!(float[]) |
176 case "ubyte": | 217 ~ addTag_elifIsType_add!(double[]) |
177 UByte[id] = parse!(ubyte) (dt); | 218 ~ addTag_elifIsType_add!(real[]) |
178 break; | 219 ); |
179 case "u16": | 220 } catch (TextParseException) { |
180 case "ushort": | 221 // Just ignore it. A warning's already been logged. |
181 UShort[id] = parse!(ushort) (dt); | |
182 break; | |
183 case "u32": | |
184 case "uint": | |
185 UInt[id] = parse!(uint) (dt); | |
186 break; | |
187 case "u64": | |
188 case "ulong": | |
189 ULong[id] = parse!(ulong) (dt); | |
190 break; | |
191 | |
192 case "1[]": | |
193 case "bool[]": | |
194 BoolA[id] = parse!(bool[]) (dt); | |
195 break; | |
196 case "s8[]": | |
197 case "byte[]": | |
198 ByteA[id] = parse!(byte[]) (dt); | |
199 break; | |
200 case "s16[]": | |
201 case "short[]": | |
202 ShortA[id] = parse!(short[]) (dt); | |
203 break; | |
204 case "s32[]": | |
205 case "int[]": | |
206 IntA[id] = parse!(int[]) (dt); | |
207 break; | |
208 case "s64[]": | |
209 case "long[]": | |
210 LongA[id] = parse!(long[]) (dt); | |
211 break; | |
212 case "u8[]": | |
213 case "ubyte[]": | |
214 case "binary": | |
215 UByteA[id] = parse!(ubyte[]) (dt); | |
216 break; | |
217 case "u16[]": | |
218 case "ushort[]": | |
219 UShortA[id] = parse!(ushort[]) (dt); | |
220 break; | |
221 case "u32[]": | |
222 case "uint[]": | |
223 UIntA[id] = parse!(uint[]) (dt); | |
224 break; | |
225 case "u64[]": | |
226 case "ulong[]": | |
227 ULongA[id] = parse!(ulong[]) (dt); | |
228 break; | |
229 | |
230 case "fp32": | |
231 case "float": | |
232 Float[id] = parse!(float) (dt); | |
233 break; | |
234 case "fp64": | |
235 case "double": | |
236 Double[id] = parse!(double) (dt); | |
237 break; | |
238 case "fp": | |
239 case "real": | |
240 Real[id] = parse!(real) (dt); | |
241 break; | |
242 case "fp32[]": | |
243 case "float[]": | |
244 FloatA[id] = parse!(float[]) (dt); | |
245 break; | |
246 case "fp64[]": | |
247 case "double[]": | |
248 DoubleA[id] = parse!(double[]) (dt); | |
249 break; | |
250 case "fp[]": | |
251 case "real[]": | |
252 RealA[id] = parse!(real[]) (dt); | |
253 break; | |
254 | |
255 case "UTF8": | |
256 case "char": | |
257 Char[id] = parse!(char) (dt); | |
258 break; | |
259 case "UTF8[]": | |
260 case "char[]": | |
261 case "string": | |
262 CharA[id] = parse!(char[]) (dt); | |
263 break; | |
264 | |
265 default: | |
266 logger.warn ("Type not supported: " ~ tp); | |
267 throw new MTUnknownTypeException (); | |
268 } | 222 } |
269 } catch (Exception e) { | 223 } |
270 // an error should have already been logged | 224 private template addTag_elifIsType_add(T) { |
271 } | 225 const addTag_elifIsType_add = `else if (ti == typeid(`~T.stringof~`)) addTag_add!(`~T.stringof~`) (id, dt);` ; |
272 } | 226 } |
273 | 227 private void addTag_add(T) (ID id, char[] dt) { |
274 private: | 228 Arg!(T).Arg[id] = parse!(T) (dt); |
275 void addTagTp(T) (ID id, char[] dt) { | 229 } |
276 Arg!(T)[id] = parse!(T) (dt); | 230 |
277 } | 231 void writeTags (out TextTag[] ret) { |
278 | 232 //ret.length = Arg!().length + ...; |
279 // use as: mixin Arg!(type); or Arg!(type) | 233 |
280 template Arg(T : bool) { | 234 |
281 alias Bool Arg; | 235 } |
282 } | 236 |
283 template Arg(T : byte) { | 237 /* These make no attempt to check Arg is valid. |
284 alias Byte Arg; | 238 * But if the symbol doesn't exist the complier will throw an error anyway, e.g.: |
285 } | 239 * Error: identifier '_boolAA' is not defined |
286 template Arg(T : short) { | 240 */ |
287 alias Short Arg; | 241 template Arg(T : T[]) { |
288 } | 242 const ArgString = Arg!(T).ArgString ~ `A`; |
289 template Arg(T : int) { | 243 mixin(`alias `~ArgString~` Arg;`); |
290 alias Int Arg; | 244 } |
291 } | 245 template Arg(T) { |
292 template Arg(T : long) { | 246 const ArgString = `_` ~ T.stringof; |
293 alias Long Arg; | 247 mixin(`alias `~ArgString~` Arg;`); |
294 } | |
295 template Arg(T : ubyte) { | |
296 alias UByte Arg; | |
297 } | |
298 template Arg(T : ushort) { | |
299 alias UShort Arg; | |
300 } | |
301 template Arg(T : uint) { | |
302 alias UInt Arg; | |
303 } | |
304 template Arg(T : ulong) { | |
305 alias ULong Arg; | |
306 } | |
307 template Arg(T : bool[]) { | |
308 alias BoolA Arg; | |
309 } | |
310 template Arg(T : byte[]) { | |
311 alias ByteA Arg; | |
312 } | |
313 template Arg(T : short[]) { | |
314 alias ShortA Arg; | |
315 } | |
316 template Arg(T : int[]) { | |
317 alias IntA Arg; | |
318 } | |
319 template Arg(T : long[]) { | |
320 alias LongA Arg; | |
321 } | |
322 template Arg(T : ubyte[]) { | |
323 alias UByteA Arg; | |
324 } | |
325 template Arg(T : ushort[]) { | |
326 alias UShortA Arg; | |
327 } | |
328 template Arg(T : uint[]) { | |
329 alias UIntA Arg; | |
330 } | |
331 template Arg(T : ulong[]) { | |
332 alias ULongA Arg; | |
333 } | |
334 template Arg(T : float) { | |
335 alias Float Arg; | |
336 } | |
337 template Arg(T : double) { | |
338 alias Double Arg; | |
339 } | |
340 template Arg(T : real) { | |
341 alias Real Arg; | |
342 } | |
343 template Arg(T : float[]) { | |
344 alias FloatA Arg; | |
345 } | |
346 template Arg(T : double[]) { | |
347 alias DoubleA Arg; | |
348 } | |
349 template Arg(T : real[]) { | |
350 alias RealA Arg; | |
351 } | |
352 template Arg(T : char) { | |
353 alias Char Arg; | |
354 } | |
355 template Arg(T : char[]) { | |
356 alias CharA Arg; | |
357 } | 248 } |
358 } | 249 } |
359 | 250 |
360 /+ | 251 /+ |
361 class TemplateData : DataSection | 252 class TemplateData : DataSection |