Thread overview
How to translate this C macro to D mixin/template mixin?
Jun 15
VitaliiY
Jun 16
VitaliiY
Jun 15
Dennis
Jun 16
VitaliiY
Jun 16
Tejas
June 15

Could anybody help with translation of this C macro to D mixin/mixin template? Here a - unsigned char, b - int. It's simple with STARTDATA as mixin, but STOREBITS and ADDBITS use variables defined in STARTDATA scope, so I can't understand how to do mixin template with it.

#define STARTDATA \
  size_t ressize=0; \
  char *blockstart; \
  int numbits; \
  uint64_t bitbuffer=0;

#define STOREBITS \
  while(numbits >= 8) \
  { \
    if(!size) return 0; \
    *(buffer++) = bitbuffer>>(numbits-8); \
    numbits -= 8; \
    ++ressize; \
    --size; \
  }

#define ADDBITS(a, b) \
  { \
    bitbuffer = (bitbuffer<<(a))|((b)&((1<<a)-1)); \
    numbits += (a); \
    STOREBITS \
  }
June 15
On 6/15/21 5:18 AM, VitaliiY wrote:

> STOREBITS and ADDBITS use variables defined in STARTDATA

If possible in your use case, I would put those variables in a struct type and make add() a member function. However, a similar type already exists as std.bitmanip.BitArray.

Ali

June 15

On Tuesday, 15 June 2021 at 12:18:26 UTC, VitaliiY wrote:

>

It's simple with STARTDATA as mixin, but STOREBITS and ADDBITS use variables defined in STARTDATA scope, so I can't understand how to do mixin template with it.

If the code duplication isn't too bad, consider just expanding the C macros and translating that. I've noticed that some C programmers like to use complex macros just to save 10 lines.

Otherwise, to make STOREBITS and ADDBITS access variables from STARTDATA, you can define them as inner functions.

void f() {
    size_t ressize=0;
    char* blockstart;
    int numbits;
    ulong bitbuffer=0;

    size_t size;

    void storeBits() {
        while(numbits >= 8) {
            if(!size) return 0;
            *(buffer++) = bitbuffer>>(numbits-8);
            numbits -= 8;
            ++ressize;
            --size;
        }
    }
}

For the most literal translation, you can use a string mixin. You can't use a template mixin here since those can't insert code, only declarations.

enum string ADDBITS(string a, string b) = `
{
    bitbuffer = (bitbuffer<<(`~a~`))|((`~b~`)&((1<<`~a~`)-1));
    numbits += (`~a~`);
    mixin(STOREBITS);
}`;

// on use: ADDBITS(varA, varB) becomes
mixin(ADDBITS!("varA", "varB"));
June 16
On Tuesday, 15 June 2021 at 12:38:15 UTC, Ali Çehreli wrote:
> On 6/15/21 5:18 AM, VitaliiY wrote:
>
> > STOREBITS and ADDBITS use variables defined in STARTDATA
>
> If possible in your use case, I would put those variables in a struct type and make add() a member function. However, a similar type already exists as std.bitmanip.BitArray.
>
> Ali

Thank you, Ali! Idea with member function seems interesting.
June 16

On Tuesday, 15 June 2021 at 12:39:40 UTC, Dennis wrote:

>

On Tuesday, 15 June 2021 at 12:18:26 UTC, VitaliiY wrote:

>

[...]

enum string ADDBITS(string a, string b) = { bitbuffer = (bitbuffer<<(~a~))|((~b~)&((1<<~a~)-1)); numbits += (~a~); mixin(STOREBITS); };

// on use: ADDBITS(varA, varB) becomes
mixin(ADDBITS!("varA", "varB"));
`

[...]

Thank you, Dennis. I tried with this kind of mixin, but a, b - are type of 'int so it's confusing to use them as mixin arguments.

June 16

On Wednesday, 16 June 2021 at 05:48:21 UTC, VitaliiY wrote:

>

On Tuesday, 15 June 2021 at 12:39:40 UTC, Dennis wrote:

>

On Tuesday, 15 June 2021 at 12:18:26 UTC, VitaliiY wrote:

>

[...]

enum string ADDBITS(string a, string b) = { bitbuffer = (bitbuffer<<(~a~))|((~b~)&((1<<~a~)-1)); numbits += (~a~); mixin(STOREBITS); };

// on use: ADDBITS(varA, varB) becomes
mixin(ADDBITS!("varA", "varB"));
`

[...]

Thank you, Dennis. I tried with this kind of mixin, but a, b - are type of 'int so it's confusing to use them as mixin arguments.

Use the .stringof property. That should do it.