View mode: basic / threaded / horizontal-split · Log in · Help
August 09, 2005
Converting C/C++ bit fields...
I'd like to find out what techniques people have been using to convert  
C/C++ structs containing bitfields to D, take for example this struct:

typedef struct _DCB {
    DWORD DCBlength;      /* sizeof(DCB)                     */
    DWORD BaudRate;       /* Baudrate at which running       */
    DWORD fBinary: 1;     /* Binary Mode (skip EOF check)    */
    DWORD fParity: 1;     /* Enable parity checking          */
    DWORD fOutxCtsFlow:1; /* CTS handshaking on output       */
    DWORD fOutxDsrFlow:1; /* DSR handshaking on output       */
    DWORD fDtrControl:2;  /* DTR Flow control                */
    DWORD fDsrSensitivity:1; /* DSR Sensitivity              */
    DWORD fTXContinueOnXoff: 1; /* Continue TX when Xoff sent */
    DWORD fOutX: 1;       /* Enable output X-ON/X-OFF        */
    DWORD fInX: 1;        /* Enable input X-ON/X-OFF         */
    DWORD fErrorChar: 1;  /* Enable Err Replacement          */
    DWORD fNull: 1;       /* Enable Null stripping           */
    DWORD fRtsControl:2;  /* Rts Flow control                */
    DWORD fAbortOnError:1; /* Abort all reads and writes on Error */
    DWORD fDummy2:17;     /* Reserved                        */
    WORD wReserved;       /* Not currently used              */
    WORD XonLim;          /* Transmit X-ON threshold         */
    WORD XoffLim;         /* Transmit X-OFF threshold        */
    BYTE ByteSize;        /* Number of bits/byte, 4-8        */
    BYTE Parity;          /* 0-4=None,Odd,Even,Mark,Space    */
    BYTE StopBits;        /* 0,1,2 = 1, 1.5, 2               */
    char XonChar;         /* Tx and Rx X-ON character        */
    char XoffChar;        /* Tx and Rx X-OFF character       */
    char ErrorChar;       /* Error replacement char          */
    char EofChar;         /* End of Input character          */
    char EvtChar;         /* Received Event character        */
    WORD wReserved1;      /* Fill for now.                   */
} DCB, *LPDCB;

My initial thought was to use bit, bit[2] and bit[17] but of course D  
allocates 1 byte for each stand alone 'bit' so the structure ends up  
totally the wrong size.


Next I tried a bit[32] called _bits (this should make the struct size  
correct), and some aliases, eg.
  alias _bits[0] fBinary;

but I get the error "_bits is used as a type". That is a little odd  
considering I can write "alias EvtChar bob" (is this using EvtChar as a  
type?)


Lastly I tried to use properties, i.e.

bit fBinary()      { return _bits[0]; }
bit fBinary(bit b) { _bits[0] = b; return fBinary; }

these seem to work for the single bit ones, but the 2 bit ones:

bit[2] fDtrControl()          { return _bits[4..6]; }
bit[2] fDtrControl(bit[2] b)  { _bits[4..6] = b[]; return fDtrControl; }

that's no good, you cannot return a 'static' bit[2].

I then tried:

ubyte toUbyte(bit[] ba)      { ubyte v = 0; foreach(bit b; ba) { v *= 2; v  
+= b; } return v; }
ubyte fDtrControl()          { return toUbyte(_bits[4..6]); }
ubyte fDtrControl(ubyte b)   { _bits[4..6] = (cast(bit*)&b)[0..2]; return  
fDtrControl; }

but that gives an array bounds error in the setter. I didn't investigate  
this any further, the effort required already is quite ridiculous, such  
that I figure there must or should be a better solution.


Thoughts?

Regan
August 09, 2005
Re: Converting C/C++ bit fields...
On Tue, 09 Aug 2005 07:54:16 -0400, Regan Heath <regan@netwin.co.nz> wrote:

> I'd like to find out what techniques people have been using to convert  
> C/C++ structs containing bitfields to D

