d: Merge dmd, druntime d8e3976a58, phobos 7a6e95688
[official-gcc.git] / gcc / d / dmd / common / bitfields.d
blob01aa56d1809e663dd12adc5df133d54ecd04596f
1 /**
2 * A library bitfields utility
4 * Copyright: Copyright (C) 1999-2024 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
11 module dmd.common.bitfields;
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
20 extern (D) string generateBitFields(S, T)()
21 if (__traits(isUnsigned, T))
23 string result = "extern (C++) pure nothrow @nogc @safe final {";
24 enum structName = __traits(identifier, S);
26 string initialValue = "";
27 foreach (size_t i, mem; __traits(allMembers, S))
29 static assert(is(typeof(__traits(getMember, S, mem)) == bool));
30 static assert(i < T.sizeof * 8, "too many fields for bit field storage of type `"~T.stringof~"`");
31 enum mask = "(1 << "~i.stringof~")";
32 result ~= "
33 /// set or get the corresponding "~structName~" member
34 bool "~mem~"() const scope { return !!(bitFields & "~mask~"); }
35 /// ditto
36 bool "~mem~"(bool v)
38 v ? (bitFields |= "~mask~") : (bitFields &= ~"~mask~");
39 return v;
40 }";
42 initialValue = (__traits(getMember, S.init, mem) ? "1" : "0") ~ initialValue;
44 return result ~ "}\n private "~T.stringof~" bitFields = 0b" ~ initialValue ~ ";\n";
47 ///
48 unittest
50 static struct B
52 bool x;
53 bool y;
54 bool z = 1;
57 static struct S
59 mixin(generateBitFields!(B, ubyte));
62 S s;
63 assert(!s.x);
64 s.x = true;
65 assert(s.x);
66 s.x = false;
67 assert(!s.x);
69 s.y = true;
70 assert(s.y);
71 assert(!s.x);
72 assert(s.z);