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;
}
}
+/