How about masking and shifting DWORD bits
August 09, 2005
Re: Converting C/C++ bit fields...
On Tue, 09 Aug 2005 08:12:17 -0400, Vathix <chris@dprogramming.com> wrote:
> On Tue, 09 Aug 2005 07:54:16 -0400, Regan Heath <regan@netwin.co.nz>  
> wrote:
>
>> I'd like to find out what techniques people have been using to convert  
>> C/C++ structs containing bitfields to D
>
> How about masking and shifting DWORD bits

Sure, but I want to be able to say:

DCB a;
a.fParity = true;
..etc..

which I guess I can do, if I define a getter/setter for each one, and do  
all the bit shifting etc in them. All that effort/work.. seems like it  
_should_ be easier.

Regan
August 09, 2005
Re: Converting C/C++ bit fields...
"Regan Heath" <regan@netwin.co.nz> wrote in message 
news:opsu8ooqhn23k2f5@nrage.netwin.co.nz...
> I'd like to find out what techniques people have been using to convert 
> C/C++ structs containing bitfields to D, take for example this struct:
[snip]
> Thoughts?

import std.intrinsic;

// a bit field
template BitField(uint n, alias data) {
   int get(){ return bt(&data,n); }
   void set(int m){m?bts(&data,n):btr(&data,n);}
}
// a two-bit field
template BitField2(uint n, alias data) {
   int get(){ return data >> n & 3; }
   void set(int m){ data = (data & ~(3<<n)) | (m<<n) ;}
}
struct Foo {
   uint fields;
   mixin BitField!(0,fields) f1;
   mixin BitField!(1,fields) f2;
   mixin BitField2!(2,fields) f3;
   mixin BitField!(4,fields) f4;
}

int main() {
   Foo x;
   x.f1.set = true;
   x.f3.set = 3;
   x.f4.set = true;
   printf("fields: %d\n",x.fields);
   printf("x.f1 %d\n", x.f1.get);
   printf("x.f2 %d\n", x.f2.get);
   printf("x.f3 %d\n", x.f3.get);
   printf("x.f4 %d\n", x.f4.get);
   return 0;
}
August 09, 2005
Re: Converting C/C++ bit fields...
Ben Hinkle wrote:

> "Regan Heath" <regan@netwin.co.nz> wrote in message 
> news:opsu8ooqhn23k2f5@nrage.netwin.co.nz...
> 
>>I'd like to find out what techniques people have been using to convert 
>>C/C++ structs containing bitfields to D, take for example this struct:
> 
> [snip]
> 
>>Thoughts?
> 
> 
> import std.intrinsic;
> 
> // a bit field
> template BitField(uint n, alias data) {
>     int get(){ return bt(&data,n); }
>     void set(int m){m?bts(&data,n):btr(&data,n);}
> }
> // a two-bit field
> template BitField2(uint n, alias data) {
>     int get(){ return data >> n & 3; }
>     void set(int m){ data = (data & ~(3<<n)) | (m<<n) ;}
> }
> struct Foo {
>     uint fields;
>     mixin BitField!(0,fields) f1;
>     mixin BitField!(1,fields) f2;
>     mixin BitField2!(2,fields) f3;
>     mixin BitField!(4,fields) f4;
> }
> 
> int main() {
>     Foo x;
>     x.f1.set = true;
>     x.f3.set = 3;
>     x.f4.set = true;
>     printf("fields: %d\n",x.fields);
>     printf("x.f1 %d\n", x.f1.get);
>     printf("x.f2 %d\n", x.f2.get);
>     printf("x.f3 %d\n", x.f3.get);
>     printf("x.f4 %d\n", x.f4.get);
>     return 0;
> }

Clever boy.  I'll need to remember that.  I'd use the more general:

    template BitField (uint start, uint count, alias data, type = uint)
    {
        static assert ((1L << (start + count)) - 1 <= data.max);

        const uint mask = (1 << count) - 1;

        type get ()
        {
            return cast (type) ((data >> start) & mask);
        }

        type set (type value)
        {
            data = (data & ~(mask << start)) | ((cast (typeof (data)) 
value & mask) << start);
            return value;
        }
    }

