bitfields

downs default_357-line at yahoo.de
Sat Jun 27 05:56:57 PDT 2009


novice2 wrote:
> does anyone know: is D2 std.bitmanip compatible with C bitfields?
> can i use it, if i need translate .h file with something like this:
> 
> typedef struct {
>     unsigned int can_compress : 1;
>     unsigned int can_uncompress : 1;
>     unsigned int can_get_info : 1;
>     unsigned int : 7;
>     unsigned int : 16;
>     unsigned int : 16;
>     unsigned int : 16;
>     unsigned int : 16;
>     unsigned int : 16;
> } capabilities;
> 
> Thanks.

Here's a way to do it.

Enjoy! :)

Usage example:

struct Test {
  ushort bits;
  mixin GroupPackedAccess!(bits,
    ubyte, "stuff", 3,
    bool, "otherstuff"
  );
}


module packed;

template PackedAccessTools(string NAME, int from, int to) {
  const max = 1 << (to-from);
  static if (to >= 32) static assert(false, "Too large");
  else static if (to >= 16) alias uint type;
  else static if (to >= 8) alias ushort type;
  else alias ubyte type;
  // 0 .. 4 -> ((1 << 4):16 - 1):15 & ~0 -> 7 == 1111
  // 4 .. 8 -> ((1 << 8):256 - 1):255 & ~((1 << 4): 16 - 1):15 -> 11110000
  const type mask = ((1 << to) - 1) - ((1 << from) - 1);
  const ID = NAME~"_"~from.stringof~"_"~to.stringof;
}

template PackedAccess(alias VAR, T, string NAME, int from, int to) {
  mixin(ctReplace(`
    T NAME() {
      static if (is(T == bool))
        return (VAR & (°.mask)) != 0;
      else
        return cast(T) ((VAR & (°.mask)) >> from);
    }
    T NAME(T nv) {
      Assert(nv < °.max, "Value too big");
      VAR &= (~°.mask);
      VAR |= (nv << from);
      return nv;
    }
  `, "NAME", NAME, "°", "PackedAccessTools!(NAME, from, to)", "·", PackedAccessTools!(NAME, from, to).ID
  ));
}

template NaturalTypeSize(T) {
  static if (is(T==bool)) const NaturalTypeSize = 1;
  else static assert(false, "No known default size for "~T.stringof~"!");
}

template GroupPackedAccess(alias VAR, T...) {
  static if (T.length > 2) {
    static if (is(typeof(T[0])==void)) {
      static if (is(typeof(T[4]): int) && !is(T[4]: int)) {
        mixin PackedAccess!(VAR, T[2], T[3], T[1], T[1]+T[4]);
        mixin GroupPackedAccess!(VAR, void, T[1]+T[4], T[5 ..$]);
      } else {
        mixin PackedAccess!(VAR, T[2], T[3], T[1], T[1]+NaturalTypeSize!(T[2]));
        mixin GroupPackedAccess!(VAR, void, T[1]+NaturalTypeSize!(T[2]), T[4 ..$]);
      }
    } else {
      mixin GroupPackedAccess!(VAR, void, 0, T);
    }
  }
}


More information about the Digitalmars-d-learn mailing list