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