www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - iterating through members of bitfields

reply Nestor <nestorperez2016 yopmail.com> writes:
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
Jan 17
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
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
Jan 17
parent reply Nestor <nestorperez2016 yopmail.com> writes:
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) ); }
Jan 18
parent reply drug <drug2004 bk.ru> writes:
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.
Jan 18
parent reply Nestor <nestorperez2016 yopmail.com> writes:
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?
Jan 19
next sibling parent reply drug <drug2004 bk.ru> writes:
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.
Jan 20
parent reply Nestor <nestorperez2016 yopmail.com> writes:
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?
Jan 20
next sibling parent drug <drug2004 bk.ru> writes:
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.
Jan 20
prev sibling parent drug <drug2004 bk.ru> writes:
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
Jan 20
prev sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
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
Jan 20
parent Nestor <nestorperez2016 yopmail.com> writes:
Thank you both!
Jan 21