Thread overview
bit fields in struct
Nov 07, 2005
Shawn Liu
Nov 07, 2005
Regan Heath
Nov 07, 2005
Shawn Liu
Nov 07, 2005
Regan Heath
Nov 08, 2005
Shawn Liu
Nov 07, 2005
Sean Kelly
Nov 07, 2005
Regan Heath
Nov 07, 2005
Sean Kelly
Nov 08, 2005
Shawn Liu
Nov 09, 2005
Stewart Gordon
November 07, 2005
C struct has bit fields ability, e.g

typedef struct tag_SCRIPT_STATE { WORD uBidiLevel         :5; WORD fOverrideDirection :1; WORD fInhibitSymSwap    :1; WORD fCharShape         :1; WORD fDigitSubstitute   :1; WORD fInhibitLigate     :1; WORD fDisplayZWG        :1; WORD fArabicNumContext  :1; WORD fGcpClusters       :1; WORD fReserved          :1; WORD fEngineReserved    :2; } SCRIPT_STATE;

the C code sizeof(SCRIPT_STATE) results 2

According to D spec, no bit fields in D struct http://www.digitalmars.com/d/struct.html

The question is how to implement the bit fileds operation around D struct. Declare a WORD, then wrapper bitwise method with this WORD ?



November 07, 2005
On Mon, 7 Nov 2005 06:59:22 +0000 (UTC), Shawn Liu <Shawn_member@pathlink.com> wrote:
> C struct has bit fields ability, e.g
>
> typedef struct tag_SCRIPT_STATE {
> WORD uBidiLevel         :5;
> WORD fOverrideDirection :1;
> WORD fInhibitSymSwap    :1;
> WORD fCharShape         :1;
> WORD fDigitSubstitute   :1;
> WORD fInhibitLigate     :1;
> WORD fDisplayZWG        :1;
> WORD fArabicNumContext  :1;
> WORD fGcpClusters       :1;
> WORD fReserved          :1;
> WORD fEngineReserved    :2;
> } SCRIPT_STATE;
>
> the C code sizeof(SCRIPT_STATE) results 2
>
> According to D spec, no bit fields in D struct
> http://www.digitalmars.com/d/struct.html
>
> The question is how to implement the bit fileds operation around D struct.
> Declare a WORD, then wrapper bitwise method with this WORD ?

Here is what I did once:

struct DCB {
    DWORD DCBlength;       /* sizeof(DCB)                     */
    DWORD BaudRate;        /* Baudrate at which running       */
    uint BITS;
    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.                   */
}
alias DCB* LPDCB;

void fBinary(DCB* dcb, uint b)           { (b) ? bts(&dcb.BITS,0) : btr(&dcb.BITS,0); }	
void fParity(DCB* dcb, uint b)           { (b) ? bts(&dcb.BITS,1) : btr(&dcb.BITS,1); }
void fOutxCtsFlow(DCB* dcb, uint b)      { (b) ? bts(&dcb.BITS,2) : btr(&dcb.BITS,2); }
void fOutxDsrFlow(DCB* dcb, uint b)      { (b) ? bts(&dcb.BITS,3) : btr(&dcb.BITS,3); }
void fDtrControl(DCB* dcb, uint b)       { (bt(&b,0)) ? bts(&dcb.BITS,4) : btr(&dcb.BITS,4); (bt(&b,1)) ? bts(&dcb.BITS,5) : btr(&dcb.BITS,5); }
void fDsrSensitivity(DCB* dcb, uint b)   { (b) ? bts(&dcb.BITS,6) : btr(&dcb.BITS,6); }
void fTXContinueOnXoff(DCB* dcb, uint b) { (b) ? bts(&dcb.BITS,7) : btr(&dcb.BITS,7); }
void fOutX(DCB* dcb, uint b)             { (b) ? bts(&dcb.BITS,8) : btr(&dcb.BITS,8); }
void fInX(DCB* dcb, uint b)              { (b) ? bts(&dcb.BITS,9) : btr(&dcb.BITS,9); }
void fErrorChar(DCB* dcb, uint b)        { (b) ? bts(&dcb.BITS,10) : btr(&dcb.BITS,10); }
void fNull(DCB* dcb, uint b)             { (b) ? bts(&dcb.BITS,11) : btr(&dcb.BITS,11); }
void fRtsControl(DCB* dcb, uint b)       { (bt(&b,0)) ? bts(&dcb.BITS,12) : btr(&dcb.BITS,12); (bt(&b,1)) ? bts(&dcb.BITS,13) : btr(&dcb.BITS,13); }
void fAbortOnError(DCB* dcb, uint b)     { (b) ? bts(&dcb.BITS,14) : btr(&dcb.BITS,14); }

