Report a bug
If you spot a problem with this page, click here to create a Github issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using a local clone.

mir.bitmanip

Bit-level manipulation facilities.
Category Functions
Bit constructs bitfields
Tagging taggedClassRef taggedPointer
Authors:
template bitfields(T...)
Allows creating bit fields inside structs and classes.

Example:

struct A
{
    int a;
    mixin(bitfields!(
        uint, "x",    2,
        int,  "y",    3,
        uint, "z",    2,
        bool, "flag", 1));
}
A obj;
obj.x = 2;
obj.z = obj.x;
The example above creates a bitfield pack of eight bits, which fit in one ubyte. The bitfields are allocated starting from the least significant bit, i.e. x occupies the two least significant bits of the bitfields storage.
The sum of all bit lengths in one bitfield instantiation must be exactly 8, 16, 32, or 64. If padding is needed, just allocate one bitfield with an empty name.

Example:

struct A
{
    mixin(bitfields!(
        bool, "flag1",    1,
        bool, "flag2",    1,
        uint, "",         6));
}
The type of a bit field can be any integral type or enumerated type. The most efficient type to store in bitfields is bool, followed by unsigned types, followed by signed types.

enum auto taggedPointer(T : T*, string name, Ts...);
This string mixin generator allows one to create tagged pointers inside structs and classes.
A tagged pointer uses the bits known to be zero in a normal pointer or class reference to store extra information. For example, a pointer to an integer must be 4-byte aligned, so there are 2 bits that are always known to be zero. One can store a 2-bit integer there.
The example above creates a tagged pointer in the struct A. The pointer is of type uint* as specified by the first argument, and is named x, as specified by the second argument.
Following arguments works the same way as bitfield's. The bitfield must fit into the bits known to be zero because of the pointer alignment.
Examples:
struct A
{
    int a;
    mixin(taggedPointer!(
        uint*, "x",
        bool, "b1", 1,
        bool, "b2", 1));
}
A obj;
obj.x = new uint;
obj.b1 = true;
obj.b2 = false;
template taggedClassRef(T, string name, Ts...) if (is(T == class))
This string mixin generator allows one to create tagged class reference inside structs and classes.
A tagged class reference uses the bits known to be zero in a normal class reference to store extra information. For example, a pointer to an integer must be 4-byte aligned, so there are 2 bits that are always known to be zero. One can store a 2-bit integer there.
The example above creates a tagged reference to an Object in the struct A. This expects the same parameters as taggedPointer, except the first argument which must be a class type instead of a pointer type.
Examples:
struct A
{
    int a;
    mixin(taggedClassRef!(
        Object, "o",
        uint, "i", 2));
}
A obj;
obj.o = new Object();
obj.i = 3;