Home | History | Annotate | Line # | Download | only in common
      1 /**
      2  * A library bitfields utility
      3  *
      4  * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved
      5  * Authors:   Dennis Korpel
      6  * License:   $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
      7  * Source:    $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/common/bitfields.d, common/bitfields.d)
      8  * Documentation: https://dlang.org/phobos/dmd_common_bitfields.html
      9  * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/common/bitfields.d
     10  */
     11 module dmd.common.bitfields;
     12 
     13 /**
     14  * Generate code for bit fields inside a struct/class body
     15  * Params:
     16  *   S = type of a struct with only boolean fields, which should become bit fields
     17  *   T = type of bit fields variable, must have enough bits to store all booleans
     18  * Returns: D code with a bit fields variable and getter / setter functions
     19  */
     20 extern (D) string generateBitFields(S, T)()
     21 if (__traits(isUnsigned, T))
     22 {
     23     string result = "extern (C++) pure nothrow @nogc @safe final {";
     24     enum structName = __traits(identifier, S);
     25 
     26     foreach (size_t i, mem; __traits(allMembers, S))
     27     {
     28         static assert(is(typeof(__traits(getMember, S, mem)) == bool));
     29         static assert(i < T.sizeof * 8, "too many fields for bit field storage of type `"~T.stringof~"`");
     30         enum mask = "(1 << "~i.stringof~")";
     31         result ~= "
     32         /// set or get the corresponding "~structName~" member
     33         bool "~mem~"() const { return !!(bitFields & "~mask~"); }
     34         /// ditto
     35         bool "~mem~"(bool v)
     36         {
     37             v ? (bitFields |= "~mask~") : (bitFields &= ~"~mask~");
     38             return v;
     39         }";
     40     }
     41     return result ~ "}\n private "~T.stringof~" bitFields;\n";
     42 }
     43 
     44 ///
     45 unittest
     46 {
     47     static struct B
     48     {
     49         bool x;
     50         bool y;
     51         bool z;
     52     }
     53 
     54     static struct S
     55     {
     56         mixin(generateBitFields!(B, ubyte));
     57     }
     58 
     59     S s;
     60     assert(!s.x);
     61     s.x = true;
     62     assert(s.x);
     63     s.x = false;
     64     assert(!s.x);
     65 
     66     s.y = true;
     67     assert(s.y);
     68     assert(!s.x);
     69     assert(!s.z);
     70 }
     71