structs, templates, alias

Ellery Newcomer ellery-newcomer at utulsa.edu
Sun Apr 25 08:04:33 PDT 2010


Hello.

I have a bunch of disparate binary record types that I need to be able 
to read and write to/from a binary stream. Currently, the way I do this 
is just by drumming out a struct declaration and relying on the tupleof 
property to specify how to read/write.

Ex:

struct Rec0{
   ushort index1;
   ushort index2;
   ushort index3;
   ushort junk;
   double value;
}

Rec rec;
// blit knows!
blit(rec, x"01 00 12 00 05 00 00 00 7F F8 00 00 00 00 00 00");

It works really well for simple cases. However, there are some records 
that have really complicated substructures.

struct Rec1{
   ushort index;
   ushort options;
   ushort nparams;
   Parameter[] params;
}
struct Parameter{
   ParamType pt;
   union{
     STRING str;
     CV param;
   }
}

etc etc

for params, or any substructure dependent on a length field, if the 
length field immediately precedes the structure, I can wrap the two in a 
struct which my read/write routines can treat specially as the next 
contiguous field. Well and good.

What's really annoying is when the length field and the array/structure 
are separated by one or more fields, eg.

struct Rec2{
   ushort index;
   ushort nparams;
   ushort options;
   Parameter[] params;
}

At the moment, I just special case these records. However, I would very 
much like to annotate their fields somehow so that the io routines can 
treat them like any other record. One thing I thought about was using 
templates to express this:

struct Rec1{
   ushort index;
   ushort options;
   Parameters!() params;
}

struct Rec2{
   ushort index;
   ushort nparams;
   ushort options;
   Parameters!(nparams) params;
}

// blit knows it can call member blit on this struct
// one thing I like about this is that it always knows
// about the length field, and can automatically modify
// it when you do something with the parameter array.
struct Parameters(alias k = __dflt__){
   static if(k.stringof == "__dflt__") ushort len;
   else alias k len;

   Parameter[] _params;
   int blit(byte[] data){
     int pos = 0;
     static if(k.stringof == "__dflt__") pos = read(len,data);
     //else assume len has already been read
     params.length = len;
     ...
     // read params
   }
}

That doesn't work, though, as DMD complains about inaccessible frames or 
something. I suppose it probably shouldn't work.

Does anyone have any ideas regarding this problem?


More information about the Digitalmars-d-learn mailing list