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

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, 2021
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, 2021

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, 2021
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, 2021

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, 2021

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.