Jump to page: 1 2
Thread overview
iterating through members of bitfields
Jan 18, 2017
Nestor
Jan 18, 2017
Ali Çehreli
Jan 18, 2017
Nestor
Jan 18, 2017
drug
Jan 20, 2017
Nestor
Jan 20, 2017
drug
Jan 20, 2017
Nestor
Jan 20, 2017
drug
Jan 20, 2017
drug
Jan 20, 2017
Ali Çehreli
Jan 21, 2017
Nestor
January 18, 2017
Hi,

I was just looking at an interesting function from http://codepad.org/lSDTFd7E :

void printFields(T)(T args) {
  auto values = args.tupleof;

  size_t max;
  size_t temp;
  foreach (index, value; values) {
    temp = T.tupleof[index].stringof.length;
    if (max < temp) max = temp;
  }
  max += 1;
  foreach (index, value; values) {
    writefln("%-" ~ to!string(max) ~ "s %s", T.tupleof[index].stringof, value);
  }
}

Can something similar be done for bitfields? I tried running this and I only get something like this:

_f01_f02_f03      25312
_f04_f05_f06_f07  21129
_f08_f09_f10      53575
_f11_f12_f13_f14  9264

January 17, 2017
On 01/17/2017 04:37 PM, Nestor wrote:
> Hi,
>
> I was just looking at an interesting function from
> http://codepad.org/lSDTFd7E :
>
> void printFields(T)(T args) {
>   auto values = args.tupleof;
>
>   size_t max;
>   size_t temp;
>   foreach (index, value; values) {
>     temp = T.tupleof[index].stringof.length;
>     if (max < temp) max = temp;
>   }
>   max += 1;
>   foreach (index, value; values) {
>     writefln("%-" ~ to!string(max) ~ "s %s", T.tupleof[index].stringof,
> value);
>   }
> }
>
> Can something similar be done for bitfields? I tried running this and I
> only get something like this:
>
> _f01_f02_f03      25312
> _f04_f05_f06_f07  21129
> _f08_f09_f10      53575
> _f11_f12_f13_f14  9264
>

Not available but it should be possible to parse the produced code:

import std.bitmanip;

string makeBitFieldPrinter(string fieldImpl) {
    return q{
        void printBitFields() const {
            import std.stdio: writeln;
            writeln("Please improve this function by parsing fieldImpl. :)");
        }
    };
}

struct S {
    enum myFields = bitfields!(int, "a", 24,
                               byte, "b", 8);

    pragma(msg, "This is the mixed-in bit field code\n---------\n",
           myFields, "\n----------");


    mixin (myFields);
    mixin (makeBitFieldPrinter(myFields));
}

void main() {
    const s = S();
    s.printBitFields();
}

Of course that would depend on the implementation of bitfields(), which can change without notice.

Ali

January 18, 2017
On Wednesday, 18 January 2017 at 01:15:05 UTC, Ali Çehreli wrote:
> Not available but it should be possible to parse the produced code:
>
> import std.bitmanip;
>
> string makeBitFieldPrinter(string fieldImpl) {
>     return q{
>         void printBitFields() const {
>             import std.stdio: writeln;
>             writeln("Please improve this function by parsing fieldImpl. :)");
>         }
>     };
> }
>
> struct S {
>     enum myFields = bitfields!(int, "a", 24,
>                                byte, "b", 8);
>
>     pragma(msg, "This is the mixed-in bit field code\n---------\n",
>            myFields, "\n----------");
>
>
>     mixin (myFields);
>     mixin (makeBitFieldPrinter(myFields));
> }
>
> void main() {
>     const s = S();
>     s.printBitFields();
> }
>
> Of course that would depend on the implementation of bitfields(), which can change without notice.
>
> Ali

Thanks Ali, I was using bitfields according to documentation, but now I see that way I can't access the mixin string:

struct S {
    mixin(bitfields!(
        bool, "f1",    1,
        uint, "f2",    4,
        uint, "f3",    3)
    );
}


January 18, 2017
I've "solved" the same problem by using AliasSeq to generate bitfields so that for iterating over bitfields I can iterate over alias sequence and mixin code. Not very good but it works.
January 20, 2017
On Wednesday, 18 January 2017 at 12:52:56 UTC, drug wrote:
> I've "solved" the same problem by using AliasSeq to generate bitfields so that for iterating over bitfields I can iterate over alias sequence and mixin code. Not very good but it works.

Interesting, could you provide a working example?
January 20, 2017
20.01.2017 04:21, Nestor пишет:
> On Wednesday, 18 January 2017 at 12:52:56 UTC, drug wrote:
>> I've "solved" the same problem by using AliasSeq to generate bitfields
>> so that for iterating over bitfields I can iterate over alias sequence
>> and mixin code. Not very good but it works.
>
> Interesting, could you provide a working example?
Something like that https://goo.gl/C4nOqw
Because you generate code iterating over AliasSeq you can do almost everything you need - for example generate setters/getters.
January 20, 2017
On Friday, 20 January 2017 at 08:13:08 UTC, drug wrote:
> Something like that https://goo.gl/C4nOqw
> Because you generate code iterating over AliasSeq you can do almost everything you need - for example generate setters/getters.

