std.bitmanip
Bit-level manipulation facilities.
Category | Functions |
---|---|
Bit constructs | BitArray bitfields bitsSet |
Endianness conversion | bigEndianToNative littleEndianToNative nativeToBigEndian nativeToLittleEndian swapEndian |
Integral ranges | append peek read write |
Floating-Point manipulation | DoubleRep FloatRep |
Tagging | taggedClassRef taggedPointer |
- License:
- Boost License 1.0.
- Authors:
- Walter Bright, Andrei Alexandrescu, Jonathan M Davis, Alex Rønne Petersen, Damian Ziemba, Amaury SECHET
- Source
- std/bitmanip.d
- template bitfields(T...)
-
Allows creating bit fields inside structs and classes.
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.
- See Also:
std.typecons.BitFlags
- Examples:
- Create 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.
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; writeln(obj.x); // 2 writeln(obj.y); // 0 writeln(obj.z); // 2 writeln(obj.flag); // false
- Examples:
- 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.
struct A { mixin(bitfields!( bool, "flag1", 1, bool, "flag2", 1, uint, "", 6)); } A a; writeln(a.flag1); // 0 a.flag1 = 1; writeln(a.flag1); // 1 a.flag1 = 0; writeln(a.flag1); // 0
- Examples:
- enums can be used too
enum ABC { A, B, C } struct EnumTest { mixin(bitfields!( ABC, "x", 2, bool, "y", 1, ubyte, "z", 5)); }
- 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 typeuint*
as specified by the first argument, and is named x, as specified by the second argument.
Following arguments works the same way asbitfield
'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 astaggedPointer
, 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;
- struct FloatRep;
-
Allows manipulating the fraction, exponent, and sign parts of a float separately. The definition is:
struct FloatRep { union { float value; mixin(bitfields!( uint, "fraction", 23, ubyte, "exponent", 8, bool, "sign", 1)); } enum uint bias = 127, fractionBits = 23, exponentBits = 8, signBits = 1; }
- Examples:
-
FloatRep rep = {value: 0}; writeln(rep.fraction); // 0 writeln(rep.exponent); // 0 assert(!rep.sign); rep.value = 42; writeln(rep.fraction); // 2621440 writeln(rep.exponent); // 132 assert(!rep.sign); rep.value = 10; writeln(rep.fraction); // 2097152 writeln(rep.exponent); // 130
- Examples:
-
FloatRep rep = {value: 1}; writeln(rep.fraction); // 0 writeln(rep.exponent); // 127 assert(!rep.sign); rep.exponent = 126; writeln(rep.value); // 0.5 rep.exponent = 130; writeln(rep.value); // 8
- Examples:
-
FloatRep rep = {value: 1}; rep.value = -0.5; writeln(rep.fraction); // 0 writeln(rep.exponent); // 126 assert(rep.sign); rep.value = -1. / 3; writeln(rep.fraction); // 2796203 writeln(rep.exponent); // 125 assert(rep.sign);
- struct DoubleRep;
-
Allows manipulating the fraction, exponent, and sign parts of a double separately. The definition is:
struct DoubleRep { union { double value; mixin(bitfields!( ulong, "fraction", 52, ushort, "exponent", 11, bool, "sign", 1)); } enum uint bias = 1023, signBits = 1, fractionBits = 52, exponentBits = 11; }
- Examples:
-
DoubleRep rep = {value: 0}; writeln(rep.fraction); // 0 writeln(rep.exponent); // 0 assert(!rep.sign); rep.value = 42; writeln(rep.fraction); // 1407374883553280 writeln(rep.exponent); // 1028 assert(!rep.sign); rep.value = 10; writeln(rep.fraction); // 1125899906842624 writeln(rep.exponent); // 1026
- Examples:
-
DoubleRep rep = {value: 1}; writeln(rep.fraction); // 0 writeln(rep.exponent); // 1023 assert(!rep.sign); rep.exponent = 1022; writeln(rep.value); // 0.5 rep.exponent = 1026; writeln(rep.value); // 8
- Examples:
-
DoubleRep rep = {value: 1}; rep.value = -0.5; writeln(rep.fraction); // 0 writeln(rep.exponent); // 1022 assert(rep.sign); rep.value = -1. / 3; writeln(rep.fraction); // 1501199875790165 writeln(rep.exponent); // 1021 assert(rep.sign);
- Examples:
- Reading
DoubleRep x; x.value = 1.0; assert(x.fraction == 0 && x.exponent == 1023 && !x.sign); x.value = -0.5; assert(x.fraction == 0 && x.exponent == 1022 && x.sign); x.value = 0.5; assert(x.fraction == 0 && x.exponent == 1022 && !x.sign);
- Examples:
- Writing
DoubleRep x; x.fraction = 1125899906842624; x.exponent = 1025; x.sign = true; writeln(x.value); // -5.0
- struct BitArray;
-
A dynamic array of bits. Each bit in a
BitArray
can be manipulated individually or by the standard bitwise operators&
,|
,^
,~
,>>
,<<
and also by other effective member functions; most of them work relative to theBitArray
's dimension (seedim
), instead of itslength
.- Examples:
- Slicing & bitsSet
import std.algorithm.comparison : equal; import std.range : iota; bool[] buf = new bool[64 * 3]; buf[0 .. 64] = true; BitArray b = BitArray(buf); assert(b.bitsSet.equal(iota(0, 64))); b <<= 64; assert(b.bitsSet.equal(iota(64, 128)));
- Examples:
- Concatenation and appending
import std.algorithm.comparison : equal; auto b = BitArray([1, 0]); b ~= true; writeln(b[2]); // 1 b ~= BitArray([0, 1]); auto c = BitArray([1, 0, 1, 0, 1]); writeln(b); // c assert(b.bitsSet.equal([0, 2, 4]));
- Examples:
- Bit flipping
import std.algorithm.comparison : equal; auto b = BitArray([1, 1, 0, 1]); b &= BitArray([0, 1, 1, 0]); assert(b.bitsSet.equal([1])); b.flip; assert(b.bitsSet.equal([0, 2, 3]));
- Examples:
- String format of bitarrays
import std.format : format; auto b = BitArray([1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1]); writeln(format("%b", b)); // "1_00001111_00001111"
- Examples:
-
import std.format : format; BitArray b; b = BitArray([]); writeln(format("%s", b)); // "[]" assert(format("%b", b) is null); b = BitArray([1]); writeln(format("%s", b)); // "[1]" writeln(format("%b", b)); // "1" b = BitArray([0, 0, 0, 0]); writeln(format("%b", b)); // "0000" b = BitArray([0, 0, 0, 0, 1, 1, 1, 1]); writeln(format("%s", b)); // "[0, 0, 0, 0, 1, 1, 1, 1]" writeln(format("%b", b)); // "00001111" b = BitArray([0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1]); writeln(format("%s", b)); // "[0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1]" writeln(format("%b", b)); // "00001111_00001111" b = BitArray([1, 0, 0, 0, 0, 1, 1, 1, 1]); writeln(format("%b", b)); // "1_00001111" b = BitArray([1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1]); writeln(format("%b", b)); // "1_00001111_00001111"
- pure nothrow this(in bool[] ba);
-
Creates a
BitArray
from abool
array, such thatbool
values read from left to right correspond to subsequent bits in theBitArray
.- Parameters:
bool[] ba
Source array of bool
values.
- Examples:
-
import std.algorithm.comparison : equal; bool[] input = [true, false, false, true, true]; auto a = BitArray(input); writeln(a.length); // 5 assert(a.bitsSet.equal([0, 3, 4])); // This also works because an implicit cast to bool[] occurs for this array. auto b = BitArray([0, 0, 1]); writeln(b.length); // 3 assert(b.bitsSet.equal([2]));
- Examples:
-
import std.algorithm.comparison : equal; import std.array : array; import std.range : iota, repeat; BitArray a = true.repeat(70).array; writeln(a.length); // 70 assert(a.bitsSet.equal(iota(0, 70)));
- pure nothrow @nogc this(void[] v, size_t numbits);
-
Creates a
BitArray
from the raw contents of the source array. The source array is not copied but simply acts as the underlying array of bits, which stores data assize_t
units.That means a particular care should be taken when passing an array of a type different than
size_t
, firstly because its length should be a multiple ofsize_t.sizeof
, and secondly because how the bits are mapped:size_t[] source = [1, 2, 3, 3424234, 724398, 230947, 389492]; enum sbits = size_t.sizeof * 8; auto ba = BitArray(source, source.length * sbits); foreach (n; 0 .. source.length * sbits) { auto nth_bit = cast(bool) (source[n / sbits] & (1L << (n % sbits))); assert(ba[n] == nth_bit); }
The least significant bit in anysize_t
unit is the starting bit of this unit, and the most significant bit is the last bit of this unit. Therefore, passing e.g. an array ofint
s may result in a differentBitArray
depending on the processor's endianness.
This constructor is the inverse ofopCast
.- Parameters:
void[] v
Source array. v.length
must be a multple ofsize_t.sizeof
.size_t numbits
Number of bits to be mapped from the source array, i.e. length of the created BitArray
.
- Examples:
-
import std.algorithm.comparison : equal; auto a = BitArray([1, 0, 0, 1, 1]); // Inverse of the cast. auto v = cast(void[]) a; auto b = BitArray(v, a.length); writeln(b.length); // 5 assert(b.bitsSet.equal([0, 3, 4])); // a and b share the underlying data. a[0] = 0; writeln(b[0]); // 0 writeln(a); // b
- Examples:
-
import std.algorithm.comparison : equal; size_t[] source = [0b1100, 0b0011]; enum sbits = size_t.sizeof * 8; auto ba = BitArray(source, source.length * sbits); // The least significant bit in each unit is this unit's starting bit. assert(ba.bitsSet.equal([2, 3, sbits, sbits + 1]));
- Examples:
-
// Example from the doc for this constructor. static immutable size_t[] sourceData = [1, 0b101, 3, 3424234, 724398, 230947, 389492]; size_t[] source = sourceData.dup; enum sbits = size_t.sizeof * 8; auto ba = BitArray(source, source.length * sbits); foreach (n; 0 .. source.length * sbits) { auto nth_bit = cast(bool) (source[n / sbits] & (1L << (n % sbits))); writeln(ba[n]); // nth_bit } // Example of mapping only part of the array. import std.algorithm.comparison : equal; auto bc = BitArray(source, sbits + 1); assert(bc.bitsSet.equal([0, sbits])); // Source array has not been modified. writeln(source); // sourceData
- const pure nothrow @nogc @property @safe size_t dim();
-
- Returns:
- Dimension i.e. the number of native words backing this
BitArray
. Technically, this is the length of the underlying array storing bits, which is equal toceil(length / (size_t.sizeof * 8))
, as bits are packed intosize_t
units.
- const pure nothrow @nogc @property @safe size_t length();
-
- Returns:
- Number of bits in the
BitArray
.
- pure nothrow @property @system size_t length(size_t newlen);
-
Sets the amount of bits in the
BitArray
. Warning: increasing length may overwrite bits in the final word of the current underlying data regardless of whether it is shared between BitArray objects. i.e. D dynamic array extension semantics are not followed. - const pure nothrow @nogc bool opIndex(size_t i);
-
Gets the
i
'th bit in theBitArray
.- Examples:
-
static void fun(const BitArray arr) { auto x = arr[0]; writeln(x); // 1 } BitArray a; a.length = 3; a[0] = 1; fun(a);
- pure nothrow @nogc bool opIndexAssign(bool b, size_t i);
-
Sets the
i
'th bit in theBitArray
. - pure nothrow @nogc void opSliceAssign(bool val);
-
Sets all the values in the
BitArray
to the value specified byval
.- Examples:
-
import std.algorithm.comparison : equal; auto b = BitArray([1, 0, 1, 0, 1, 1]); b[] = true; // all bits are set assert(b.bitsSet.equal([0, 1, 2, 3, 4, 5])); b[] = false; // none of the bits are set assert(b.bitsSet.empty);
- pure nothrow @nogc void opSliceAssign(bool val, size_t start, size_t end);
-
Sets the bits of a slice of
BitArray
starting at indexstart
and ends at index ($D end - 1) with the values specified byval
.- Examples:
-
import std.algorithm.comparison : equal; import std.range : iota; import std.stdio; auto b = BitArray([1, 0, 0, 0, 1, 1, 0]); b[1 .. 3] = true; assert(b.bitsSet.equal([0, 1, 2, 4, 5])); bool[72] bitArray; auto b1 = BitArray(bitArray); b1[63 .. 67] = true; assert(b1.bitsSet.equal([63, 64, 65, 66])); b1[63 .. 67] = false; assert(b1.bitsSet.empty); b1[0 .. 64] = true; assert(b1.bitsSet.equal(iota(0, 64))); b1[0 .. 64] = false; assert(b1.bitsSet.empty); bool[256] bitArray2; auto b2 = BitArray(bitArray2); b2[3 .. 245] = true; assert(b2.bitsSet.equal(iota(3, 245))); b2[3 .. 245] = false; assert(b2.bitsSet.empty);
- pure nothrow @nogc void flip();
-
Flips all the bits in the
BitArray
- Examples:
-
import std.algorithm.comparison : equal; import std.range : iota; // positions 0, 2, 4 are set auto b = BitArray([1, 0, 1, 0, 1, 0]); b.flip(); // after flipping, positions 1, 3, 5 are set assert(b.bitsSet.equal([1, 3, 5])); bool[270] bits; auto b1 = BitArray(bits); b1.flip(); assert(b1.bitsSet.equal(iota(0, 270)));
- pure nothrow @nogc void flip(size_t i);
-
Flips a single bit, specified by
pos
- Examples:
-
auto ax = BitArray([1, 0, 0, 1]); ax.flip(0); writeln(ax[0]); // 0 bool[200] y; y[90 .. 130] = true; auto ay = BitArray(y); ay.flip(100); writeln(ay[100]); // 0
- const pure nothrow @nogc size_t count();
-
Counts all the set bits in the
BitArray
- Examples:
-
auto a = BitArray([0, 1, 1, 0, 0, 1, 1]); writeln(a.count); // 4 BitArray b; writeln(b.count); // 0 bool[200] boolArray; boolArray[45 .. 130] = true; auto c = BitArray(boolArray); writeln(c.count); // 85
- const pure nothrow @property BitArray dup();
-
Duplicates the
BitArray
and its contents.- Examples:
-
BitArray a; BitArray b; a.length = 3; a[0] = 1; a[1] = 0; a[2] = 1; b = a.dup; writeln(b.length); // 3 foreach (i; 0 .. 3) writeln(b[i]); // (((i ^ 1) & 1) ? true : false)
- int opApply(scope int delegate(ref bool) dg);
const int opApply(scope int delegate(bool) dg);
int opApply(scope int delegate(size_t, ref bool) dg);
const int opApply(scope int delegate(size_t, bool) dg); -
Support for
foreach
loops forBitArray
.- Examples:
-
bool[] ba = [1,0,1]; auto a = BitArray(ba); int i; foreach (b;a) { switch (i) { case 0: assert(b == true); break; case 1: assert(b == false); break; case 2: assert(b == true); break; default: assert(0); } i++; } foreach (j,b;a) { switch (j) { case 0: assert(b == true); break; case 1: assert(b == false); break; case 2: assert(b == true); break; default: assert(0); } }
- pure nothrow @nogc @property BitArray reverse();
-
Reverses the bits of the
BitArray
.- Examples:
-
BitArray b; bool[5] data = [1,0,1,1,0]; b = BitArray(data); b.reverse; foreach (i; 0 .. data.length) writeln(b[i]); // data[4 - i]
- pure nothrow @nogc @property BitArray sort();
-
Sorts the
BitArray
's elements.- Examples:
-
size_t x = 0b1100011000; auto ba = BitArray(10, &x); ba.sort; foreach (i; 0 .. 6) writeln(ba[i]); // false foreach (i; 6 .. 10) writeln(ba[i]); // true
- const pure nothrow @nogc bool opEquals(ref const BitArray a2);
-
Support for operators == and != for
BitArray
.- Examples:
-
bool[] ba = [1,0,1,0,1]; bool[] bb = [1,0,1]; bool[] bc = [1,0,1,0,1,0,1]; bool[] bd = [1,0,1,1,1]; bool[] be = [1,0,1,0,1]; bool[] bf = [1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]; bool[] bg = [1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1]; auto a = BitArray(ba); auto b = BitArray(bb); auto c = BitArray(bc); auto d = BitArray(bd); auto e = BitArray(be); auto f = BitArray(bf); auto g = BitArray(bg); assert(a != b); assert(a != c); assert(a != d); writeln(a); // e assert(f != g);
- const pure nothrow @nogc int opCmp(BitArray a2);
-
Supports comparison operators for
BitArray
.- Examples:
-
bool[] ba = [1,0,1,0,1]; bool[] bb = [1,0,1]; bool[] bc = [1,0,1,0,1,0,1]; bool[] bd = [1,0,1,1,1]; bool[] be = [1,0,1,0,1]; bool[] bf = [1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1]; bool[] bg = [1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0]; auto a = BitArray(ba); auto b = BitArray(bb); auto c = BitArray(bc); auto d = BitArray(bd); auto e = BitArray(be); auto f = BitArray(bf); auto g = BitArray(bg); assert(a > b); assert(a >= b); assert(a < c); assert(a <= c); assert(a < d); assert(a <= d); writeln(a); // e assert(a <= e); assert(a >= e); assert(f < g); assert(g <= g);
- const pure nothrow @nogc size_t toHash();
-
Support for hashing for
BitArray
. - inout pure nothrow @nogc inout(void)[] opCast(T : const(void[]))();
-
Convert to
void[]
. - inout pure nothrow @nogc inout(size_t)[] opCast(T : const(size_t[]))();
-
Convert to
size_t[]
.- Examples:
-
import std.array : array; import std.range : repeat, take; // bit array with 300 elements auto a = BitArray(true.repeat.take(300).array); size_t[] v = cast(size_t[]) a; const blockSize = size_t.sizeof * 8; writeln(v.length); // (a.length + blockSize - 1) / blockSize
- const pure nothrow BitArray opUnary(string op)()
Constraints: if (op == "~"); -
Support for unary operator ~ for
BitArray
.- Examples:
-
bool[] ba = [1,0,1,0,1]; auto a = BitArray(ba); BitArray b = ~a; writeln(b[0]); // 0 writeln(b[1]); // 1 writeln(b[2]); // 0 writeln(b[3]); // 1 writeln(b[4]); // 0
- const pure nothrow BitArray opBinary(string op)(const BitArray e2)
Constraints: if (op == "-" || op == "&" || op == "|" || op == "^"); -
Support for binary bitwise operators for
BitArray
.- Examples:
-
static bool[] ba = [1,0,1,0,1]; static bool[] bb = [1,0,1,1,0]; auto a = BitArray(ba); auto b = BitArray(bb); BitArray c = a & b; writeln(c[0]); // 1 writeln(c[1]); // 0 writeln(c[2]); // 1 writeln(c[3]); // 0 writeln(c[4]); // 0
- Examples:
-
bool[] ba = [1,0,1,0,1]; bool[] bb = [1,0,1,1,0]; auto a = BitArray(ba); auto b = BitArray(bb); BitArray c = a | b; writeln(c[0]); // 1 writeln(c[1]); // 0 writeln(c[2]); // 1 writeln(c[3]); // 1 writeln(c[4]); // 1
- Examples:
-
bool[] ba = [1,0,1,0,1]; bool[] bb = [1,0,1,1,0]; auto a = BitArray(ba); auto b = BitArray(bb); BitArray c = a ^ b; writeln(c[0]); // 0 writeln(c[1]); // 0 writeln(c[2]); // 0 writeln(c[3]); // 1 writeln(c[4]); // 1
- Examples:
-
bool[] ba = [1,0,1,0,1]; bool[] bb = [1,0,1,1,0]; auto a = BitArray(ba); auto b = BitArray(bb); BitArray c = a - b; writeln(c[0]); // 0 writeln(c[1]); // 0 writeln(c[2]); // 0 writeln(c[3]); // 0 writeln(c[4]); // 1
- pure nothrow @nogc BitArray opOpAssign(string op)(const BitArray e2)
Constraints: if (op == "-" || op == "&" || op == "|" || op == "^"); -
Support for operator op= for
BitArray
.- Examples:
-
bool[] ba = [1,0,1,0,1,1,0,1,0,1]; bool[] bb = [1,0,1,1,0]; auto a = BitArray(ba); auto b = BitArray(bb); BitArray c = a; c.length = 5; c &= b; writeln(a[5]); // 1 writeln(a[6]); // 0 writeln(a[7]); // 1 writeln(a[8]); // 0 writeln(a[9]); // 1
- Examples:
-
bool[] ba = [1,0,1,0,1]; bool[] bb = [1,0,1,1,0]; auto a = BitArray(ba); auto b = BitArray(bb); a &= b; writeln(a[0]); // 1 writeln(a[1]); // 0 writeln(a[2]); // 1 writeln(a[3]); // 0 writeln(a[4]); // 0
- Examples:
-
bool[] ba = [1,0,1,0,1]; bool[] bb = [1,0,1,1,0]; auto a = BitArray(ba); auto b = BitArray(bb); a |= b; writeln(a[0]); // 1 writeln(a[1]); // 0 writeln(a[2]); // 1 writeln(a[3]); // 1 writeln(a[4]); // 1
- Examples:
-
bool[] ba = [1,0,1,0,1]; bool[] bb = [1,0,1,1,0]; auto a = BitArray(ba); auto b = BitArray(bb); a ^= b; writeln(a[0]); // 0 writeln(a[1]); // 0 writeln(a[2]); // 0 writeln(a[3]); // 1 writeln(a[4]); // 1
- Examples:
-
bool[] ba = [1,0,1,0,1]; bool[] bb = [1,0,1,1,0]; auto a = BitArray(ba); auto b = BitArray(bb); a -= b; writeln(a[0]); // 0 writeln(a[1]); // 0 writeln(a[2]); // 0 writeln(a[3]); // 0 writeln(a[4]); // 1
- pure nothrow BitArray opOpAssign(string op)(bool b)
Constraints: if (op == "~");
pure nothrow BitArray opOpAssign(string op)(BitArray b)
Constraints: if (op == "~"); -
Support for operator ~= for
BitArray
. Warning: This will overwrite a bit in the final word of the current underlying data regardless of whether it is shared between BitArray objects. i.e. D dynamic array concatenation semantics are not followed- Examples:
-
bool[] ba = [1,0,1,0,1]; auto a = BitArray(ba); BitArray b; b = (a ~= true); writeln(a[0]); // 1 writeln(a[1]); // 0 writeln(a[2]); // 1 writeln(a[3]); // 0 writeln(a[4]); // 1 writeln(a[5]); // 1 writeln(b); // a
- Examples:
-
bool[] ba = [1,0]; bool[] bb = [0,1,0]; auto a = BitArray(ba); auto b = BitArray(bb); BitArray c; c = (a ~= b); writeln(a.length); // 5 writeln(a[0]); // 1 writeln(a[1]); // 0 writeln(a[2]); // 0 writeln(a[3]); // 1 writeln(a[4]); // 0 writeln(c); // a
- const pure nothrow BitArray opBinary(string op)(bool b)
Constraints: if (op == "~");
const pure nothrow BitArray opBinaryRight(string op)(bool b)
Constraints: if (op == "~");
const pure nothrow BitArray opBinary(string op)(BitArray b)
Constraints: if (op == "~"); -
Support for binary operator ~ for
BitArray
.- Examples:
-
bool[] ba = [1,0]; bool[] bb = [0,1,0]; auto a = BitArray(ba); auto b = BitArray(bb); BitArray c; c = (a ~ b); writeln(c.length); // 5 writeln(c[0]); // 1 writeln(c[1]); // 0 writeln(c[2]); // 0 writeln(c[3]); // 1 writeln(c[4]); // 0 c = (a ~ true); writeln(c.length); // 3 writeln(c[0]); // 1 writeln(c[1]); // 0 writeln(c[2]); // 1 c = (false ~ a); writeln(c.length); // 3 writeln(c[0]); // 0 writeln(c[1]); // 1 writeln(c[2]); // 0
- pure nothrow @nogc void opOpAssign(string op)(size_t nbits)
Constraints: if (op == "<<"); -
Operator
<<=
support.Shifts all the bits in the array to the left by the given number of bits. The leftmost bits are dropped, and 0's are appended to the end to fill up the vacant bits.
Warning: unused bits in the final word up to the next word boundary may be overwritten by this operation. It does not attempt to preserve bits past the end of the array. - pure nothrow @nogc void opOpAssign(string op)(size_t nbits)
Constraints: if (op == ">>"); -
Operator
>>=
support.Shifts all the bits in the array to the right by the given number of bits. The rightmost bits are dropped, and 0's are inserted at the back to fill up the vacant bits.
Warning: unused bits in the final word up to the next word boundary may be overwritten by this operation. It does not attempt to preserve bits past the end of the array.- Examples:
-
import std.format : format; auto b = BitArray([1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1]); b <<= 1; writeln(format("%b", b)); // "01100_10101101" b >>= 1; writeln(format("%b", b)); // "11001_01011010" b <<= 4; writeln(format("%b", b)); // "00001_10010101" b >>= 5; writeln(format("%b", b)); // "10010_10100000" b <<= 13; writeln(format("%b", b)); // "00000_00000000" b = BitArray([1, 0, 1, 1, 0, 1, 1, 1]); b >>= 8; writeln(format("%b", b)); // "00000000"
- const void toString(W)(ref W sink, ref scope const FormatSpec!char fmt)
Constraints: if (isOutputRange!(W, char)); -
Return a string representation of this BitArray.
Two format specifiers are supported:
- %s which prints the bits as an array, and
- %b which prints the bits as 8-bit byte packets
separated with an underscore.- Parameters:
W sink
A char
accepting output range.FormatSpec!char fmt
A std.format.FormatSpec
which controls how the data is displayed.
- Examples:
-
import std.format : format; auto b = BitArray([0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1]); auto s1 = format("%s", b); writeln(s1); // "[0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1]" auto s2 = format("%b", b); writeln(s2); // "00001111_00001111"
- const nothrow @property auto bitsSet();
-
Return a lazy range of the indices of set bits.
- Examples:
-
import std.algorithm.comparison : equal; auto b1 = BitArray([0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1]); assert(b1.bitsSet.equal([4, 5, 6, 7, 12, 13, 14, 15])); BitArray b2; b2.length = 1000; b2[333] = true; b2[666] = true; b2[999] = true; assert(b2.bitsSet.equal([333, 666, 999]));
- pure nothrow @nogc @safe T swapEndian(T)(const T val)
Constraints: if (isIntegral!T || isSomeChar!T || isBoolean!T); -
Swaps the endianness of the given integral value or character.
- Examples:
-
writeln(42.swapEndian); // 704643072 assert(42.swapEndian.swapEndian == 42); // reflexive writeln(1.swapEndian); // 16777216 writeln(true.swapEndian); // true writeln(byte(10).swapEndian); // 10 writeln(char(10).swapEndian); // 10 writeln(ushort(10).swapEndian); // 2560 writeln(long(10).swapEndian); // 720575940379279360 writeln(ulong(10).swapEndian); // 720575940379279360
- pure nothrow @nogc @safe auto nativeToBigEndian(T)(const T val)
Constraints: if (canSwapEndianness!T); -
Converts the given value from the native endianness to big endian and returns it as a
ubyte[n]
wheren
is the size of the given type.Returning a
ubyte[n]
helps prevent accidentally using a swapped value as a regular one (and in the case of floating point values, it's necessary, because the FPU will mess up any swapped floating point values. So, you can't actually have swapped floating point values as floating point values).
real
is not supported, because its size is implementation-dependent and therefore could vary from machine to machine (which could make it unusable if you tried to transfer it to another machine).- Examples:
-
int i = 12345; ubyte[4] swappedI = nativeToBigEndian(i); writeln(i); // bigEndianToNative!int(swappedI) float f = 123.45f; ubyte[4] swappedF = nativeToBigEndian(f); writeln(f); // bigEndianToNative!float(swappedF) const float cf = 123.45f; ubyte[4] swappedCF = nativeToBigEndian(cf); writeln(cf); // bigEndianToNative!float(swappedCF) double d = 123.45; ubyte[8] swappedD = nativeToBigEndian(d); writeln(d); // bigEndianToNative!double(swappedD) const double cd = 123.45; ubyte[8] swappedCD = nativeToBigEndian(cd); writeln(cd); // bigEndianToNative!double(swappedCD)
- pure nothrow @nogc @safe T bigEndianToNative(T, size_t n)(ubyte[n] val)
Constraints: if (canSwapEndianness!T && (n == T.sizeof)); -
Converts the given value from big endian to the native endianness and returns it. The value is given as a
ubyte[n]
wheren
is the size of the target type. You must give the target type as a template argument, because there are multiple types with the same size and so the type of the argument is not enough to determine the return type.Taking a
ubyte[n]
helps prevent accidentally using a swapped value as a regular one (and in the case of floating point values, it's necessary, because the FPU will mess up any swapped floating point values. So, you can't actually have swapped floating point values as floating point values).- Examples:
-
ushort i = 12345; ubyte[2] swappedI = nativeToBigEndian(i); writeln(i); // bigEndianToNative!ushort(swappedI) dchar c = 'D'; ubyte[4] swappedC = nativeToBigEndian(c); writeln(c); // bigEndianToNative!dchar(swappedC)
- pure nothrow @nogc @safe auto nativeToLittleEndian(T)(const T val)
Constraints: if (canSwapEndianness!T); -
Converts the given value from the native endianness to little endian and returns it as a
ubyte[n]
wheren
is the size of the given type.Returning a
ubyte[n]
helps prevent accidentally using a swapped value as a regular one (and in the case of floating point values, it's necessary, because the FPU will mess up any swapped floating point values. So, you can't actually have swapped floating point values as floating point values).- Examples:
-
int i = 12345; ubyte[4] swappedI = nativeToLittleEndian(i); writeln(i); // littleEndianToNative!int(swappedI) double d = 123.45; ubyte[8] swappedD = nativeToLittleEndian(d); writeln(d); // littleEndianToNative!double(swappedD)
- pure nothrow @nogc @safe T littleEndianToNative(T, size_t n)(ubyte[n] val)
Constraints: if (canSwapEndianness!T && (n == T.sizeof)); -
Converts the given value from little endian to the native endianness and returns it. The value is given as a
ubyte[n]
wheren
is the size of the target type. You must give the target type as a template argument, because there are multiple types with the same size and so the type of the argument is not enough to determine the return type.Taking a
ubyte[n]
helps prevent accidentally using a swapped value as a regular one (and in the case of floating point values, it's necessary, because the FPU will mess up any swapped floating point values. So, you can't actually have swapped floating point values as floating point values).
real
is not supported, because its size is implementation-dependent and therefore could vary from machine to machine (which could make it unusable if you tried to transfer it to another machine).- Examples:
-
ushort i = 12345; ubyte[2] swappedI = nativeToLittleEndian(i); writeln(i); // littleEndianToNative!ushort(swappedI) dchar c = 'D'; ubyte[4] swappedC = nativeToLittleEndian(c); writeln(c); // littleEndianToNative!dchar(swappedC)
- T peek(T, Endian endianness = Endian.bigEndian, R)(R range)
Constraints: if (canSwapEndianness!T && isForwardRange!R && is(ElementType!R : const(ubyte)));
T peek(T, Endian endianness = Endian.bigEndian, R)(R range, size_t index)
Constraints: if (canSwapEndianness!T && isForwardRange!R && hasSlicing!R && is(ElementType!R : const(ubyte)));
T peek(T, Endian endianness = Endian.bigEndian, R)(R range, size_t* index)
Constraints: if (canSwapEndianness!T && isForwardRange!R && hasSlicing!R && is(ElementType!R : const(ubyte))); -
Takes a range of
ubyte
s and converts the firstT.sizeof
bytes toT
. The value returned is converted from the given endianness to the native endianness. The range is not consumed.- Parameters:
T The integral type to convert the first T.sizeof
bytes to.endianness The endianness that the bytes are assumed to be in. R range
The range to read from. size_t index
The index to start reading from (instead of starting at the front). If index is a pointer, then it is updated to the index after the bytes read. The overloads with index are only available if hasSlicing!R
istrue
.
- Examples:
-
ubyte[] buffer = [1, 5, 22, 9, 44, 255, 8]; writeln(buffer.peek!uint()); // 17110537 writeln(buffer.peek!ushort()); // 261 writeln(buffer.peek!ubyte()); // 1 writeln(buffer.peek!uint(2)); // 369700095 writeln(buffer.peek!ushort(2)); // 5641 writeln(buffer.peek!ubyte(2)); // 22 size_t index = 0; writeln(buffer.peek!ushort(&index)); // 261 writeln(index); // 2 writeln(buffer.peek!uint(&index)); // 369700095 writeln(index); // 6 writeln(buffer.peek!ubyte(&index)); // 8 writeln(index); // 7
- Examples:
-
import std.algorithm.iteration : filter; ubyte[] buffer = [1, 5, 22, 9, 44, 255, 7]; auto range = filter!"true"(buffer); writeln(range.peek!uint()); // 17110537 writeln(range.peek!ushort()); // 261 writeln(range.peek!ubyte()); // 1
- T read(T, Endian endianness = Endian.bigEndian, R)(ref R range)
Constraints: if (canSwapEndianness!T && isInputRange!R && is(ElementType!R : const(ubyte))); -
Takes a range of
ubyte
s and converts the firstT.sizeof
bytes toT
. The value returned is converted from the given endianness to the native endianness. TheT.sizeof
bytes which are read are consumed from the range.- Parameters:
T The integral type to convert the first T.sizeof
bytes to.endianness The endianness that the bytes are assumed to be in. R range
The range to read from.
- Examples:
-
import std.range.primitives : empty; ubyte[] buffer = [1, 5, 22, 9, 44, 255, 8]; writeln(buffer.length); // 7 writeln(buffer.read!ushort()); // 261 writeln(buffer.length); // 5 writeln(buffer.read!uint()); // 369700095 writeln(buffer.length); // 1 writeln(buffer.read!ubyte()); // 8 assert(buffer.empty);
- void write(T, Endian endianness = Endian.bigEndian, R)(R range, const T value, size_t index)
Constraints: if (canSwapEndianness!T && isForwardRange!R && hasSlicing!R && is(ElementType!R : ubyte));
void write(T, Endian endianness = Endian.bigEndian, R)(R range, const T value, size_t* index)
Constraints: if (canSwapEndianness!T && isForwardRange!R && hasSlicing!R && is(ElementType!R : ubyte)); -
Takes an integral value, converts it to the given endianness, and writes it to the given range of
ubyte
s as a sequence ofT.sizeof
ubyte
s starting at index.hasSlicing!R
must betrue
.- Parameters:
T The integral type to convert the first T.sizeof
bytes to.endianness The endianness to write the bytes in. R range
The range to write to. T value
The value to write. size_t index
The index to start writing to. If index is a pointer, then it is updated to the index after the bytes read.
- Examples:
-
ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0]; buffer.write!uint(29110231u, 0); writeln(buffer); // [1, 188, 47, 215, 0, 0, 0, 0] buffer.write!ushort(927, 0); writeln(buffer); // [3, 159, 47, 215, 0, 0, 0, 0] buffer.write!ubyte(42, 0); writeln(buffer); // [42, 159, 47, 215, 0, 0, 0, 0]
- Examples:
-
ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0, 0]; buffer.write!uint(142700095u, 2); writeln(buffer); // [0, 0, 8, 129, 110, 63, 0, 0, 0] buffer.write!ushort(19839, 2); writeln(buffer); // [0, 0, 77, 127, 110, 63, 0, 0, 0] buffer.write!ubyte(132, 2); writeln(buffer); // [0, 0, 132, 127, 110, 63, 0, 0, 0]
- Examples:
-
ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0]; size_t index = 0; buffer.write!ushort(261, &index); writeln(buffer); // [1, 5, 0, 0, 0, 0, 0, 0] writeln(index); // 2 buffer.write!uint(369700095u, &index); writeln(buffer); // [1, 5, 22, 9, 44, 255, 0, 0] writeln(index); // 6 buffer.write!ubyte(8, &index); writeln(buffer); // [1, 5, 22, 9, 44, 255, 8, 0] writeln(index); // 7
- Examples:
- bool
ubyte[] buffer = [0, 0]; buffer.write!bool(false, 0); writeln(buffer); // [0, 0] buffer.write!bool(true, 0); writeln(buffer); // [1, 0] buffer.write!bool(true, 1); writeln(buffer); // [1, 1] buffer.write!bool(false, 1); writeln(buffer); // [1, 0] size_t index = 0; buffer.write!bool(false, &index); writeln(buffer); // [0, 0] writeln(index); // 1 buffer.write!bool(true, &index); writeln(buffer); // [0, 1] writeln(index); // 2
- Examples:
- char(8-bit)
ubyte[] buffer = [0, 0, 0]; buffer.write!char('a', 0); writeln(buffer); // [97, 0, 0] buffer.write!char('b', 1); writeln(buffer); // [97, 98, 0] size_t index = 0; buffer.write!char('a', &index); writeln(buffer); // [97, 98, 0] writeln(index); // 1 buffer.write!char('b', &index); writeln(buffer); // [97, 98, 0] writeln(index); // 2 buffer.write!char('c', &index); writeln(buffer); // [97, 98, 99] writeln(index); // 3
- Examples:
- wchar (16bit - 2x ubyte)
ubyte[] buffer = [0, 0, 0, 0]; buffer.write!wchar('ą', 0); writeln(buffer); // [1, 5, 0, 0] buffer.write!wchar('”', 2); writeln(buffer); // [1, 5, 32, 29] size_t index = 0; buffer.write!wchar('ć', &index); writeln(buffer); // [1, 7, 32, 29] writeln(index); // 2 buffer.write!wchar('ą', &index); writeln(buffer); // [1, 7, 1, 5] writeln(index); // 4
- Examples:
- dchar (32bit - 4x ubyte)
ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0]; buffer.write!dchar('ą', 0); writeln(buffer); // [0, 0, 1, 5, 0, 0, 0, 0] buffer.write!dchar('”', 4); writeln(buffer); // [0, 0, 1, 5, 0, 0, 32, 29] size_t index = 0; buffer.write!dchar('ć', &index); writeln(buffer); // [0, 0, 1, 7, 0, 0, 32, 29] writeln(index); // 4 buffer.write!dchar('ą', &index); writeln(buffer); // [0, 0, 1, 7, 0, 0, 1, 5] writeln(index); // 8
- Examples:
- float (32bit - 4x ubyte)
ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0]; buffer.write!float(32.0f, 0); writeln(buffer); // [66, 0, 0, 0, 0, 0, 0, 0] buffer.write!float(25.0f, 4); writeln(buffer); // [66, 0, 0, 0, 65, 200, 0, 0] size_t index = 0; buffer.write!float(25.0f, &index); writeln(buffer); // [65, 200, 0, 0, 65, 200, 0, 0] writeln(index); // 4 buffer.write!float(32.0f, &index); writeln(buffer); // [65, 200, 0, 0, 66, 0, 0, 0] writeln(index); // 8
- Examples:
- double (64bit - 8x ubyte)
ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; buffer.write!double(32.0, 0); writeln(buffer); // [64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] buffer.write!double(25.0, 8); writeln(buffer); // [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0] size_t index = 0; buffer.write!double(25.0, &index); writeln(buffer); // [64, 57, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0] writeln(index); // 8 buffer.write!double(32.0, &index); writeln(buffer); // [64, 57, 0, 0, 0, 0, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0] writeln(index); // 16
- Examples:
- enum
ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; enum Foo { one = 10, two = 20, three = 30 } buffer.write!Foo(Foo.one, 0); writeln(buffer); // [0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0] buffer.write!Foo(Foo.two, 4); writeln(buffer); // [0, 0, 0, 10, 0, 0, 0, 20, 0, 0, 0, 0] buffer.write!Foo(Foo.three, 8); writeln(buffer); // [0, 0, 0, 10, 0, 0, 0, 20, 0, 0, 0, 30] size_t index = 0; buffer.write!Foo(Foo.three, &index); writeln(buffer); // [0, 0, 0, 30, 0, 0, 0, 20, 0, 0, 0, 30] writeln(index); // 4 buffer.write!Foo(Foo.one, &index); writeln(buffer); // [0, 0, 0, 30, 0, 0, 0, 10, 0, 0, 0, 30] writeln(index); // 8 buffer.write!Foo(Foo.two, &index); writeln(buffer); // [0, 0, 0, 30, 0, 0, 0, 10, 0, 0, 0, 20] writeln(index); // 12
- Examples:
- enum - float
ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0]; enum Float: float { one = 32.0f, two = 25.0f } buffer.write!Float(Float.one, 0); writeln(buffer); // [66, 0, 0, 0, 0, 0, 0, 0] buffer.write!Float(Float.two, 4); writeln(buffer); // [66, 0, 0, 0, 65, 200, 0, 0] size_t index = 0; buffer.write!Float(Float.two, &index); writeln(buffer); // [65, 200, 0, 0, 65, 200, 0, 0] writeln(index); // 4 buffer.write!Float(Float.one, &index); writeln(buffer); // [65, 200, 0, 0, 66, 0, 0, 0] writeln(index); // 8
- Examples:
- enum - double
ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; enum Double: double { one = 32.0, two = 25.0 } buffer.write!Double(Double.one, 0); writeln(buffer); // [64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] buffer.write!Double(Double.two, 8); writeln(buffer); // [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0] size_t index = 0; buffer.write!Double(Double.two, &index); writeln(buffer); // [64, 57, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0] writeln(index); // 8 buffer.write!Double(Double.one, &index); writeln(buffer); // [64, 57, 0, 0, 0, 0, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0] writeln(index); // 16
- Examples:
- enum - real
ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; enum Real: real { one = 32.0, two = 25.0 } static assert(!__traits(compiles, buffer.write!Real(Real.one)));
- void append(T, Endian endianness = Endian.bigEndian, R)(R range, const T value)
Constraints: if (canSwapEndianness!T && isOutputRange!(R, ubyte)); -
Takes an integral value, converts it to the given endianness, and appends it to the given range of
ubyte
s (usingput
) as a sequence ofT.sizeof
ubyte
s starting at index.hasSlicing!R
must betrue
.- Parameters:
T The integral type to convert the first T.sizeof
bytes to.endianness The endianness to write the bytes in. R range
The range to append to. T value
The value to append.
- Examples:
-
import std.array; auto buffer = appender!(const ubyte[])(); buffer.append!ushort(261); writeln(buffer.data); // [1, 5] buffer.append!uint(369700095u); writeln(buffer.data); // [1, 5, 22, 9, 44, 255] buffer.append!ubyte(8); writeln(buffer.data); // [1, 5, 22, 9, 44, 255, 8]
- Examples:
- bool
import std.array : appender; auto buffer = appender!(const ubyte[])(); buffer.append!bool(true); writeln(buffer.data); // [1] buffer.append!bool(false); writeln(buffer.data); // [1, 0]
- Examples:
- char wchar dchar
import std.array : appender; auto buffer = appender!(const ubyte[])(); buffer.append!char('a'); writeln(buffer.data); // [97] buffer.append!char('b'); writeln(buffer.data); // [97, 98] buffer.append!wchar('ą'); writeln(buffer.data); // [97, 98, 1, 5] buffer.append!dchar('ą'); writeln(buffer.data); // [97, 98, 1, 5, 0, 0, 1, 5]
- Examples:
- float double
import std.array : appender; auto buffer = appender!(const ubyte[])(); buffer.append!float(32.0f); writeln(buffer.data); // [66, 0, 0, 0] buffer.append!double(32.0); writeln(buffer.data); // [66, 0, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0]
- Examples:
- enum
import std.array : appender; auto buffer = appender!(const ubyte[])(); enum Foo { one = 10, two = 20, three = 30 } buffer.append!Foo(Foo.one); writeln(buffer.data); // [0, 0, 0, 10] buffer.append!Foo(Foo.two); writeln(buffer.data); // [0, 0, 0, 10, 0, 0, 0, 20] buffer.append!Foo(Foo.three); writeln(buffer.data); // [0, 0, 0, 10, 0, 0, 0, 20, 0, 0, 0, 30]
- Examples:
- enum - bool
import std.array : appender; auto buffer = appender!(const ubyte[])(); enum Bool: bool { bfalse = false, btrue = true, } buffer.append!Bool(Bool.btrue); writeln(buffer.data); // [1] buffer.append!Bool(Bool.bfalse); writeln(buffer.data); // [1, 0] buffer.append!Bool(Bool.btrue); writeln(buffer.data); // [1, 0, 1]
- Examples:
- enum - float
import std.array : appender; auto buffer = appender!(const ubyte[])(); enum Float: float { one = 32.0f, two = 25.0f } buffer.append!Float(Float.one); writeln(buffer.data); // [66, 0, 0, 0] buffer.append!Float(Float.two); writeln(buffer.data); // [66, 0, 0, 0, 65, 200, 0, 0]
- Examples:
- enum - double
import std.array : appender; auto buffer = appender!(const ubyte[])(); enum Double: double { one = 32.0, two = 25.0 } buffer.append!Double(Double.one); writeln(buffer.data); // [64, 64, 0, 0, 0, 0, 0, 0] buffer.append!Double(Double.two); writeln(buffer.data); // [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0]
- Examples:
- enum - real
import std.array : appender; auto buffer = appender!(const ubyte[])(); enum Real: real { one = 32.0, two = 25.0 } static assert(!__traits(compiles, buffer.append!Real(Real.one)));
- pure nothrow @nogc auto bitsSet(T)(const T value)
Constraints: if (isIntegral!T); -
Range that iterates the indices of the set bits in
value
. Index 0 corresponds to the least significant bit. For signed integers, the highest index corresponds to the sign bit.- Examples:
-
import std.algorithm.comparison : equal; import std.range : iota; assert(bitsSet(1).equal([0])); assert(bitsSet(5).equal([0, 2])); assert(bitsSet(-1).equal(iota(32))); assert(bitsSet(int.min).equal([31]));
© 1999–2021 The D Language Foundation
Licensed under the Boost License 1.0.
https://dlang.org/phobos/std_bitmanip.html