Mercurial > projects > mde
view mde/mergetag/defaultdata.d @ 9:1885a9080f2a
Joystick button input now works with config.
committer: Diggory Hardy <diggory.hardy@gmail.com>
author | Diggory Hardy <diggory.hardy@gmail.com> |
---|---|
date | Wed, 30 Jan 2008 11:33:56 +0000 |
parents | |
children | 4c3575400769 |
line wrap: on
line source
/// This module contains the DefaultData class, and some notes possibly useful for implementing /// other types of DataSection. module mde.mergetag.defaultdata; public import mde.mergetag.dataset; import mde.text.util; import mde.text.parse : parse; import mde.text.format : format; /** * Default DataSection class. * * Supports all the basic types currently supported and array versions of * each (except no arrays of binary, but arrays of strings are supported). * Doesn't support custom types, but inheriting classes may add support. */ /* Note: I wrote this comment when the code looked rather worse. It's still partially applicable though. * * Due to a failure to use generic programming techniques for most of this (maybe because it's not * possible or maybe just because I don't know how to use templates properly) a lot of this code is * really horrible and has to refer to EVERY data member. * Be really careful if you add any items to this class. * * I really don't like having to do things like this, but it provides a lot of benefits such as no * need to store types and no need to check an argument's type for every access (this could be done * by throwing errors, but then an incorrect (perhaps hand-edited) data file could cause a lot of * errors to be thrown). */ class DefaultData : DataSection { //BEGIN DATA /** Data Members * * These names are available for direct access. * * An alternative access method is to use the provided templates: * -------------------- * template Arg(T) { * alias Name Arg; * } * -------------------- * * Use with a mixin or directly: * -------------------- * mixin Arg!(type); * auto x = Arg; * * type y = Arg!(type).Arg; * -------------------- * Note: trying to use Arg!(type) to implicitly refer to Arg!(type).Arg causes compiler errors due to * --- alias Name Arg; --- * actually being a mixin. */ bool [ID] _bool; byte [ID] _byte; /// ditto short [ID] _short; /// ditto int [ID] _int; /// ditto long [ID] _long; /// ditto ubyte [ID] _ubyte; /// ditto ushort [ID] _ushort; /// ditto uint [ID] _uint; /// ditto ulong [ID] _ulong; /// ditto char [ID] _char; /// ditto float [ID] _float; /// ditto double [ID] _double; /// ditto real [ID] _real; /// ditto bool[] [ID] _boolA; /// ditto byte[] [ID] _byteA; /// ditto short[] [ID] _shortA; /// ditto int[] [ID] _intA; /// ditto long[] [ID] _longA; /// ditto ubyte[] [ID] _ubyteA; /// ditto ushort[] [ID] _ushortA; /// ditto uint[] [ID] _uintA; /// ditto ulong[] [ID] _ulongA; /// ditto char[] [ID] _charA; /// ditto float[] [ID] _floatA; /// ditto double[] [ID] _doubleA; /// ditto real[] [ID] _realA; /// ditto char[][] [ID] _charAA; /// ditto /** Alias names */ alias _ubyteA _binary; alias _charA _string; /// ditto alias _charAA _stringA; /// ditto //END DATA void addTag (char[] tp, ID id, char[] dt) { /// Supports all standard types. if (tp.length == 0) throw new MTUnknownTypeException; // split list up a bit for performance: if (tp[0] < 'l') { if (tp[0] < 'd') { mixin ( `if (tp == "binary") addTag_add!(ubyte[]) (id, dt);` ~ addTag_elifIsType_add!(bool) ~ addTag_elifIsType_add!(bool[]) ~ addTag_elifIsType_add!(byte) ~ addTag_elifIsType_add!(byte[]) ~ addTag_elifIsType_add!(char) ~ addTag_elifIsType_add!(char[]) ~ addTag_elifIsType_add!(char[][]) ~ `else throw new MTUnknownTypeException;` ); } else { mixin ( `if (tp == "double") addTag_add!(double) (id, dt);` ~ addTag_elifIsType_add!(double[]) ~ addTag_elifIsType_add!(float) ~ addTag_elifIsType_add!(float[]) ~ addTag_elifIsType_add!(int) ~ addTag_elifIsType_add!(int[]) ~ `else throw new MTUnknownTypeException;` ); } } else { if (tp[0] < 'u') { mixin ( `if (tp == "long") addTag_add!(long) (id, dt);` ~ addTag_elifIsType_add!(long[]) ~ addTag_elifIsType_add!(real) ~ addTag_elifIsType_add!(real[]) ~ addTag_elifIsType_add!(short) ~ addTag_elifIsType_add!(short[]) ~ `else if (tp == "string") addTag_add!(char[]) (id, dt);` ~ `else throw new MTUnknownTypeException;` ); } else { mixin ( `if (tp == "ubyte") addTag_add!(ubyte) (id, dt);` ~ addTag_elifIsType_add!(ubyte[]) ~ addTag_elifIsType_add!(ushort) ~ addTag_elifIsType_add!(ushort[]) ~ addTag_elifIsType_add!(uint) ~ addTag_elifIsType_add!(uint[]) ~ addTag_elifIsType_add!(ulong) ~ addTag_elifIsType_add!(ulong[]) ~ `else throw new MTUnknownTypeException;` ); } } // try-catch block removed (caught by read) } private template addTag_elifIsType_add(T) { const addTag_elifIsType_add = `else if (tp == "`~T.stringof~`")` `addTag_add!(`~T.stringof~`) (id, dt);` ; } private void addTag_add(T) (ID id, char[] dt) { Arg!(T).Arg[id] = parse!(T) (dt); } void writeAll (ItemDelg itemdlg) { foreach (id, dt; _charA) itemdlg ("char[]", id, format!(char[])(dt)); } /* These make no attempt to check Arg is valid. * But if the symbol doesn't exist the complier will throw an error anyway, e.g.: * Error: identifier '_boolAA' is not defined */ template Arg(T : T[]) { const ArgString = Arg!(T).ArgString ~ `A`; mixin(`alias `~ArgString~` Arg;`); } template Arg(T) { const ArgString = `_` ~ T.stringof; mixin(`alias `~ArgString~` Arg;`); } } /+class DynamicData : DataSection { void*[TypeInfo] data; }+/ /+ class TemplateData : DataSection { void addTag (char[] tp, ID id, char[] dt) { // runtime deduction of tp and aliasing? // CANNOT add data at runtime though. } // will this work? no idea. // templates can't be used to add non-static elements, so use a static array at index: this template Data(T,TemplateData* p) { static T[ID][TemplateData*] Data; } } +/