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?

Reply via email to