xref: /netbsd-src/external/gpl3/gcc/dist/gcc/d/dmd/common/bitfields.d (revision b1e838363e3c6fc78a55519254d99869742dd33c)
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 
foreach(size_t i,mem;__traits (allMembers,S))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