Interesting site, I wouldn't implemente something like this in a public server but sure it's useful.

Regarding the example, looks interesting though it raises s a few doubts (forgive me if they sound silly):

What's UAP?

Where does one define the size for a field using AliasSeq, and in this example, why does it take 1 bit if the size is not declared anywhere? (also, why does it compile when the last field terminates with a comma?)

alias Fields = AliasSeq!(
	ushort,     "field0",
	ubyte,      "field1",
	uint,       "field2",
	ubyte,      "field3",
	bool,       "field4",
	bool,       "field5",
	bool,       "field6",
	ubyte,      "field7",
);

Why does the switch apply to the remainder of the modulo operation, does Fields contains indexes to types and names as if it was an array?

January 20, 2017
20.01.2017 15:04, Nestor пишет:
> On Friday, 20 January 2017 at 08:13:08 UTC, drug wrote:
>> Something like that https://goo.gl/C4nOqw
>> Because you generate code iterating over AliasSeq you can do almost
>> everything you need - for example generate setters/getters.
>
> Interesting site, I wouldn't implemente something like this in a public
> server but sure it's useful.
>
> Regarding the example, looks interesting though it raises s a few doubts
> (forgive me if they sound silly):
>
> What's UAP?
This code is part of an inhouse instrument, UAP is artifact of this instrument, should be:
```
struct MyStruct(Fields...)
{
	import std.bitmanip : bitfields;
	
	mixin(makeBitfields!Fields); // <-- Fields instead of UAP
}
```
>
> Where does one define the size for a field using AliasSeq, and in this
> example, why does it take 1 bit if the size is not declared anywhere?
I have fields with size equal to one only, you can add another column to AliasSeq to describe the size
> (also, why does it compile when the last field terminates with a comma?)
it's feature of D for convenience
>
> alias Fields = AliasSeq!(
>     ushort,     "field0",
>     ubyte,      "field1",
>     uint,       "field2",
>     ubyte,      "field3",
>     bool,       "field4",
>     bool,       "field5",
>     bool,       "field6",
>     ubyte,      "field7",
> );
>
> Why does the switch apply to the remainder of the modulo operation, does
> Fields contains indexes to types and names as if it was an array?
>
May be does, I don't know so I use the remainder.
January 20, 2017
20.01.2017 15:04, Nestor пишет:
> Where does one define the size for a field using AliasSeq, and in this
> example, why does it take 1 bit if the size is not declared anywhere?

Something like that https://goo.gl/zV8T23
January 20, 2017
On 01/19/2017 05:21 PM, Nestor wrote:
> On Wednesday, 18 January 2017 at 12:52:56 UTC, drug wrote:
>> I've "solved" the same problem by using AliasSeq to generate bitfields
>> so that for iterating over bitfields I can iterate over alias sequence
>> and mixin code. Not very good but it works.
>
> Interesting, could you provide a working example?

Here is 'iterableBitfields' that mixes in both a static array of bit field specs and a range that iterates through their values. Obviously, because the range must have one element type, you have to specify what works you: int, string, etc.

import std.stdio;
import std.bitmanip;
import std.string;
import std.typecons;
import std.conv;
import std.algorithm;

string makeBitfieldSpecs(IterValueType, Args...)(string specsPrefix) {
    static assert(Args.length % 3 == 0);

    string members;
    string type;
    string name;
    size_t width;
    string value;
    foreach (i, arg; Args) {
        static if (i % 3 == 0) {
            type = arg.stringof;
        }
        else static if (i % 3 == 1) {
            name = arg;
        }
        else {
            width = arg;
            value = format("(typeof(this) obj) => obj.%s().to!%s",
                           name, IterValueType.stringof);
            members ~= format(`tuple("%s", "%s", %s, %s),`,type, name, width, value);
        }
    }
    string specsArray = format("static const %sSpecs = [ %s ];", specsPrefix, members);
    string specsFunc = format(q{
        auto %sValues() const {
            return %sSpecs.map!(spec => spec[3](this));
        }}, specsPrefix, specsPrefix);
    return specsArray ~ specsFunc;
}

string iterableBitfields(string specsPrefix, IterValueType, Args...)() {
    return bitfields!Args ~ makeBitfieldSpecs!(IterValueType, Args)(specsPrefix);
}

struct S {
    int myVar;
    mixin (iterableBitfields!("myFields", // prefix for names of mixed-in array and func
                              int,        // the type to present field values in (can be string)
                              // Regular args to std.typecons.bitfields follow:
                              int, "a", 24,
                              byte, "b", 8));
}

void main() {
    auto s = S();
    s.myVar = 42;
    s.a = 1;
    s.b = 2;

    /* The struct gains two additional members:
     *    <prefix>Specs: An array of tuples
     *    <prefix>Values: A range of field values
     */
    writefln("The specs (last one is a lambda):\n%(  %s\n%)", s.myFieldsSpecs);
    writefln("The values: %(%s, %)", s.myFieldsValues);

    // You must pass the object when calling the value lambda explicitly.
    // Here is the value of 'a' through the lambda in the spec:
    assert(s.a == s.myFieldsSpecs[0][3](s));  // Note 's' is passed to lambda
}

Ali

« First   ‹ Prev
1 2