/** * A library bitfields utility * * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved * Authors: Dennis Korpel * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/common/bitfields.d, common/bitfields.d) * Documentation: https://dlang.org/phobos/dmd_common_bitfields.html * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/common/bitfields.d */ module dmd.common.bitfields; /** * Generate code for bit fields inside a struct/class body * Params: * S = type of a struct with only boolean fields, which should become bit fields * T = type of bit fields variable, must have enough bits to store all booleans * Returns: D code with a bit fields variable and getter / setter functions */ extern (D) string generateBitFields(S, T)() if (__traits(isUnsigned, T)) { string result = "extern (C++) pure nothrow @nogc @safe final {"; enum structName = __traits(identifier, S); foreach (size_t i, mem; __traits(allMembers, S)) { static assert(is(typeof(__traits(getMember, S, mem)) == bool)); static assert(i < T.sizeof * 8, "too many fields for bit field storage of type `"~T.stringof~"`"); enum mask = "(1 << "~i.stringof~")"; result ~= " /// set or get the corresponding "~structName~" member bool "~mem~"() const { return !!(bitFields & "~mask~"); } /// ditto bool "~mem~"(bool v) { v ? (bitFields |= "~mask~") : (bitFields &= ~"~mask~"); return v; }"; } return result ~ "}\n private "~T.stringof~" bitFields;\n"; } /// unittest { static struct B { bool x; bool y; bool z; } static struct S { mixin(generateBitFields!(B, ubyte)); } S s; assert(!s.x); s.x = true; assert(s.x); s.x = false; assert(!s.x); s.y = true; assert(s.y); assert(!s.x); assert(!s.z); }