Q: Populating a structure with RTTI

Myron Alexander someone at somewhere.com
Mon Jun 11 09:54:30 PDT 2007


I received the answer in another thread so I have a functional spike.

I just want to thank Chris Nicholson-Sauls, Lutger Blijdestijn, and 
Christian Kam for the help. Without you guys this would not have been 
possible.

I am so excited now and if the concept pans out, I think I may explode :)

Just one last thing, what do you think of the type-safe fetch idea, 
something that will make your lives easier, or just another WTF?

Best Regards,

Myron.

Here is the final spike in full:

> import std.stdio;
> import std.traits;
> import std.conv;
> 
> /* Example value object.
>  */
> struct ValueStruc {
>    char[] name;
>    int    age;
>    char[] addr1;
>    char[] addr2;
>    char[] addr3;
>    double balance;
> }
> 
> struct OtherValue {
>    int     type;
>    char[]  dirname;
>    char[]  filename;
> }
> 
> struct ValueStrucWNull {
>    char[] name;
>    int    age;
>    char[] addr1;
>    char[] addr2;
>    char[] addr3;
>    double balance;
> 
>    bool[6] nullFlag;
> }
> 
> struct OtherValueWNull {
>    int     type;
>    char[]  dirname;
>    char[]  filename;
>    
>    bool[3] nullFlag;
> }
> 
> /* Typesafe database row object.
>  */
> struct Row(T ...) {
>    T              t;
>    bool[T.length] nullFlag;
> }
> 
> char[][] args;
> 
> int getInt (int i) {
>    return toInt (args[i+1]);
> }
> 
> char[] getString (int i) {
>    return args[i+1];
> }
> 
> double getDouble (int i) {
>    return toDouble(args[i+1]);
> }
> 
> // This works
> T getRowElement(T) (uint i) {
>    static if (is (T == int)) {
>       return getInt (i);
>    } else static if (is (T == char[])) {
>       return getString (i);
>    } else static if (is (T == double)) {
>       return getDouble (i);
>    } else {
>       static assert (0);
>    }
> }
> 
> // So do these when the index is uint. If you use void getElem (int i, .....
> // then it fails as it does not know how to differentiate between "int value"
> // and "double value" signatures.
> void getElem (uint i, ref int value) {
>    value = getInt (i);
> }
> 
> void getElem (uint i, ref char[] value) {
>    value = getString (i);
> }
> 
> void getElem (uint i, ref double value) {
>    value = getDouble (i);
> }
> 
> /* Simulate a typesafe fetch from the database.
>  *
>  * With thanks to Chris Nicholson-Sauls, Lutger Blijdestijn, and Christian Kam
>  * who provided code and information on how to make this possible.
>  *
>  * Thanks to Kirk McDonald for for the type-safe fetch idea.
>  */
> Row!(T) fetchone(T ...) () {
>    Row!(T) r;
> 
>    foreach (i, val; r.t) {
>       r.t[i] = getRowElement!(typeof(r.t[i]))(i);
> 
>       // Works too
>       //getElem (i, r.t[i]);
>    }
> 
>    static if (T.length == 6) {
>       //~ r.t[0] = "Myron";
>       //~ r.t[1] = 10;
>       //~ r.t[2] = "addr1";
>       //~ r.t[3] = "addr2";
>       //~ r.t[4] = "addr3";
>       //~ r.t[5] = 100001.10;
>       r.nullFlag[0] = true; 
>       r.nullFlag[1] = false; 
>       r.nullFlag[2] = false; 
>       r.nullFlag[3] = true; 
>       r.nullFlag[4] = false; 
>       r.nullFlag[5] = false; 
>    }
> 
>    static if (T.length == 3) {
>       //~ r.t [0] = 34;
>       //~ r.t [1] = r"c:\dir1\dir2\dir2\";
>       //~ r.t [2] = "filename";
>       r.nullFlag[0] = false; 
>       r.nullFlag[1] = true; 
>       r.nullFlag[2] = false; 
>    }
> 
>    return r;
> }
> 
> /* Fetch a typesafe record from the database and populate the struct.
>  *
>  * With thanks to Chris Nicholson-Sauls, Lutger Blijdestijn, and Christian Kam.
>  */
> T fetchstruc(T) () {
>    
>    static if (is (T == struct)) {
>       auto r = fetchone!(FieldTypeTuple!(T))();
>       T t;
>       foreach (i, v; r.t) {
>          // According to Christian, using v may not work every time.
>          t.tupleof[i] = r.t[i];
>       }
>       return t;
> 
>    } else {
>       static assert (0);
>    }
> }
> 
> /* Fetch a typesafe record from the database, populate the struct and set
>  * null field flags.
>  */
> T fetchnullstruc(T) () {
>    
>    static if (is (T == struct)) {
>       auto r = fetchone!(FieldTypeTuple!(T)[0..length-1])();
>       T t;
>       foreach (i, v; r.t) {
>          // According to Christian, using v may not work every time.
>          t.tupleof[i] = r.t[i];
>       }
>       foreach (i, nullFlagValue; r.nullFlag) {
>          t.nullFlag[i] = nullFlagValue;
>       }
>       return t;
> 
>    } else {
>       static assert (0);
>    }
> }
> 
> 
> void main (char[][] args) {
> 
>    .args = args;
> 
>    auto x = fetchstruc!(ValueStruc) ();
>    writefln ("%s, %s, %s, %s, %s, %#.2f", x.name, x.age, x.addr1, x.addr2, x.addr3, x.balance);
> 
>    auto y = fetchstruc!(OtherValue) ();
>    writefln ("%s, %s, %s", y.type, y.dirname, y.filename);
>    
>    auto a = fetchnullstruc!(ValueStrucWNull) ();
>    writefln ("%s, %s, %s, %s, %s, %#.2f, %s", a.name, a.age, a.addr1, a.addr2, a.addr3, a.balance, a.nullFlag);
> 
>    auto b = fetchnullstruc!(OtherValueWNull) ();
>    writefln ("%s, %s, %s, %s", b.type, b.dirname, b.filename, b.nullFlag);
> }


More information about the Digitalmars-d-learn mailing list