Too bad opCall doesn't work with mixins.
August 09, 2005
Re: Converting C/C++ bit fields...
Burton Radons wrote:

>         const uint mask = (1 << count) - 1;

That should be "const typeof (data) mask = (1UL << count) - 1;" so that 
it works with long.
August 09, 2005
Re: Converting C/C++ bit fields...
Nice! Thanks.

Still, it would be nice if D had a better way to handle bitfields, if only  
to ease conversion of C/C++ structs containing them. The fact that we're  
not using the built in bit support suggests to me that it's not as useful  
as it should be.

Regan

On Tue, 9 Aug 2005 10:25:44 -0400, Ben Hinkle <bhinkle@mathworks.com>  
wrote:
> "Regan Heath" <regan@netwin.co.nz> wrote in message
> news:opsu8ooqhn23k2f5@nrage.netwin.co.nz...
>> I'd like to find out what techniques people have been using to convert
>> C/C++ structs containing bitfields to D, take for example this struct:
> [snip]
>> Thoughts?
>
> import std.intrinsic;
>
> // a bit field
> template BitField(uint n, alias data) {
>     int get(){ return bt(&data,n); }
>     void set(int m){m?bts(&data,n):btr(&data,n);}
> }
> // a two-bit field
> template BitField2(uint n, alias data) {
>     int get(){ return data >> n & 3; }
>     void set(int m){ data = (data & ~(3<<n)) | (m<<n) ;}
> }
> struct Foo {
>     uint fields;
>     mixin BitField!(0,fields) f1;
>     mixin BitField!(1,fields) f2;
>     mixin BitField2!(2,fields) f3;
>     mixin BitField!(4,fields) f4;
> }
>
> int main() {
>     Foo x;
>     x.f1.set = true;
>     x.f3.set = 3;
>     x.f4.set = true;
>     printf("fields: %d\n",x.fields);
>     printf("x.f1 %d\n", x.f1.get);
>     printf("x.f2 %d\n", x.f2.get);
>     printf("x.f3 %d\n", x.f3.get);
>     printf("x.f4 %d\n", x.f4.get);
>     return 0;
> }
>
>
August 09, 2005
Re: Converting C/C++ bit fields...
> Still, it would be nice if D had a better way to handle bitfields, if only 
> to ease conversion of C/C++ structs containing them. The fact that we're 
> not using the built in bit support suggests to me that it's not as useful 
> as it should be.

I haven't read the docs in detail but probably bit arrays have too much 
freedom in how they are implemented to be reliable for replacing C bit 
fields. ie- the packing and alignment become crucial and that's something 
that the shifting implementation can control (since they have to control 
it). To me the only problem with bitfields is that the auto .h->.d 
translator (I can't remember the name of the program) seems to ignore them 
so any struct with a bitfield gets hosed (without warning, I believe).
August 09, 2005
Re: Converting C/C++ bit fields...
On Tue, 9 Aug 2005 19:07:53 -0400, Ben Hinkle <ben.hinkle@gmail.com> wrote:
>> Still, it would be nice if D had a better way to handle bitfields, if  
>> only
>> to ease conversion of C/C++ structs containing them. The fact that we're
>> not using the built in bit support suggests to me that it's not as  
>> useful
>> as it should be.
>
> I haven't read the docs in detail but probably bit arrays have too much
> freedom in how they are implemented to be reliable for replacing C bit
> fields. ie- the packing and alignment become crucial and that's something
> that the shifting implementation can control (since they have to control
> it). To me the only problem with bitfields is that the auto .h->.d
> translator (I can't remember the name of the program) seems to ignore  
> them
> so any struct with a bitfield gets hosed (without warning, I believe).

I think the problem with .h->.d translations is that there is no simple,  
easy way to translate bitfields.

Why can't I use:

bit[32] data;
alias data[0] a;
alias data[1] b;
alias data[2] c;

..etc..?

Regan
Top | Discussion index | About this forum | D home