So, BITS replaces all the bit fields and methods replace all access to the bits.

Hope it helps.

Regan
November 07, 2005
Shawn Liu wrote:
> 
> The question is how to implement the bit fileds operation around D struct.
> Declare a WORD, then wrapper bitwise method with this WORD ?

Use bit arrays.


Sean
November 07, 2005
In article <opszuzgtvj23k2f5@nrage.netwin.co.nz>, Regan Heath says...
>
>On Mon, 7 Nov 2005 06:59:22 +0000 (UTC), Shawn Liu <Shawn_member@pathlink.com> wrote:
>> C struct has bit fields ability, e.g
>>
>> typedef struct tag_SCRIPT_STATE {
>>
>> The question is how to implement the bit fileds operation around D
>> struct.
>> Declare a WORD, then wrapper bitwise method with this WORD ?
>
>Here is what I did once:
>>So, BITS replaces all the bit fields and methods replace all access to the
>bits.
>
>Hope it helps.
>
>Regan


Well done. Thanks!


November 07, 2005
On Mon, 7 Nov 2005 08:05:49 +0000 (UTC), Shawn Liu <Shawn_member@pathlink.com> wrote:
> In article <opszuzgtvj23k2f5@nrage.netwin.co.nz>, Regan Heath says...
>>
>> On Mon, 7 Nov 2005 06:59:22 +0000 (UTC), Shawn Liu
>> <Shawn_member@pathlink.com> wrote:
>>> C struct has bit fields ability, e.g
>>>
>>> typedef struct tag_SCRIPT_STATE {
>>>
>>> The question is how to implement the bit fileds operation around D
>>> struct.
>>> Declare a WORD, then wrapper bitwise method with this WORD ?
>>
>> Here is what I did once:
>>> So, BITS replaces all the bit fields and methods replace all access to the
>> bits.
>>
>> Hope it helps.
>>
>> Regan
>
>
> Well done. Thanks!

Ooops I forgot to comment out the bit fields in the struct I posted, that'll teach me for copy/pasting them from the original source instead of my slightly modified one. Just remove/comment the bitfields and you have what I have. Sorry.

Regan
November 07, 2005
On Sun, 06 Nov 2005 23:24:06 -0800, Sean Kelly <sean@f4.ca> wrote:
> Shawn Liu wrote:
>>  The question is how to implement the bit fileds operation around D struct.
>> Declare a WORD, then wrapper bitwise method with this WORD ?
>
> Use bit arrays.

It's a nice idea but I found that it didn't really work that well.

I asked this same question once before here:
http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D.learn/1503

Using this struct:

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.                   */
}
alias DCB* LPDCB;

Ideally I'd like to be able to say:

struct DCB {
  ..etc..
  bit[32] BITS;
  alias BITS[0] fBinary;
  alias BITS[1] fParity;
}

and so on, then use them like so:

void main() {
  DCB d;
  d.fBinary = 1;
  d.fParity = 0;
}

I tried a number of things but couldn't come up with anything short of writing methods for each bitfield, meaning you end up with a getter and setter for every bit, ick.

The best implementation I found was what posted to the other branch of this thread, and I guess I could have used a bit array there, but the intrinsic functions seemed better somehow.

Regan
November 07, 2005
Regan Heath wrote:
> 
> I tried a number of things but couldn't come up with anything short of  writing methods for each bitfield, meaning you end up with a getter and  setter for every bit, ick.

True, but at least D has properties... and the methods don't affect the size of the struct.  I suppose it's a toss-up whether size concerns are better addressed by an enum and get/set methods or per-bit properties. The enum method has the advantage of being more easily maintainable however.


Sean
November 08, 2005
In article <opszu3vig823k2f5@nrage.netwin.co.nz>, Regan Heath says...
>
>Ideally I'd like to be able to say:
>
>struct DCB {
>   ..etc..
>   bit[32] BITS;
>   alias BITS[0] fBinary;
>   alias BITS[1] fParity;
>}
>
>and so on, then use them like so:
>
>void main() {
>   DCB d;
>   d.fBinary = 1;
>   d.fParity = 0;
>}
>


The compiler complains that :
bits_struct.d(3): BITS is used as a type
bits_struct.d(4): BITS is used as a type


November 08, 2005
"Regan Heath" <regan@netwin.co.nz> wrote:opszuzgtvj23k2f5@nrage.netwin.co.nz...
> On Mon, 7 Nov 2005 06:59:22 +0000 (UTC), Shawn Liu <Shawn_member@pathlink.com> wrote:
>> C struct has bit fields ability, e.g
>>
>> typedef struct tag_SCRIPT_STATE {
>> WORD uBidiLevel         :5;

template BITWISE(T)
{
// bit value set
void btvs(T* pData, uint bitnum, uint val){
 *pData &=  ~(0x01 << bitnum);
 if(val) *pData |= (0x01 << bitnum);
}
// bit value get
T btvg(T* data, uint bitnum){
 return cast(T)((*data >> bitnum) & 0x01);
}
}
alias BITWISE!(BYTE).btvs btvs;
alias BITWISE!(WORD).btvs btvs;
alias BITWISE!(DWORD).btvs btvs;
alias BITWISE!(BYTE).btvg btvg;
alias BITWISE!(WORD).btvg btvg;
alias BITWISE!(DWORD).btvg btvg;

struct SCRIPT_STATE {
WORD data;
// getter
uint uBidiLevel()   { return cast(uint)(data & 0x1F);}
uint fOverrideDirection()  { return btvg(data, 5); }
uint fInhibitSymSwap()  { return btvg(data, 6); }
uint fCharShape()    { return btvg(data, 7); }
uint fDigitSubstitute()  { return btvg(data, 8); }
uint fInhibitLigate()   { return btvg(data, 9); }
uint fDisplayZWG()    { return btvg(data, 10); }
uint fArabicNumContext()  { return btvg(data, 11); }
uint fGcpClusters()   { return btvg(data, 12); }
uint fReserved()   { return btvg(data, 13); }
uint fEngineReserved()  { return 0; }//do nothing with reserved
// setter
void uBidiLevel(uint val)    { data &= 0xFFE0; data |= (val & 0x1F); }
void fOverrideDirection(uint val)  { btvs(&data, 5, val); }
void fInhibitSymSwap(uint val)  { btvs(&data, 6, val); }
void fCharShape(uint val)   { btvs(&data, 7, val); }
void fDigitSubstitute(uint val)  { btvs(&data, 8, val); }
void fInhibitLigate(uint val)  { btvs(&data, 9, val); }
void fDisplayZWG(uint val)   { btvs(&data, 10, val); }
void fArabicNumContext(uint val) { btvs(&data, 11, val); }
void fGcpClusters(uint val)   { btvs(&data, 12, val); }
void fReserved(uint val)   { btvs(&data, 13, val); }
void fEngineReserved(uint val)  { } //do nothing with reserved
}

November 09, 2005
Shawn Liu wrote:
<snip>
> According to D spec, no bit fields in D struct
> http://www.digitalmars.com/d/struct.html
> 
> The question is how to implement the bit fileds operation around D struct.
> Declare a WORD, then wrapper bitwise method with this WORD ?

http://www.digitalmars.com/d/dstyle.html

"Meaningless Type Aliases

Things like:

    alias void VOID;
    alias int INT;
    alias int* pint;

should be avoided."

Stewart.

-- 
-----BEGIN GEEK CODE BLOCK-----
Version: 3.1
GCS/M d- s:- C++@ a->--- UB@ P+ L E@ W++@ N+++ o K-@ w++@ O? M V? PS- PE- Y? PGP- t- 5? X? R b DI? D G e++>++++ h-- r-- !y
------END GEEK CODE BLOCK------

My e-mail is valid but not my primary mailbox.  Please keep replies on the 'group where everyone may benefit.