1 // Written in the D programming language.
4 Bit-level manipulation facilities.
6 $(SCRIPT inhibitQuickIndex = 1;)
9 $(TR $(TH Category) $(TH Functions))
10 $(TR $(TD Bit constructs) $(TD
15 $(TR $(TD Endianness conversion) $(TD
16 $(LREF bigEndianToNative)
17 $(LREF littleEndianToNative)
18 $(LREF nativeToBigEndian)
19 $(LREF nativeToLittleEndian)
22 $(TR $(TD Integral ranges) $(TD
28 $(TR $(TD Floating-Point manipulation) $(TD
32 $(TR $(TD Tagging) $(TD
33 $(LREF taggedClassRef)
38 Copyright: Copyright The D Language Foundation 2007 - 2011.
39 License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
40 Authors: $(HTTP digitalmars.com, Walter Bright),
41 $(HTTP erdani.org, Andrei Alexandrescu),
42 $(HTTP jmdavisprog.com, Jonathan M Davis),
46 Source: $(PHOBOSSRC std/bitmanip.d)
49 Copyright The D Language Foundation 2007 - 2012.
50 Distributed under the Boost Software License, Version 1.0.
51 (See accompanying file LICENSE_1_0.txt or copy at
52 http://www.boost.org/LICENSE_1_0.txt)
56 import std
.range
.primitives
;
57 public import std
.system
: Endian
;
60 private string
myToString(ulong n
) pure @safe
62 import core
.internal
.string
: UnsignedStringBuf
, unsignedToTempString
;
63 UnsignedStringBuf buf
;
64 auto s
= unsignedToTempString(n
, buf
);
65 // pure allows implicit cast to string
66 return s
~ (n
> uint.max ?
"UL" : "U");
71 assert(myToString(5) == "5U");
72 assert(myToString(uint.max
) == "4294967295U");
73 assert(myToString(uint.max
+ 1UL) == "4294967296UL");
77 private template createAccessors(
78 string store
, T
, string name
, size_t len
, size_t offset
)
80 static if (!name
.length
)
82 // No need to create any accessor
83 enum createAccessors
= "";
85 else static if (len
== 0)
87 // Fields of length 0 are always zero
88 enum createAccessors
= "enum "~T
.stringof
~" "~name
~" = 0;\n";
92 enum ulong maskAllElse
= ((~0uL) >> (64 - len
)) << offset
;
93 enum TSize
= 8 * T
.sizeof
;
94 enum SignShift
= TSize
- len
;
98 enum long minVal
= -(1uL << (len
- 1));
99 enum ulong maxVal
= (1uL << (len
- 1)) - 1;
100 enum RightShiftOp
= ">>=";
104 enum ulong minVal
= 0;
105 enum ulong maxVal
= (~0uL) >> (64 - len
);
106 enum RightShiftOp
= ">>>=";
109 static if (is(T
: bool))
111 enum createAccessors
=
113 "@property bool " ~ name
~ "() @safe pure nothrow @nogc const { return "
114 ~"("~store
~" & "~myToString(maskAllElse
)~") != 0;}\n"
116 ~"@property void " ~ name
~ "(bool v) @safe pure nothrow @nogc { "
117 ~"if (v) "~store
~" |= "~myToString(maskAllElse
)~";"
118 ~"else "~store
~" &= cast(typeof("~store
~"))(-1-cast(typeof("~store
~"))"~myToString(maskAllElse
)~");}\n";
123 enum createAccessors
= "@property "~T
.stringof
~" "~name
~"() @safe pure nothrow @nogc const {"
124 ~ "auto result = cast("~T
.stringof
~") (" ~ store
~ " >>" ~ myToString(offset
) ~ ");"
125 ~ "result <<= " ~ myToString(SignShift
) ~ ";"
126 ~ "result " ~ RightShiftOp
~ myToString(SignShift
) ~ ";"
127 ~ " return result;}\n"
129 ~"@property void "~name
~"("~T
.stringof
~" v) @safe pure nothrow @nogc { "
130 ~"assert(v >= "~name
~`_min, "Value is smaller than the minimum value of bitfield '`~name
~`'"); `
131 ~"assert(v <= "~name
~`_max, "Value is greater than the maximum value of bitfield '`~name
~`'"); `
132 ~store
~" = cast(typeof("~store
~"))"
133 ~" (("~store
~" & (-1-cast(typeof("~store
~"))"~myToString(maskAllElse
)~"))"
134 ~" | ((cast(typeof("~store
~")) v << "~myToString(offset
)~")"
135 ~" & "~myToString(maskAllElse
)~"));}\n"
137 ~"enum "~T
.stringof
~" "~name
~"_min = cast("~T
.stringof
~")"
138 ~myToString(minVal
)~"; "
139 ~" enum "~T
.stringof
~" "~name
~"_max = cast("~T
.stringof
~")"
140 ~myToString(maxVal
)~"; ";
145 private template createStoreName(Ts
...)
147 static if (Ts
.length
< 2)
148 enum createStoreName
= "_bf";
150 enum createStoreName
= "_" ~ Ts
[1] ~ createStoreName
!(Ts
[3 .. $]);
153 private template createStorageAndFields(Ts
...)
155 enum Name
= createStoreName
!Ts
;
156 enum Size
= sizeOfBitField
!Ts
;
157 static if (Size
== ubyte.sizeof
* 8)
158 alias StoreType
= ubyte;
159 else static if (Size
== ushort.sizeof
* 8)
160 alias StoreType
= ushort;
161 else static if (Size
== uint.sizeof
* 8)
162 alias StoreType
= uint;
163 else static if (Size
== ulong.sizeof
* 8)
164 alias StoreType
= ulong;
167 static assert(false, "Field widths must sum to 8, 16, 32, or 64, not " ~ Size
.stringof
);
168 alias StoreType
= ulong; // just to avoid another error msg
171 enum createStorageAndFields
172 = "private " ~ StoreType
.stringof
~ " " ~ Name
~ ";"
173 ~ createFields
!(Name
, 0, Ts
);
176 private template createFields(string store
, size_t offset
, Ts
...)
178 static if (Ts
.length
> 0)
180 = createAccessors
!(store
, Ts
[0], Ts
[1], Ts
[2], offset
)
181 ~ createFields
!(store
, offset
+ Ts
[2], Ts
[3 .. $]);
183 enum createFields
= "";
186 private ulong getBitsForAlign(ulong a
)
189 while ((a
& 0x01) == 0)
195 assert(a
== 1, "alignment is not a power of 2");
199 private template createReferenceAccessor(string store
, T
, ulong bits
, string name
)
201 enum storage
= "private void* " ~ store
~ "_ptr;\n";
202 enum storage_accessor
= "@property ref size_t " ~ store
~ "() return @trusted pure nothrow @nogc const { "
203 ~ "return *cast(size_t*) &" ~ store
~ "_ptr;}\n"
204 ~ "@property void " ~ store
~ "(size_t v) @trusted pure nothrow @nogc { "
205 ~ "" ~ store
~ "_ptr = cast(void*) v;}\n";
207 enum mask
= (1UL << bits
) - 1;
209 enum ref_accessor
= "@property "~T
.stringof
~" "~name
~"() @trusted pure nothrow @nogc const { auto result = "
210 ~ "("~store
~" & "~myToString(~mask
)~"); "
211 ~ "return cast("~T
.stringof
~") cast(void*) result;}\n"
213 ~"@property void "~name
~"("~T
.stringof
~" v) @trusted pure nothrow @nogc { "
214 ~"assert(((cast(typeof("~store
~")) cast(void*) v) & "~myToString(mask
)
215 ~`) == 0, "Value not properly aligned for '`~name
~`'"); `
216 ~store
~" = cast(typeof("~store
~"))"
217 ~" (("~store
~" & (cast(typeof("~store
~")) "~myToString(mask
)~"))"
218 ~" | ((cast(typeof("~store
~")) cast(void*) v) & (cast(typeof("~store
~")) "~myToString(~mask
)~")));}\n";
220 enum createReferenceAccessor
= storage
~ storage_accessor
~ ref_accessor
;
223 private template sizeOfBitField(T
...)
225 static if (T
.length
< 2)
226 enum sizeOfBitField
= 0;
228 enum sizeOfBitField
= T
[2] + sizeOfBitField
!(T
[3 .. $]);
231 private template createTaggedReference(T
, ulong a
, string name
, Ts
...)
234 sizeOfBitField
!Ts
<= getBitsForAlign(a
),
235 "Fields must fit in the bits know to be zero because of alignment."
237 enum StoreName
= createStoreName
!(T
, name
, 0, Ts
);
238 enum createTaggedReference
239 = createReferenceAccessor
!(StoreName
, T
, sizeOfBitField
!Ts
, name
)
240 ~ createFields
!(StoreName
, 0, Ts
, size_t
, "", T
.sizeof
* 8 - sizeOfBitField
!Ts
);
244 Allows creating `bitfields` inside `structs`, `classes` and `unions`.
246 A `bitfield` consists of one or more entries with a fixed number of
247 bits reserved for each of the entries. The types of the entries can
248 be `bool`s, integral types or enumerated types, arbitrarily mixed.
249 The most efficient type to store in `bitfields` is `bool`, followed
250 by unsigned types, followed by signed types.
252 Each non-`bool` entry of the `bitfield` will be represented by the
253 number of bits specified by the user. The minimum and the maximum
254 numbers that represent this domain can be queried by using the name
255 of the variable followed by `_min` or `_max`.
257 Limitation: The number of bits in a `bitfield` is limited to 8, 16,
258 32 or 64. If padding is needed, an entry should be explicitly
259 allocated with an empty name.
261 Implementation_details: `Bitfields` are internally stored in an
262 `ubyte`, `ushort`, `uint` or `ulong` depending on the number of bits
263 used. The bits are filled in the order given by the parameters,
264 starting with the lowest significant bit. The name of the (private)
265 variable used for saving the `bitfield` is created by concatenating
266 all of the variable names, each preceded by an underscore, and
269 Params: T = A list of template parameters divided into chunks of 3
270 items. Each chunk consists (in this order) of a type, a
271 name and a number. Together they define an entry
272 of the `bitfield`: a variable of the given type and name,
273 which can hold as many bits as the number denotes.
275 Returns: A string that can be used in a `mixin` to add the `bitfield`.
277 See_Also: $(REF BitFlags, std,typecons)
279 string
bitfields(T
...)()
281 static assert(T
.length
% 3 == 0,
282 "Wrong number of arguments (" ~ T
.length
.stringof
~ "): Must be a multiple of 3");
284 static foreach (i
, ARG
; T
)
286 static if (i
% 3 == 0)
287 static assert(is (typeof({ARG tmp
= cast (ARG
)0; if (ARG
.min
< 0) {} }())),
288 "Integral type or `bool` expected, found " ~ ARG
.stringof
);
290 // would be nice to check for valid variable names too
291 static if (i
% 3 == 1)
292 static assert(is (typeof(ARG
) : string
),
293 "Variable name expected, found " ~ ARG
.stringof
);
295 static if (i
% 3 == 2)
297 static assert(is (typeof({ulong tmp
= ARG
;}())),
298 "Integral value expected, found " ~ ARG
.stringof
);
300 static if (T
[i
-1] != "")
302 static assert(!is (T
[i
-2] : bool) || ARG
<= 1,
303 "Type `bool` is only allowed for single-bit fields");
305 static assert(ARG
>= 0 && ARG
<= T
[i
-2].sizeof
* 8,
306 "Wrong size of bitfield: " ~ ARG
.stringof
);
311 return createStorageAndFields
!T
;
315 Create a `bitfield` pack of eight bits, which fit in
316 one `ubyte`. The `bitfields` are allocated starting from the
317 least significant bit, i.e. `x` occupies the two least significant bits
318 of the `bitfields` storage.
339 assert(obj
.flag
== false);
343 The sum of all bit lengths in one `bitfield` instantiation
344 must be exactly 8, 16, 32, or 64. If padding is needed, just allocate
345 one bitfield with an empty name.
358 assert(a
.flag1
== 0);
360 assert(a
.flag1
== 1);
362 assert(a
.flag1
== 0);
365 /// enums can be used too
378 @safe pure nothrow @nogc
381 // Degenerate bitfields tests mixed with range tests
382 // https://issues.dlang.org/show_bug.cgi?id=8474
383 // https://issues.dlang.org/show_bug.cgi?id=11160
386 mixin(bitfields
!(uint, "a", 32,
392 static assert(Test1
.b_min
== 0);
393 static assert(Test1
.b_max
== 15);
398 mixin(bitfields
!(bool, "a", 0,
401 static assert(Test2
.b_min
== ulong.min
);
402 static assert(Test2
.b_max
== ulong.max
);
407 mixin(bitfields
!(bool, "a", 0,
413 mixin(bitfields
!(int, "a", 32,
419 static assert(Test2b
.b_min
== -8);
420 static assert(Test2b
.b_max
== 7);
425 mixin(bitfields
!(bool, "a", 0,
428 static assert(Test3b
.b_min
== long.min
);
429 static assert(Test3b
.b_max
== long.max
);
434 mixin(bitfields
!(long, "a", 32,
438 // Sign extension tests
441 t2b
.b
= -5; assert(t2b
.b
== -5);
442 t2b
.d
= -5; assert(t2b
.d
== -5);
443 t2b
.e
= -5; assert(t2b
.e
== -5);
444 t4b
.a
= -5; assert(t4b
.a
== -5L);
447 // https://issues.dlang.org/show_bug.cgi?id=6686
451 ulong bits
= ulong.max
;
459 num
.bits
= ulong.max
;
461 assert(num
.bits
== 0xFFFF_FFFF
_8000_0001uL);
464 // https://issues.dlang.org/show_bug.cgi?id=5942
478 assert(data
.b
== 42);
485 mixin(bitfields
!(bool, "a", 1,
490 @safe void test() pure nothrow
509 static struct Integrals
{
510 bool checkExpectations(bool eb
, int ei
, short es
) { return b
== eb
&& i
== ei
&& s
== es
; }
518 assert(i
.checkExpectations(false, 0, 0));
520 assert(i
.checkExpectations(true, 0, 0));
522 assert(i
.checkExpectations(true, 7, 0));
524 assert(i
.checkExpectations(true, 7, -8));
526 assert(i
.checkExpectations(true, 7, 7));
529 //https://issues.dlang.org/show_bug.cgi?id=8876
531 struct MoreIntegrals
{
532 bool checkExpectations(uint eu
, ushort es
, uint ei
) { return u
== eu
&& s
== es
&& i
== ei
; }
541 assert(i
.checkExpectations(0, 0, 0));
543 assert(i
.checkExpectations(0, 20, 0));
545 assert(i
.checkExpectations(0, 20, 72));
547 assert(i
.checkExpectations(8, 20, 72));
549 assert(i
.checkExpectations(8, 7, 72));
552 enum A
{ True
, False
}
553 enum B
{ One
, Two
, Three
, Four
}
554 static struct Enums
{
555 bool checkExpectations(A ea
, B eb
) { return a
== ea
&& b
== eb
; }
563 assert(e
.checkExpectations(A
.True
, B
.One
));
565 assert(e
.checkExpectations(A
.False
, B
.One
));
567 assert(e
.checkExpectations(A
.False
, B
.Three
));
569 static struct SingleMember
{
570 bool checkExpectations(bool eb
) { return b
== eb
; }
577 assert(f
.checkExpectations(false));
579 assert(f
.checkExpectations(true));
582 // https://issues.dlang.org/show_bug.cgi?id=12477
585 import core
.exception
: AssertError
;
586 import std
.algorithm
.searching
: canFind
;
597 try { s
.a
= uint.max
; assert(0); }
598 catch (AssertError ae
)
599 { assert(ae
.msg
.canFind("Value is greater than the maximum value of bitfield 'a'"), ae
.msg
); }
601 try { s
.b
= int.min
; assert(0); }
602 catch (AssertError ae
)
603 { assert(ae
.msg
.canFind("Value is smaller than the minimum value of bitfield 'b'"), ae
.msg
); }
606 // https://issues.dlang.org/show_bug.cgi?id=15305
617 s
.bob
= long.max
- 1;
619 assert(s
.bob
== long.max
- 1);
622 // https://issues.dlang.org/show_bug.cgi?id=21634
627 mixin(bitfields
!(int, "", 1,
632 // https://issues.dlang.org/show_bug.cgi?id=21725
645 This string mixin generator allows one to create tagged pointers inside $(D_PARAM struct)s and $(D_PARAM class)es.
647 A tagged pointer uses the bits known to be zero in a normal pointer or class reference to store extra information.
648 For example, a pointer to an integer must be 4-byte aligned, so there are 2 bits that are always known to be zero.
649 One can store a 2-bit integer there.
651 The example above creates a tagged pointer in the struct A. The pointer is of type
652 `uint*` as specified by the first argument, and is named x, as specified by the second
655 Following arguments works the same way as `bitfield`'s. The bitfield must fit into the
656 bits known to be zero because of the pointer alignment.
659 template taggedPointer(T
: T
*, string name
, Ts
...) {
660 enum taggedPointer
= createTaggedReference
!(T
*, T
.alignof
, name
, Ts
);
669 mixin(taggedPointer
!(
684 mixin(taggedPointer
!(
692 assert(t5
.a
is null);
697 assert(t5
.a
is &myint
);
702 This string mixin generator allows one to create tagged class reference inside $(D_PARAM struct)s and $(D_PARAM class)es.
704 A tagged class reference uses the bits known to be zero in a normal class reference to store extra information.
705 For example, a pointer to an integer must be 4-byte aligned, so there are 2 bits that are always known to be zero.
706 One can store a 2-bit integer there.
708 The example above creates a tagged reference to an Object in the struct A. This expects the same parameters
709 as `taggedPointer`, except the first argument which must be a class type instead of a pointer type.
712 template taggedClassRef(T
, string name
, Ts
...)
715 enum taggedClassRef
= createTaggedReference
!(T
, 8, name
, Ts
);
724 mixin(taggedClassRef
!(
729 obj
.o
= new Object();
737 mixin(taggedClassRef
!(
745 assert(t6
.o
is null);
746 assert(t6
.b
== false);
748 auto o
= new Object();
752 assert(t6
.b
== true);
757 static assert(!__traits(compiles
,
762 static assert(!__traits(compiles
,
768 mixin(taggedClassRef
!(
776 static assert(!__traits(compiles
, bar(s
)));
779 private struct FloatingPointRepresentation(T
)
781 static if (is(T
== float))
783 enum uint bias
= 127, fractionBits
= 23, exponentBits
= 8, signBits
= 1;
784 alias FractionType
= uint;
785 alias ExponentType
= ubyte;
789 enum uint bias
= 1023, fractionBits
= 52, exponentBits
= 11, signBits
= 1;
790 alias FractionType
= ulong;
791 alias ExponentType
= ushort;
798 FractionType
, "fraction", fractionBits
,
799 ExponentType
, "exponent", exponentBits
,
800 bool, "sign", signBits
));
805 Allows manipulating the fraction, exponent, and sign parts of a
806 `float` separately. The definition is:
816 uint, "fraction", 23,
817 ubyte, "exponent", 8,
820 enum uint bias = 127, fractionBits = 23, exponentBits = 8, signBits = 1;
825 alias FloatRep
= FloatingPointRepresentation
!float;
830 FloatRep
rep = {value
: 0};
831 assert(rep.fraction
== 0);
832 assert(rep.exponent
== 0);
836 assert(rep.fraction
== 2621440);
837 assert(rep.exponent
== 132);
841 assert(rep.fraction
== 2097152);
842 assert(rep.exponent
== 130);
848 FloatRep
rep = {value
: 1};
849 assert(rep.fraction
== 0);
850 assert(rep.exponent
== 127);
854 assert(rep.value
== 0.5);
857 assert(rep.value
== 8);
863 FloatRep
rep = {value
: 1};
865 assert(rep.fraction
== 0);
866 assert(rep.exponent
== 126);
870 assert(rep.fraction
== 2796203);
871 assert(rep.exponent
== 125);
876 Allows manipulating the fraction, exponent, and sign parts of a
877 `double` separately. The definition is:
887 ulong, "fraction", 52,
888 ushort, "exponent", 11,
891 enum uint bias = 1023, signBits = 1, fractionBits = 52, exponentBits = 11;
896 alias DoubleRep
= FloatingPointRepresentation
!double;
901 DoubleRep
rep = {value
: 0};
902 assert(rep.fraction
== 0);
903 assert(rep.exponent
== 0);
907 assert(rep.fraction
== 1407374883553280);
908 assert(rep.exponent
== 1028);
912 assert(rep.fraction
== 1125899906842624);
913 assert(rep.exponent
== 1026);
919 DoubleRep
rep = {value
: 1};
920 assert(rep.fraction
== 0);
921 assert(rep.exponent
== 1023);
925 assert(rep.value
== 0.5);
928 assert(rep.value
== 8);
934 DoubleRep
rep = {value
: 1};
936 assert(rep.fraction
== 0);
937 assert(rep.exponent
== 1022);
941 assert(rep.fraction
== 1501199875790165);
942 assert(rep.exponent
== 1021);
951 assert(x
.fraction
== 0 && x
.exponent
== 1023 && !x
.sign
);
953 assert(x
.fraction
== 0 && x
.exponent
== 1022 && x
.sign
);
955 assert(x
.fraction
== 0 && x
.exponent
== 1022 && !x
.sign
);
962 x
.fraction
= 1125899906842624;
965 assert(x
.value
== -5.0);
969 A dynamic array of bits. Each bit in a `BitArray` can be manipulated individually
970 or by the standard bitwise operators `&`, `|`, `^`, `~`, `>>`, `<<` and also by
971 other effective member functions; most of them work relative to the `BitArray`'s
972 dimension (see $(LREF dim)), instead of its $(LREF length).
978 import core
.bitop
: btc, bts, btr, bsf, bt;
979 import std
.format
.spec
: FormatSpec
;
983 enum bitsPerSizeT
= size_t
.sizeof
* 8;
985 @property size_t
fullWords() const scope @safe @nogc pure nothrow
987 return _len
/ bitsPerSizeT
;
989 // Number of bits after the last full word
990 @property size_t
endBits() const scope @safe @nogc pure nothrow
992 return _len
% bitsPerSizeT
;
994 // Bit mask to extract the bits after the last full word
995 @property size_t
endMask() const scope @safe @nogc pure nothrow
997 return (size_t(1) << endBits
) - 1;
999 static size_t
lenToDim(size_t len
) @nogc pure nothrow @safe
1001 return (len
+ (bitsPerSizeT
-1)) / bitsPerSizeT
;
1006 Creates a `BitArray` from a `bool` array, such that `bool` values read
1007 from left to right correspond to subsequent bits in the `BitArray`.
1009 Params: ba = Source array of `bool` values.
1011 this(in bool[] ba
) nothrow pure
1023 import std
.algorithm
.comparison
: equal
;
1025 bool[] input
= [true, false, false, true, true];
1026 auto a
= BitArray(input
);
1027 assert(a
.length
== 5);
1028 assert(a
.bitsSet
.equal([0, 3, 4]));
1030 // This also works because an implicit cast to bool[] occurs for this array.
1031 auto b
= BitArray([0, 0, 1]);
1032 assert(b
.length
== 3);
1033 assert(b
.bitsSet
.equal([2]));
1039 import std
.algorithm
.comparison
: equal
;
1040 import std
.array
: array
;
1041 import std
.range
: iota
, repeat
;
1043 BitArray a
= true.repeat(70).array
;
1044 assert(a
.length
== 70);
1045 assert(a
.bitsSet
.equal(iota(0, 70)));
1049 Creates a `BitArray` from the raw contents of the source array. The
1050 source array is not copied but simply acts as the underlying array
1051 of bits, which stores data as `size_t` units.
1053 That means a particular care should be taken when passing an array
1054 of a type different than `size_t`, firstly because its length should
1055 be a multiple of `size_t.sizeof`, and secondly because how the bits
1060 size_t[] source = [1, 2, 3, 3424234, 724398, 230947, 389492];
1061 enum sbits = size_t.sizeof * 8;
1062 auto ba = BitArray(source, source.length * sbits);
1063 foreach (n; 0 .. source.length * sbits)
1065 auto nth_bit = cast(bool) (source[n / sbits] & (1L << (n % sbits)));
1066 assert(ba[n] == nth_bit);
1070 The least significant bit in any `size_t` unit is the starting bit of this
1071 unit, and the most significant bit is the last bit of this unit. Therefore,
1072 passing e.g. an array of `int`s may result in a different `BitArray`
1073 depending on the processor's endianness.
1075 This constructor is the inverse of $(LREF opCast).
1078 v = Source array. `v.length` must be a multple of `size_t.sizeof`.
1079 numbits = Number of bits to be mapped from the source array, i.e.
1080 length of the created `BitArray`.
1082 this(void[] v
, size_t numbits
) @nogc nothrow pure
1085 assert(numbits
<= v
.length
* 8,
1086 "numbits must be less than or equal to v.length * 8");
1087 assert(v
.length
% size_t
.sizeof
== 0,
1088 "v.length must be a multiple of the size of size_t");
1092 _ptr
= cast(size_t
*) v
.ptr
;
1099 import std
.algorithm
.comparison
: equal
;
1101 auto a
= BitArray([1, 0, 0, 1, 1]);
1103 // Inverse of the cast.
1104 auto v
= cast(void[]) a
;
1105 auto b
= BitArray(v
, a
.length
);
1107 assert(b
.length
== 5);
1108 assert(b
.bitsSet
.equal([0, 3, 4]));
1110 // a and b share the underlying data.
1119 import std
.algorithm
.comparison
: equal
;
1121 size_t
[] source
= [0b1100, 0b0011];
1122 enum sbits
= size_t
.sizeof
* 8;
1123 auto ba
= BitArray(source
, source
.length
* sbits
);
1124 // The least significant bit in each unit is this unit's starting bit.
1125 assert(ba
.bitsSet
.equal([2, 3, sbits
, sbits
+ 1]));
1131 // Example from the doc for this constructor.
1132 static immutable size_t
[] sourceData
= [1, 0b101, 3, 3424234, 724398, 230947, 389492];
1133 size_t
[] source
= sourceData
.dup
;
1134 enum sbits
= size_t
.sizeof
* 8;
1135 auto ba
= BitArray(source
, source
.length
* sbits
);
1136 foreach (n
; 0 .. source
.length
* sbits
)
1138 auto nth_bit
= cast(bool) (source
[n
/ sbits
] & (1L << (n
% sbits
)));
1139 assert(ba
[n
] == nth_bit
);
1142 // Example of mapping only part of the array.
1143 import std
.algorithm
.comparison
: equal
;
1145 auto bc
= BitArray(source
, sbits
+ 1);
1146 assert(bc
.bitsSet
.equal([0, sbits
]));
1147 // Source array has not been modified.
1148 assert(source
== sourceData
);
1151 // Deliberately undocumented: raw initialization of bit array.
1152 this(size_t len
, size_t
* ptr
) @nogc nothrow pure
1159 Returns: Dimension i.e. the number of native words backing this `BitArray`.
1161 Technically, this is the length of the underlying array storing bits, which
1162 is equal to `ceil(length / (size_t.sizeof * 8))`, as bits are packed into
1165 @property size_t
dim() const @nogc nothrow pure @safe
1167 return lenToDim(_len
);
1171 Returns: Number of bits in the `BitArray`.
1173 @property size_t
length() const @nogc nothrow pure @safe
1178 /**********************************************
1179 * Sets the amount of bits in the `BitArray`.
1180 * $(RED Warning: increasing length may overwrite bits in
1181 * the final word of the current underlying data regardless
1182 * of whether it is shared between BitArray objects. i.e. D
1183 * dynamic array extension semantics are not followed.)
1185 @property size_t
length(size_t newlen
) pure nothrow @system
1189 size_t olddim
= dim
;
1190 immutable newdim
= lenToDim(newlen
);
1192 if (newdim
!= olddim
)
1194 // Create a fake array so we can use D's realloc machinery
1195 auto b
= _ptr
[0 .. olddim
];
1196 b
.length
= newdim
; // realloc
1202 if (oldlen
< newlen
)
1204 auto end
= ((oldlen
/ bitsPerSizeT
) + 1) * bitsPerSizeT
;
1207 this[oldlen
.. end
] = 0;
1213 // https://issues.dlang.org/show_bug.cgi?id=20240
1222 assert(ba
[0] == 0); // OK
1228 assert(ba
[1] == 0); // Fail
1231 /**********************************************
1232 * Gets the `i`'th bit in the `BitArray`.
1234 bool opIndex(size_t i
) const @nogc pure nothrow
1237 assert(i
< _len
, "i must be less than the length");
1241 return cast(bool) bt(_ptr
, i
);
1247 static void fun(const BitArray arr
)
1258 /**********************************************
1259 * Sets the `i`'th bit in the `BitArray`.
1261 bool opIndexAssign(bool b
, size_t i
) @nogc pure nothrow
1264 assert(i
< _len
, "i must be less than the length");
1276 Sets all the values in the `BitArray` to the
1277 value specified by `val`.
1279 void opSliceAssign(bool val
) @nogc pure nothrow
1281 _ptr
[0 .. fullWords
] = val ?
~size_t(0) : 0;
1285 _ptr
[fullWords
] |
= endMask
;
1287 _ptr
[fullWords
] &= ~endMask
;
1292 @system pure nothrow unittest
1294 import std
.algorithm
.comparison
: equal
;
1296 auto b
= BitArray([1, 0, 1, 0, 1, 1]);
1300 assert(b
.bitsSet
.equal([0, 1, 2, 3, 4, 5]));
1303 // none of the bits are set
1304 assert(b
.bitsSet
.empty
);
1308 Sets the bits of a slice of `BitArray` starting
1309 at index `start` and ends at index $(D end - 1)
1310 with the values specified by `val`.
1312 void opSliceAssign(bool val
, size_t start
, size_t end
) @nogc pure nothrow
1315 assert(start
<= end
, "start must be less or equal to end");
1316 assert(end
<= length
, "end must be less or equal to the length");
1320 size_t startBlock
= start
/ bitsPerSizeT
;
1321 size_t endBlock
= end
/ bitsPerSizeT
;
1322 size_t startOffset
= start
% bitsPerSizeT
;
1323 size_t endOffset
= end
% bitsPerSizeT
;
1325 if (startBlock
== endBlock
)
1327 size_t startBlockMask
= ~((size_t(1) << startOffset
) - 1);
1328 size_t endBlockMask
= (size_t(1) << endOffset
) - 1;
1329 size_t joinMask
= startBlockMask
& endBlockMask
;
1331 _ptr
[startBlock
] |
= joinMask
;
1333 _ptr
[startBlock
] &= ~joinMask
;
1337 if (startOffset
!= 0)
1339 size_t startBlockMask
= ~((size_t(1) << startOffset
) - 1);
1341 _ptr
[startBlock
] |
= startBlockMask
;
1343 _ptr
[startBlock
] &= ~startBlockMask
;
1348 size_t endBlockMask
= (size_t(1) << endOffset
) - 1;
1350 _ptr
[endBlock
] |
= endBlockMask
;
1352 _ptr
[endBlock
] &= ~endBlockMask
;
1354 _ptr
[startBlock
.. endBlock
] = size_t(0) - size_t(val
);
1358 @system pure nothrow unittest
1360 import std
.algorithm
.comparison
: equal
;
1361 import std
.range
: iota
;
1364 auto b
= BitArray([1, 0, 0, 0, 1, 1, 0]);
1366 assert(b
.bitsSet
.equal([0, 1, 2, 4, 5]));
1369 auto b1
= BitArray(bitArray
);
1370 b1
[63 .. 67] = true;
1371 assert(b1
.bitsSet
.equal([63, 64, 65, 66]));
1372 b1
[63 .. 67] = false;
1373 assert(b1
.bitsSet
.empty
);
1375 assert(b1
.bitsSet
.equal(iota(0, 64)));
1376 b1
[0 .. 64] = false;
1377 assert(b1
.bitsSet
.empty
);
1379 bool[256] bitArray2
;
1380 auto b2
= BitArray(bitArray2
);
1381 b2
[3 .. 245] = true;
1382 assert(b2
.bitsSet
.equal(iota(3, 245)));
1383 b2
[3 .. 245] = false;
1384 assert(b2
.bitsSet
.empty
);
1388 Flips all the bits in the `BitArray`
1390 void flip() @nogc pure nothrow
1392 foreach (i
; 0 .. fullWords
)
1396 _ptr
[fullWords
] = (~_ptr
[fullWords
]) & endMask
;
1400 @system pure nothrow unittest
1402 import std
.algorithm
.comparison
: equal
;
1403 import std
.range
: iota
;
1405 // positions 0, 2, 4 are set
1406 auto b
= BitArray([1, 0, 1, 0, 1, 0]);
1408 // after flipping, positions 1, 3, 5 are set
1409 assert(b
.bitsSet
.equal([1, 3, 5]));
1412 auto b1
= BitArray(bits
);
1414 assert(b1
.bitsSet
.equal(iota(0, 270)));
1418 Flips a single bit, specified by `pos`
1420 void flip(size_t pos
) @nogc pure nothrow
1422 bt(_ptr
, pos
) ?
btr(_ptr
, pos
) : bts(_ptr
, pos
);
1426 @system pure nothrow unittest
1428 auto ax
= BitArray([1, 0, 0, 1]);
1433 y
[90 .. 130] = true;
1434 auto ay
= BitArray(y
);
1436 assert(ay
[100] == 0);
1439 /**********************************************
1440 * Counts all the set bits in the `BitArray`
1442 size_t
count() const scope @safe @nogc pure nothrow
1447 foreach (i
; 0 .. fullWords
)
1448 bitCount
+= (() @trusted => countBitsSet(_ptr
[i
]))();
1450 bitCount
+= (() @trusted => countBitsSet(_ptr
[fullWords
] & endMask
))();
1460 @system pure nothrow unittest
1462 auto a
= BitArray([0, 1, 1, 0, 0, 1, 1]);
1463 assert(a
.count
== 4);
1466 assert(b
.count
== 0);
1468 bool[200] boolArray
;
1469 boolArray
[45 .. 130] = true;
1470 auto c
= BitArray(boolArray
);
1471 assert(c
.count
== 85);
1474 /**********************************************
1475 * Duplicates the `BitArray` and its contents.
1477 @property BitArray
dup() const pure nothrow
1481 auto b
= _ptr
[0 .. dim
].dup
;
1494 a
[0] = 1; a
[1] = 0; a
[2] = 1;
1496 assert(b
.length
== 3);
1498 assert(b
[i
] == (((i ^
1) & 1) ?
true : false));
1501 /**********************************************
1502 * Support for `foreach` loops for `BitArray`.
1504 int opApply(scope int delegate(ref bool) dg
)
1508 foreach (i
; 0 .. _len
)
1510 bool b
= opIndex(i
);
1520 int opApply(scope int delegate(bool) dg
) const
1524 foreach (i
; 0 .. _len
)
1526 immutable b
= opIndex(i
);
1535 int opApply(scope int delegate(size_t
, ref bool) dg
)
1539 foreach (i
; 0 .. _len
)
1541 bool b
= opIndex(i
);
1551 int opApply(scope int delegate(size_t
, bool) dg
) const
1555 foreach (i
; 0 .. _len
)
1557 immutable b
= opIndex(i
);
1568 bool[] ba
= [1,0,1];
1570 auto a
= BitArray(ba
);
1577 case 0: assert(b
== true); break;
1578 case 1: assert(b
== false); break;
1579 case 2: assert(b
== true); break;
1589 case 0: assert(b
== true); break;
1590 case 1: assert(b
== false); break;
1591 case 2: assert(b
== true); break;
1598 /**********************************************
1599 * Reverses the bits of the `BitArray`.
1601 @property BitArray
reverse() @nogc pure nothrow return
1604 assert(result
== this, "the result must be equal to this");
1615 for (; lo
< hi
; lo
++, hi
--)
1618 this[lo
] = this[hi
];
1629 bool[5] data
= [1,0,1,1,0];
1633 foreach (i
; 0 .. data
.length
)
1634 assert(b
[i
] == data
[4 - i
]);
1638 /**********************************************
1639 * Sorts the `BitArray`'s elements.
1641 @property BitArray
sort() @nogc pure nothrow return
1644 assert(result
== this, "the result must be equal to this");
1660 if (this[lo
] == true)
1669 if (this[hi
] == false)
1688 size_t x
= 0b1100011000;
1689 auto ba
= BitArray(10, &x
);
1692 assert(ba
[i
] == false);
1693 foreach (i
; 6 .. 10)
1694 assert(ba
[i
] == true);
1698 /***************************************
1699 * Support for operators == and != for `BitArray`.
1701 bool opEquals(const ref BitArray a2
) const @nogc pure nothrow
1703 if (this.length
!= a2
.length
)
1705 auto p1
= this._ptr
;
1708 if (p1
[0 .. fullWords
] != p2
[0 .. fullWords
])
1715 return (p1
[i
] & endMask
) == (p2
[i
] & endMask
);
1721 bool[] ba
= [1,0,1,0,1];
1722 bool[] bb
= [1,0,1];
1723 bool[] bc
= [1,0,1,0,1,0,1];
1724 bool[] bd
= [1,0,1,1,1];
1725 bool[] be
= [1,0,1,0,1];
1726 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];
1727 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];
1729 auto a
= BitArray(ba
);
1730 auto b
= BitArray(bb
);
1731 auto c
= BitArray(bc
);
1732 auto d
= BitArray(bd
);
1733 auto e
= BitArray(be
);
1734 auto f
= BitArray(bf
);
1735 auto g
= BitArray(bg
);
1744 /***************************************
1745 * Supports comparison operators for `BitArray`.
1747 int opCmp(BitArray a2
) const @nogc pure nothrow
1749 const lesser
= this.length
< a2
.length ?
&this : &a2
;
1750 immutable fullWords
= lesser
.fullWords
;
1751 immutable endBits
= lesser
.endBits
;
1752 auto p1
= this._ptr
;
1755 foreach (i
; 0 .. fullWords
)
1759 return p1
[i
] & (size_t(1) << bsf(p1
[i
] ^ p2
[i
])) ?
1 : -1;
1765 immutable i
= fullWords
;
1766 immutable diff
= p1
[i
] ^ p2
[i
];
1769 immutable index
= bsf(diff
);
1770 if (index
< endBits
)
1772 return p1
[i
] & (size_t(1) << index
) ?
1 : -1;
1778 // A bool value can be implicitly converted to any integral type,
1779 // with false becoming 0 and true becoming 1
1780 return (this.length
> a2
.length
) - (this.length
< a2
.length
);
1786 bool[] ba
= [1,0,1,0,1];
1787 bool[] bb
= [1,0,1];
1788 bool[] bc
= [1,0,1,0,1,0,1];
1789 bool[] bd
= [1,0,1,1,1];
1790 bool[] be
= [1,0,1,0,1];
1791 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];
1792 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];
1794 auto a
= BitArray(ba
);
1795 auto b
= BitArray(bb
);
1796 auto c
= BitArray(bc
);
1797 auto d
= BitArray(bd
);
1798 auto e
= BitArray(be
);
1799 auto f
= BitArray(bf
);
1800 auto g
= BitArray(bg
);
1818 foreach (i
; 1 .. 256)
1822 auto x
= BitArray(v
);
1824 auto y
= BitArray(v
);
1831 for (size_t len
= 4; len
<= 256; len
<<= 1)
1833 a1
.length
= a2
.length
= len
;
1834 a1
[len
-2] = a2
[len
-1] = true;
1836 a1
[len
-2] = a2
[len
-1] = false;
1839 foreach (j
; 1 .. a1
.length
)
1841 a1
[j
-1] = a2
[j
] = true;
1843 a1
[j
-1] = a2
[j
] = false;
1847 /***************************************
1848 * Support for hashing for `BitArray`.
1850 size_t
toHash() const @nogc pure nothrow
1853 auto fullBytes
= _len
/ 8;
1854 foreach (i
; 0 .. fullBytes
)
1857 hash
+= (cast(byte*) this._ptr
)[i
];
1859 foreach (i
; 8*fullBytes
.. _len
)
1867 /***************************************
1868 * Convert to `void[]`.
1870 inout(void)[] opCast(T
: const void[])() inout @nogc pure nothrow
1872 return cast(inout void[]) _ptr
[0 .. dim
];
1875 /***************************************
1876 * Convert to `size_t[]`.
1878 inout(size_t
)[] opCast(T
: const size_t
[])() inout @nogc pure nothrow
1880 return _ptr
[0 .. dim
];
1886 import std
.array
: array
;
1887 import std
.range
: repeat
, take
;
1889 // bit array with 300 elements
1890 auto a
= BitArray(true.repeat
.take(300).array
);
1891 size_t
[] v
= cast(size_t
[]) a
;
1892 const blockSize
= size_t
.sizeof
* 8;
1893 assert(v
.length
== (a
.length
+ blockSize
- 1) / blockSize
);
1896 // https://issues.dlang.org/show_bug.cgi?id=20606
1899 import std
.meta
: AliasSeq
;
1901 static foreach (alias T
; AliasSeq
!(void, size_t
))
1904 T
[] ma
= cast(T
[]) m
;
1907 const(T
)[] ca
= cast(const T
[]) c
;
1909 immutable BitArray i
;
1910 immutable(T
)[] ia
= cast(immutable T
[]) i
;
1913 ca
= cast(const T
[]) m
;
1914 ca
= cast(const T
[]) i
;
1916 // Invalid cast don't compile
1917 static assert(!is(typeof(cast(T
[]) c
)));
1918 static assert(!is(typeof(cast(T
[]) i
)));
1919 static assert(!is(typeof(cast(immutable T
[]) m
)));
1920 static assert(!is(typeof(cast(immutable T
[]) c
)));
1924 /***************************************
1925 * Support for unary operator ~ for `BitArray`.
1927 BitArray
opUnary(string op
)() const pure nothrow
1930 auto dim
= this.dim
;
1933 result
.length
= _len
;
1935 result
._ptr
[0 .. dim
] = ~this._ptr
[0 .. dim
];
1937 // Avoid putting garbage in extra bits
1938 // Remove once we zero on length extension
1940 result
._ptr
[dim
- 1] &= endMask
;
1948 bool[] ba
= [1,0,1,0,1];
1950 auto a
= BitArray(ba
);
1961 /***************************************
1962 * Support for binary bitwise operators for `BitArray`.
1964 BitArray
opBinary(string op
)(const BitArray e2
) const pure nothrow
1965 if (op
== "-" || op
== "&" || op
== "|" || op
== "^")
1968 assert(e2
.length
== _len
, "e2 must have the same length as this");
1972 auto dim
= this.dim
;
1975 result
.length
= _len
;
1977 static if (op
== "-")
1978 result
._ptr
[0 .. dim
] = this._ptr
[0 .. dim
] & ~e2
._ptr
[0 .. dim
];
1980 mixin("result._ptr[0 .. dim] = this._ptr[0 .. dim]"~op
~" e2._ptr[0 .. dim];");
1982 // Avoid putting garbage in extra bits
1983 // Remove once we zero on length extension
1985 result
._ptr
[dim
- 1] &= endMask
;
1993 static bool[] ba
= [1,0,1,0,1];
1994 static bool[] bb
= [1,0,1,1,0];
1996 auto a
= BitArray(ba
);
1997 auto b
= BitArray(bb
);
2011 bool[] ba
= [1,0,1,0,1];
2012 bool[] bb
= [1,0,1,1,0];
2014 auto a
= BitArray(ba
);
2015 auto b
= BitArray(bb
);
2029 bool[] ba
= [1,0,1,0,1];
2030 bool[] bb
= [1,0,1,1,0];
2032 auto a
= BitArray(ba
);
2033 auto b
= BitArray(bb
);
2047 bool[] ba
= [1,0,1,0,1];
2048 bool[] bb
= [1,0,1,1,0];
2050 auto a
= BitArray(ba
);
2051 auto b
= BitArray(bb
);
2063 /***************************************
2064 * Support for operator op= for `BitArray`.
2066 BitArray
opOpAssign(string op
)(const BitArray e2
) @nogc pure nothrow return scope
2067 if (op
== "-" || op
== "&" || op
== "|" || op
== "^")
2070 assert(e2
.length
== _len
, "e2 must have the same length as this");
2074 foreach (i
; 0 .. fullWords
)
2076 static if (op
== "-")
2077 _ptr
[i
] &= ~e2
._ptr
[i
];
2079 mixin("_ptr[i] "~op
~"= e2._ptr[i];");
2084 size_t i
= fullWords
;
2085 size_t endWord
= _ptr
[i
];
2086 static if (op
== "-")
2087 endWord
&= ~e2
._ptr
[i
];
2089 mixin("endWord "~op
~"= e2._ptr[i];");
2090 _ptr
[i
] = (_ptr
[i
] & ~endMask
) |
(endWord
& endMask
);
2098 bool[] ba
= [1,0,1,0,1,1,0,1,0,1];
2099 bool[] bb
= [1,0,1,1,0];
2100 auto a
= BitArray(ba
);
2101 auto b
= BitArray(bb
);
2115 bool[] ba
= [1,0,1,0,1];
2116 bool[] bb
= [1,0,1,1,0];
2118 auto a
= BitArray(ba
);
2119 auto b
= BitArray(bb
);
2132 bool[] ba
= [1,0,1,0,1];
2133 bool[] bb
= [1,0,1,1,0];
2135 auto a
= BitArray(ba
);
2136 auto b
= BitArray(bb
);
2149 bool[] ba
= [1,0,1,0,1];
2150 bool[] bb
= [1,0,1,1,0];
2152 auto a
= BitArray(ba
);
2153 auto b
= BitArray(bb
);
2166 bool[] ba
= [1,0,1,0,1];
2167 bool[] bb
= [1,0,1,1,0];
2169 auto a
= BitArray(ba
);
2170 auto b
= BitArray(bb
);
2180 /***************************************
2181 * Support for operator ~= for `BitArray`.
2182 * $(RED Warning: This will overwrite a bit in the final word
2183 * of the current underlying data regardless of whether it is
2184 * shared between BitArray objects. i.e. D dynamic array
2185 * concatenation semantics are not followed)
2187 BitArray
opOpAssign(string op
)(bool b
) pure nothrow return scope
2198 bool[] ba
= [1,0,1,0,1];
2200 auto a
= BitArray(ba
);
2214 /***************************************
2217 BitArray
opOpAssign(string op
)(BitArray b
) pure nothrow return scope
2221 length
= _len
+ b
.length
;
2222 for (auto i
= istart
; i
< _len
; i
++)
2223 this[i
] = b
[i
- istart
];
2231 bool[] bb
= [0,1,0];
2233 auto a
= BitArray(ba
);
2234 auto b
= BitArray(bb
);
2238 assert(a
.length
== 5);
2248 /***************************************
2249 * Support for binary operator ~ for `BitArray`.
2251 BitArray
opBinary(string op
)(bool b
) const pure nothrow
2257 r
.length
= _len
+ 1;
2263 BitArray
opBinaryRight(string op
)(bool b
) const pure nothrow
2268 r
.length
= _len
+ 1;
2270 foreach (i
; 0 .. _len
)
2276 BitArray
opBinary(string op
)(BitArray b
) const pure nothrow
2290 bool[] bb
= [0,1,0];
2292 auto a
= BitArray(ba
);
2293 auto b
= BitArray(bb
);
2297 assert(c
.length
== 5);
2305 assert(c
.length
== 3);
2311 assert(c
.length
== 3);
2317 // Rolls double word (upper, lower) to the right by n bits and returns the
2318 // lower word of the result.
2319 private static size_t
rollRight()(size_t upper
, size_t lower
, size_t nbits
)
2320 pure @safe nothrow @nogc
2323 assert(nbits
< bitsPerSizeT
, "nbits must be less than bitsPerSizeT");
2329 return (upper
<< (bitsPerSizeT
- nbits
)) |
(lower
>> nbits
);
2334 static if (size_t
.sizeof
== 8)
2336 size_t x
= 0x12345678_90ABCDEF
;
2337 size_t y
= 0xFEDBCA09_87654321;
2339 assert(rollRight(x
, y
, 32) == 0x90ABCDEF_FEDBCA
09);
2340 assert(rollRight(y
, x
, 4) == 0x11234567_890ABCDE
);
2342 else static if (size_t
.sizeof
== 4)
2344 size_t x
= 0x12345678;
2345 size_t y
= 0x90ABCDEF;
2347 assert(rollRight(x
, y
, 16) == 0x567890AB);
2348 assert(rollRight(y
, x
, 4) == 0xF1234567);
2351 static assert(0, "Unsupported size_t width");
2354 // Rolls double word (upper, lower) to the left by n bits and returns the
2355 // upper word of the result.
2356 private static size_t
rollLeft()(size_t upper
, size_t lower
, size_t nbits
)
2357 pure @safe nothrow @nogc
2360 assert(nbits
< bitsPerSizeT
, "nbits must be less than bitsPerSizeT");
2366 return (upper
<< nbits
) |
(lower
>> (bitsPerSizeT
- nbits
));
2371 static if (size_t
.sizeof
== 8)
2373 size_t x
= 0x12345678_90ABCDEF
;
2374 size_t y
= 0xFEDBCA09_87654321;
2376 assert(rollLeft(x
, y
, 32) == 0x90ABCDEF_FEDBCA
09);
2377 assert(rollLeft(y
, x
, 4) == 0xEDBCA098_76543211);
2379 else static if (size_t
.sizeof
== 4)
2381 size_t x
= 0x12345678;
2382 size_t y
= 0x90ABCDEF;
2384 assert(rollLeft(x
, y
, 16) == 0x567890AB);
2385 assert(rollLeft(y
, x
, 4) == 0x0ABCDEF1);
2390 * Operator `<<=` support.
2392 * Shifts all the bits in the array to the left by the given number of
2393 * bits. The leftmost bits are dropped, and 0's are appended to the end
2394 * to fill up the vacant bits.
2396 * $(RED Warning: unused bits in the final word up to the next word
2397 * boundary may be overwritten by this operation. It does not attempt to
2398 * preserve bits past the end of the array.)
2400 void opOpAssign(string op
)(size_t nbits
) @nogc pure nothrow
2403 size_t wordsToShift
= nbits
/ bitsPerSizeT
;
2404 size_t bitsToShift
= nbits
% bitsPerSizeT
;
2406 if (wordsToShift
< dim
)
2408 foreach_reverse (i
; 1 .. dim
- wordsToShift
)
2410 _ptr
[i
+ wordsToShift
] = rollLeft(_ptr
[i
], _ptr
[i
-1],
2413 _ptr
[wordsToShift
] = rollLeft(_ptr
[0], 0, bitsToShift
);
2416 import std
.algorithm
.comparison
: min
;
2417 foreach (i
; 0 .. min(wordsToShift
, dim
))
2424 * Operator `>>=` support.
2426 * Shifts all the bits in the array to the right by the given number of
2427 * bits. The rightmost bits are dropped, and 0's are inserted at the back
2428 * to fill up the vacant bits.
2430 * $(RED Warning: unused bits in the final word up to the next word
2431 * boundary may be overwritten by this operation. It does not attempt to
2432 * preserve bits past the end of the array.)
2434 void opOpAssign(string op
)(size_t nbits
) @nogc pure nothrow
2437 size_t wordsToShift
= nbits
/ bitsPerSizeT
;
2438 size_t bitsToShift
= nbits
% bitsPerSizeT
;
2440 if (wordsToShift
+ 1 < dim
)
2442 foreach (i
; 0 .. dim
- wordsToShift
- 1)
2444 _ptr
[i
] = rollRight(_ptr
[i
+ wordsToShift
+ 1],
2445 _ptr
[i
+ wordsToShift
], bitsToShift
);
2449 // The last word needs some care, as it must shift in 0's from past the
2450 // end of the array.
2451 if (wordsToShift
< dim
)
2453 if (bitsToShift
== 0)
2454 _ptr
[dim
- wordsToShift
- 1] = _ptr
[dim
- 1];
2457 // Special case: if endBits == 0, then also endMask == 0.
2458 size_t lastWord
= (endBits ?
(_ptr
[fullWords
] & endMask
) : _ptr
[fullWords
- 1]);
2459 _ptr
[dim
- wordsToShift
- 1] = rollRight(0, lastWord
, bitsToShift
);
2463 import std
.algorithm
.comparison
: min
;
2464 foreach (i
; 0 .. min(wordsToShift
, dim
))
2466 _ptr
[dim
- i
- 1] = 0;
2470 // https://issues.dlang.org/show_bug.cgi?id=17467
2473 import std
.algorithm
.comparison
: equal
;
2474 import std
.range
: iota
;
2476 bool[] buf
= new bool[64*3];
2477 buf
[0 .. 64] = true;
2478 BitArray b
= BitArray(buf
);
2479 assert(equal(b
.bitsSet
, iota(0, 64)));
2481 assert(equal(b
.bitsSet
, iota(64, 128)));
2483 buf
= new bool[64*3];
2484 buf
[64*2 .. 64*3] = true;
2486 assert(equal(b
.bitsSet
, iota(64*2, 64*3)));
2488 assert(equal(b
.bitsSet
, iota(64, 128)));
2491 // https://issues.dlang.org/show_bug.cgi?id=18134
2492 // shifting right when length is a multiple of 8 * size_t.sizeof.
2495 import std
.algorithm
.comparison
: equal
;
2496 import std
.array
: array
;
2497 import std
.range
: repeat
, iota
;
2499 immutable r
= size_t
.sizeof
* 8;
2501 BitArray a
= true.repeat(r
/ 2).array
;
2503 assert(a
.bitsSet
.equal(iota(0, r
/ 2)));
2505 assert(a
.bitsSet
.equal(iota(0, r
/ 2 - 1)));
2507 BitArray b
= true.repeat(r
).array
;
2509 assert(b
.bitsSet
.equal(iota(0, r
)));
2511 assert(b
.bitsSet
.equal(iota(0, r
- 1)));
2513 BitArray c
= true.repeat(2 * r
).array
;
2515 assert(c
.bitsSet
.equal(iota(0, 2 * r
)));
2517 assert(c
.bitsSet
.equal(iota(0, 2 * r
- 10)));
2523 import std
.format
: format
;
2525 auto b
= BitArray([1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1]);
2528 assert(format("%b", b
) == "01100_10101101");
2531 assert(format("%b", b
) == "11001_01011010");
2534 assert(format("%b", b
) == "00001_10010101");
2537 assert(format("%b", b
) == "10010_10100000");
2540 assert(format("%b", b
) == "00000_00000000");
2542 b
= BitArray([1, 0, 1, 1, 0, 1, 1, 1]);
2544 assert(format("%b", b
) == "00000000");
2548 // Test multi-word case
2551 import std
.format
: format
;
2553 // This has to be long enough to occupy more than one size_t. On 64-bit
2554 // machines, this would be at least 64 bits.
2556 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,
2557 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
2558 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0,
2559 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
2560 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1,
2563 assert(format("%b", b
) ==
2564 "00000000_10000000_"~
2565 "11000000_11100000_"~
2566 "11110000_11111000_"~
2567 "11111100_11111110_"~
2568 "11111111_10101010");
2570 // Test right shift of more than one size_t's worth of bits
2572 assert(format("%b", b
) ==
2573 "00000000_00000000_"~
2574 "00000000_00000000_"~
2575 "00000000_00000000_"~
2576 "00000000_00000000_"~
2577 "00000000_00001000");
2580 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,
2581 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
2582 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0,
2583 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
2584 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1,
2587 assert(format("%b", b
) ==
2588 "11000000_11100000_"~
2589 "11110000_11111000_"~
2590 "11111100_11111110_"~
2591 "11111111_10101010_"~
2592 "01010101_00000000");
2594 // Test left shift of more than 1 size_t's worth of bits
2596 assert(format("%b", b
) ==
2597 "01010000_00000000_"~
2598 "00000000_00000000_"~
2599 "00000000_00000000_"~
2600 "00000000_00000000_"~
2601 "00000000_00000000");
2604 /***************************************
2605 * Return a string representation of this BitArray.
2607 * Two format specifiers are supported:
2608 * $(LI $(B %s) which prints the bits as an array, and)
2609 * $(LI $(B %b) which prints the bits as 8-bit byte packets)
2610 * separated with an underscore.
2613 * sink = A `char` accepting
2614 * $(REF_ALTTEXT output range, isOutputRange, std, range, primitives).
2615 * fmt = A $(REF FormatSpec, std,format) which controls how the data
2618 void toString(W
)(ref W sink
, scope const ref FormatSpec
!char fmt
) const
2619 if (isOutputRange
!(W
, char))
2621 const spec
= fmt
.spec
;
2625 return formatBitString(sink
);
2627 return formatBitArray(sink
);
2629 throw new Exception("Unknown format specifier: %" ~ spec
);
2634 @system pure unittest
2636 import std
.format
: format
;
2638 auto b
= BitArray([0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1]);
2640 auto s1
= format("%s", b
);
2641 assert(s1
== "[0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1]");
2643 auto s2
= format("%b", b
);
2644 assert(s2
== "00001111_00001111");
2647 /***************************************
2648 * Return a lazy range of the indices of set bits.
2650 @property auto bitsSet() const nothrow
2652 import std
.algorithm
.iteration
: filter
, map
, joiner
;
2653 import std
.range
: iota
, chain
;
2657 .filter
!(i
=> _ptr
[i
])()
2658 .map
!(i
=> BitsSet
!size_t(_ptr
[i
], i
* bitsPerSizeT
))()
2660 iota(fullWords
* bitsPerSizeT
, _len
)
2661 .filter
!(i
=> this[i
])()
2668 import std
.algorithm
.comparison
: equal
;
2670 auto b1
= BitArray([0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1]);
2671 assert(b1
.bitsSet
.equal([4, 5, 6, 7, 12, 13, 14, 15]));
2678 assert(b2
.bitsSet
.equal([333, 666, 999]));
2683 import std
.algorithm
.comparison
: equal
;
2684 import std
.range
: iota
;
2687 enum wordBits
= size_t
.sizeof
* 8;
2688 b
= BitArray([size_t
.max
], 0);
2689 assert(b
.bitsSet
.empty
);
2690 b
= BitArray([size_t
.max
], 1);
2691 assert(b
.bitsSet
.equal([0]));
2692 b
= BitArray([size_t
.max
], wordBits
);
2693 assert(b
.bitsSet
.equal(iota(wordBits
)));
2694 b
= BitArray([size_t
.max
, size_t
.max
], wordBits
);
2695 assert(b
.bitsSet
.equal(iota(wordBits
)));
2696 b
= BitArray([size_t
.max
, size_t
.max
], wordBits
+ 1);
2697 assert(b
.bitsSet
.equal(iota(wordBits
+ 1)));
2698 b
= BitArray([size_t
.max
, size_t
.max
], wordBits
* 2);
2699 assert(b
.bitsSet
.equal(iota(wordBits
* 2)));
2702 // https://issues.dlang.org/show_bug.cgi?id=20241
2709 assert(ba
.bitsSet
.empty
);
2712 private void formatBitString(Writer
)(auto ref Writer sink
) const
2717 auto leftover
= _len
% 8;
2718 foreach (idx
; 0 .. leftover
)
2720 put(sink
, cast(char)(this[idx
] + '0'));
2723 if (leftover
&& _len
> 8)
2727 foreach (idx
; leftover
.. _len
)
2729 put(sink
, cast(char)(this[idx
] + '0'));
2730 if (++count
== 8 && idx
!= _len
- 1)
2738 private void formatBitArray(Writer
)(auto ref Writer sink
) const
2741 foreach (idx
; 0 .. _len
)
2743 put(sink
, cast(char)(this[idx
] + '0'));
2750 // https://issues.dlang.org/show_bug.cgi?id=20639
2751 // Separate @nogc test because public tests use array literals
2752 // (and workarounds needlessly uglify those examples)
2753 @system @nogc unittest
2756 BitArray b
= BitArray(buffer
[], buffer
.sizeof
* 8);
2762 cast(void) b
.count();
2766 /// Slicing & bitsSet
2769 import std
.algorithm
.comparison
: equal
;
2770 import std
.range
: iota
;
2772 bool[] buf
= new bool[64 * 3];
2773 buf
[0 .. 64] = true;
2774 BitArray b
= BitArray(buf
);
2775 assert(b
.bitsSet
.equal(iota(0, 64)));
2777 assert(b
.bitsSet
.equal(iota(64, 128)));
2780 /// Concatenation and appending
2783 import std
.algorithm
.comparison
: equal
;
2785 auto b
= BitArray([1, 0]);
2788 b
~= BitArray([0, 1]);
2789 auto c
= BitArray([1, 0, 1, 0, 1]);
2791 assert(b
.bitsSet
.equal([0, 2, 4]));
2797 import std
.algorithm
.comparison
: equal
;
2799 auto b
= BitArray([1, 1, 0, 1]);
2800 b
&= BitArray([0, 1, 1, 0]);
2801 assert(b
.bitsSet
.equal([1]));
2803 assert(b
.bitsSet
.equal([0, 2, 3]));
2806 /// String format of bitarrays
2809 import std
.format
: format
;
2810 auto b
= BitArray([1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1]);
2811 assert(format("%b", b
) == "1_00001111_00001111");
2817 import std
.format
: format
;
2822 assert(format("%s", b
) == "[]");
2823 assert(format("%b", b
) is null);
2826 assert(format("%s", b
) == "[1]");
2827 assert(format("%b", b
) == "1");
2829 b
= BitArray([0, 0, 0, 0]);
2830 assert(format("%b", b
) == "0000");
2832 b
= BitArray([0, 0, 0, 0, 1, 1, 1, 1]);
2833 assert(format("%s", b
) == "[0, 0, 0, 0, 1, 1, 1, 1]");
2834 assert(format("%b", b
) == "00001111");
2836 b
= BitArray([0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1]);
2837 assert(format("%s", b
) == "[0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1]");
2838 assert(format("%b", b
) == "00001111_00001111");
2840 b
= BitArray([1, 0, 0, 0, 0, 1, 1, 1, 1]);
2841 assert(format("%b", b
) == "1_00001111");
2843 b
= BitArray([1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1]);
2844 assert(format("%b", b
) == "1_00001111_00001111");
2851 foreach (ref bool b
; a
)
2861 Swaps the endianness of the given integral value or character.
2863 T
swapEndian(T
)(const T val
) @safe pure nothrow @nogc
2864 if (isIntegral
!T || isSomeChar
!T || isBoolean
!T
)
2866 import core
.bitop
: bswap, byteswap
;
2867 static if (val
.sizeof
== 1)
2869 else static if (T
.sizeof
== 2)
2870 return cast(T
) byteswap(cast(ushort) val
);
2871 else static if (T
.sizeof
== 4)
2872 return cast(T
) bswap(cast(uint) val
);
2873 else static if (T
.sizeof
== 8)
2874 return cast(T
) bswap(cast(ulong) val
);
2876 static assert(0, T
.stringof
~ " unsupported by swapEndian.");
2882 assert(42.swapEndian
== 704643072);
2883 assert(42.swapEndian
.swapEndian
== 42); // reflexive
2884 assert(1.swapEndian
== 16777216);
2886 assert(true.swapEndian
== true);
2887 assert(byte(10).swapEndian
== 10);
2888 assert(char(10).swapEndian
== 10);
2890 assert(ushort(10).swapEndian
== 2560);
2891 assert(long(10).swapEndian
== 720575940379279360);
2892 assert(ulong(10).swapEndian
== 720575940379279360);
2899 static foreach (T
; AliasSeq
!(bool, byte, ubyte, short, ushort, int, uint, long, ulong, char, wchar, dchar))
2901 scope(failure
) writeln("Failed type: ", T
.stringof
);
2906 assert(swapEndian(swapEndian(val
)) == val
);
2907 assert(swapEndian(swapEndian(cval
)) == cval
);
2908 assert(swapEndian(swapEndian(ival
)) == ival
);
2909 assert(swapEndian(swapEndian(T
.min
)) == T
.min
);
2910 assert(swapEndian(swapEndian(T
.max
)) == T
.max
);
2912 // Check CTFE compiles.
2913 static assert(swapEndian(swapEndian(T(1))) is T(1));
2915 foreach (i
; 2 .. 10)
2917 immutable T maxI
= cast(T
)(T
.max
/ i
);
2918 immutable T minI
= cast(T
)(T
.min
/ i
);
2920 assert(swapEndian(swapEndian(maxI
)) == maxI
);
2922 static if (isSigned
!T
)
2923 assert(swapEndian(swapEndian(minI
)) == minI
);
2926 static if (isSigned
!T
)
2927 assert(swapEndian(swapEndian(cast(T
) 0)) == 0);
2929 // used to trigger https://issues.dlang.org/show_bug.cgi?id=6354
2930 static if (T
.sizeof
> 1 && isUnsigned
!T
)
2933 left
<<= (T
.sizeof
- 1) * 8;
2936 for (size_t i
= 1; i
< T
.sizeof
; ++i
)
2938 assert(swapEndian(left
) == right
);
2939 assert(swapEndian(right
) == left
);
2949 Converts the given value from the native endianness to big endian and
2950 returns it as a `ubyte[n]` where `n` is the size of the given type.
2952 Returning a `ubyte[n]` helps prevent accidentally using a swapped value
2953 as a regular one (and in the case of floating point values, it's necessary,
2954 because the FPU will mess up any swapped floating point values. So, you
2955 can't actually have swapped floating point values as floating point values).
2957 `real` is not supported, because its size is implementation-dependent
2958 and therefore could vary from machine to machine (which could make it
2959 unusable if you tried to transfer it to another machine).
2961 auto nativeToBigEndian(T
)(const T val
) @trusted pure nothrow @nogc
2962 if (canSwapEndianness
!T
)
2964 static if (isFloatOrDouble
!T
)
2965 return nativeToBigEndian(*cast(const UnsignedOfSize
!(T
.sizeof
)*) &val
);
2968 enum len
= T
.sizeof
;
2971 static foreach (i
; 0 .. len
)
2972 retval
[i
] = cast(ubyte)(val
>> (len
- i
- 1) * 8);
2982 ubyte[4] swappedI
= nativeToBigEndian(i
);
2983 assert(i
== bigEndianToNative
!int(swappedI
));
2986 ubyte[4] swappedF
= nativeToBigEndian(f
);
2987 assert(f
== bigEndianToNative
!float(swappedF
));
2989 const float cf
= 123.45f;
2990 ubyte[4] swappedCF
= nativeToBigEndian(cf
);
2991 assert(cf
== bigEndianToNative
!float(swappedCF
));
2994 ubyte[8] swappedD
= nativeToBigEndian(d
);
2995 assert(d
== bigEndianToNative
!double(swappedD
));
2997 const double cd
= 123.45;
2998 ubyte[8] swappedCD
= nativeToBigEndian(cd
);
2999 assert(cd
== bigEndianToNative
!double(swappedCD
));
3006 static foreach (T
; AliasSeq
!(bool, byte, ubyte, short, ushort, int, uint, long, ulong,
3008 /* The trouble here is with floats and doubles being compared against nan
3009 * using a bit compare. There are two kinds of nans, quiet and signaling.
3010 * When a nan passes through the x87, it converts signaling to quiet.
3011 * When a nan passes through the XMM, it does not convert signaling to quiet.
3012 * float.init is a signaling nan.
3013 * The binary API sometimes passes the data through the XMM, sometimes through
3014 * the x87, meaning these will fail the 'is' bit compare under some circumstances.
3015 * I cannot think of a fix for this that makes consistent sense.
3017 /*,float, double*/))
3019 scope(failure
) writeln("Failed type: ", T
.stringof
);
3024 //is instead of == because of NaN for floating point values.
3025 assert(bigEndianToNative
!T(nativeToBigEndian(val
)) is val
);
3026 assert(bigEndianToNative
!T(nativeToBigEndian(cval
)) is cval
);
3027 assert(bigEndianToNative
!T(nativeToBigEndian(ival
)) is ival
);
3028 assert(bigEndianToNative
!T(nativeToBigEndian(T
.min
)) == T
.min
);
3029 assert(bigEndianToNative
!T(nativeToBigEndian(T
.max
)) == T
.max
);
3031 //Check CTFE compiles.
3032 static assert(bigEndianToNative
!T(nativeToBigEndian(T(1))) is T(1));
3034 static if (isSigned
!T
)
3035 assert(bigEndianToNative
!T(nativeToBigEndian(cast(T
) 0)) == 0);
3037 static if (!is(T
== bool))
3039 foreach (i
; [2, 4, 6, 7, 9, 11])
3041 immutable T maxI
= cast(T
)(T
.max
/ i
);
3042 immutable T minI
= cast(T
)(T
.min
/ i
);
3044 assert(bigEndianToNative
!T(nativeToBigEndian(maxI
)) == maxI
);
3046 static if (T
.sizeof
> 1)
3047 assert(nativeToBigEndian(maxI
) != nativeToLittleEndian(maxI
));
3049 assert(nativeToBigEndian(maxI
) == nativeToLittleEndian(maxI
));
3051 static if (isSigned
!T
)
3053 assert(bigEndianToNative
!T(nativeToBigEndian(minI
)) == minI
);
3055 static if (T
.sizeof
> 1)
3056 assert(nativeToBigEndian(minI
) != nativeToLittleEndian(minI
));
3058 assert(nativeToBigEndian(minI
) == nativeToLittleEndian(minI
));
3063 static if (isUnsigned
!T || T
.sizeof
== 1 ||
is(T
== wchar))
3064 assert(nativeToBigEndian(T
.max
) == nativeToLittleEndian(T
.max
));
3066 assert(nativeToBigEndian(T
.max
) != nativeToLittleEndian(T
.max
));
3068 static if (isUnsigned
!T || T
.sizeof
== 1 || isSomeChar
!T
)
3069 assert(nativeToBigEndian(T
.min
) == nativeToLittleEndian(T
.min
));
3071 assert(nativeToBigEndian(T
.min
) != nativeToLittleEndian(T
.min
));
3077 Converts the given value from big endian to the native endianness and
3078 returns it. The value is given as a `ubyte[n]` where `n` is the size
3079 of the target type. You must give the target type as a template argument,
3080 because there are multiple types with the same size and so the type of the
3081 argument is not enough to determine the return type.
3083 Taking a `ubyte[n]` helps prevent accidentally using a swapped value
3084 as a regular one (and in the case of floating point values, it's necessary,
3085 because the FPU will mess up any swapped floating point values. So, you
3086 can't actually have swapped floating point values as floating point values).
3088 T
bigEndianToNative(T
, size_t n
)(ubyte[n
] val
) @trusted pure nothrow @nogc
3089 if (canSwapEndianness
!T
&& n
== T
.sizeof
)
3091 static if (isFloatOrDouble
!T
)
3093 auto retval
= bigEndianToNative
!(UnsignedOfSize
!(T
.sizeof
))(val
);
3094 return *cast(const T
*) &retval
;
3098 enum len
= T
.sizeof
;
3099 alias U
= UnsignedOfSize
!len
;
3102 static foreach (i
; 0 .. len
)
3103 retval |
= (cast(U
) val
[i
]) << (len
- i
- 1) * 8;
3105 return cast(T
) retval
;
3113 ubyte[2] swappedI
= nativeToBigEndian(i
);
3114 assert(i
== bigEndianToNative
!ushort(swappedI
));
3117 ubyte[4] swappedC
= nativeToBigEndian(c
);
3118 assert(c
== bigEndianToNative
!dchar(swappedC
));
3122 Converts the given value from the native endianness to little endian and
3123 returns it as a `ubyte[n]` where `n` is the size of the given type.
3125 Returning a `ubyte[n]` helps prevent accidentally using a swapped value
3126 as a regular one (and in the case of floating point values, it's necessary,
3127 because the FPU will mess up any swapped floating point values. So, you
3128 can't actually have swapped floating point values as floating point values).
3130 auto nativeToLittleEndian(T
)(const T val
) @trusted pure nothrow @nogc
3131 if (canSwapEndianness
!T
)
3133 static if (isFloatOrDouble
!T
)
3134 return nativeToLittleEndian(*cast(const UnsignedOfSize
!(T
.sizeof
)*) &val
);
3137 enum len
= T
.sizeof
;
3140 static foreach (i
; 0 .. len
)
3141 retval
[i
] = cast(ubyte)(val
>> i
* 8);
3151 ubyte[4] swappedI
= nativeToLittleEndian(i
);
3152 assert(i
== littleEndianToNative
!int(swappedI
));
3155 ubyte[4] swappedF
= nativeToLittleEndian(f
);
3156 assert(f
== littleEndianToNative
!float(swappedF
));
3158 const float cf
= 123.45f;
3159 ubyte[4] swappedCF
= nativeToLittleEndian(cf
);
3160 assert(cf
== littleEndianToNative
!float(swappedCF
));
3163 ubyte[8] swappedD
= nativeToLittleEndian(d
);
3164 assert(d
== littleEndianToNative
!double(swappedD
));
3166 const double cd
= 123.45;
3167 ubyte[8] swappedCD
= nativeToLittleEndian(cd
);
3168 assert(cd
== littleEndianToNative
!double(swappedCD
));
3175 static foreach (T
; AliasSeq
!(bool, byte, ubyte, short, ushort, int, uint, long, ulong,
3176 char, wchar, dchar/*,
3179 scope(failure
) writeln("Failed type: ", T
.stringof
);
3184 //is instead of == because of NaN for floating point values.
3185 assert(littleEndianToNative
!T(nativeToLittleEndian(val
)) is val
);
3186 assert(littleEndianToNative
!T(nativeToLittleEndian(cval
)) is cval
);
3187 assert(littleEndianToNative
!T(nativeToLittleEndian(ival
)) is ival
);
3188 assert(littleEndianToNative
!T(nativeToLittleEndian(T
.min
)) == T
.min
);
3189 assert(littleEndianToNative
!T(nativeToLittleEndian(T
.max
)) == T
.max
);
3191 //Check CTFE compiles.
3192 static assert(littleEndianToNative
!T(nativeToLittleEndian(T(1))) is T(1));
3194 static if (isSigned
!T
)
3195 assert(littleEndianToNative
!T(nativeToLittleEndian(cast(T
) 0)) == 0);
3197 static if (!is(T
== bool))
3199 foreach (i
; 2 .. 10)
3201 immutable T maxI
= cast(T
)(T
.max
/ i
);
3202 immutable T minI
= cast(T
)(T
.min
/ i
);
3204 assert(littleEndianToNative
!T(nativeToLittleEndian(maxI
)) == maxI
);
3206 static if (isSigned
!T
)
3207 assert(littleEndianToNative
!T(nativeToLittleEndian(minI
)) == minI
);
3215 Converts the given value from little endian to the native endianness and
3216 returns it. The value is given as a `ubyte[n]` where `n` is the size
3217 of the target type. You must give the target type as a template argument,
3218 because there are multiple types with the same size and so the type of the
3219 argument is not enough to determine the return type.
3221 Taking a `ubyte[n]` helps prevent accidentally using a swapped value
3222 as a regular one (and in the case of floating point values, it's necessary,
3223 because the FPU will mess up any swapped floating point values. So, you
3224 can't actually have swapped floating point values as floating point values).
3226 `real` is not supported, because its size is implementation-dependent
3227 and therefore could vary from machine to machine (which could make it
3228 unusable if you tried to transfer it to another machine).
3230 T
littleEndianToNative(T
, size_t n
)(ubyte[n
] val
) @trusted pure nothrow @nogc
3231 if (canSwapEndianness
!T
&& n
== T
.sizeof
)
3233 static if (isFloatOrDouble
!T
)
3235 auto retval
= littleEndianToNative
!(UnsignedOfSize
!(T
.sizeof
))(val
);
3236 return *cast(const T
*) &retval
;
3240 enum len
= T
.sizeof
;
3241 alias U
= UnsignedOfSize
!len
;
3244 static foreach (i
; 0 .. len
)
3245 retval |
= (cast(U
) val
[i
]) << i
* 8;
3247 return cast(T
) retval
;
3255 ubyte[2] swappedI
= nativeToLittleEndian(i
);
3256 assert(i
== littleEndianToNative
!ushort(swappedI
));
3259 ubyte[4] swappedC
= nativeToLittleEndian(c
);
3260 assert(c
== littleEndianToNative
!dchar(swappedC
));
3263 private template isFloatOrDouble(T
)
3265 enum isFloatOrDouble
= isFloatingPoint
!T
&&
3266 !is(immutable FloatingPointTypeOf
!T
== immutable real);
3272 static foreach (T
; AliasSeq
!(float, double))
3274 static assert(isFloatOrDouble
!(T
));
3275 static assert(isFloatOrDouble
!(const T
));
3276 static assert(isFloatOrDouble
!(immutable T
));
3277 static assert(isFloatOrDouble
!(shared T
));
3278 static assert(isFloatOrDouble
!(shared(const T
)));
3279 static assert(isFloatOrDouble
!(shared(immutable T
)));
3282 static assert(!isFloatOrDouble
!(real));
3283 static assert(!isFloatOrDouble
!(const real));
3284 static assert(!isFloatOrDouble
!(immutable real));
3285 static assert(!isFloatOrDouble
!(shared real));
3286 static assert(!isFloatOrDouble
!(shared(const real)));
3287 static assert(!isFloatOrDouble
!(shared(immutable real)));
3290 private template canSwapEndianness(T
)
3292 enum canSwapEndianness
= isIntegral
!T ||
3301 static foreach (T
; AliasSeq
!(bool, ubyte, byte, ushort, short, uint, int, ulong,
3302 long, char, wchar, dchar, float, double))
3304 static assert(canSwapEndianness
!(T
));
3305 static assert(canSwapEndianness
!(const T
));
3306 static assert(canSwapEndianness
!(immutable T
));
3307 static assert(canSwapEndianness
!(shared(T
)));
3308 static assert(canSwapEndianness
!(shared(const T
)));
3309 static assert(canSwapEndianness
!(shared(immutable T
)));
3313 static foreach (T
; AliasSeq
!(real, string
, wstring
, dstring
))
3315 static assert(!canSwapEndianness
!(T
));
3316 static assert(!canSwapEndianness
!(const T
));
3317 static assert(!canSwapEndianness
!(immutable T
));
3318 static assert(!canSwapEndianness
!(shared(T
)));
3319 static assert(!canSwapEndianness
!(shared(const T
)));
3320 static assert(!canSwapEndianness
!(shared(immutable T
)));
3324 private template UnsignedOfSize(size_t n
)
3327 alias UnsignedOfSize
= ulong;
3328 else static if (n
== 4)
3329 alias UnsignedOfSize
= uint;
3330 else static if (n
== 2)
3331 alias UnsignedOfSize
= ushort;
3332 else static if (n
== 1)
3333 alias UnsignedOfSize
= ubyte;
3335 alias UnsignedOfSize
= void;
3340 static assert(is(UnsignedOfSize
!(byte.sizeof
) == ubyte));
3341 static assert(is(UnsignedOfSize
!(ubyte.sizeof
) == ubyte));
3342 static assert(is(UnsignedOfSize
!(short.sizeof
) == ushort));
3343 static assert(is(UnsignedOfSize
!(ushort.sizeof
) == ushort));
3344 static assert(is(UnsignedOfSize
!(int.sizeof
) == uint));
3345 static assert(is(UnsignedOfSize
!(uint.sizeof
) == uint));
3346 static assert(is(UnsignedOfSize
!(long.sizeof
) == ulong));
3347 static assert(is(UnsignedOfSize
!(ulong.sizeof
) == ulong));
3349 static assert(is(UnsignedOfSize
!(bool.sizeof
) == ubyte));
3350 static assert(is(UnsignedOfSize
!(char.sizeof
) == ubyte));
3351 static assert(is(UnsignedOfSize
!(wchar.sizeof
) == ushort));
3352 static assert(is(UnsignedOfSize
!(dchar.sizeof
) == uint));
3354 static assert(is(UnsignedOfSize
!(float.sizeof
) == uint));
3355 static assert(is(UnsignedOfSize
!(double.sizeof
) == ulong));
3357 static assert(is(UnsignedOfSize
!10 == void));
3361 Takes a range of `ubyte`s and converts the first `T.sizeof` bytes to
3362 `T`. The value returned is converted from the given endianness to the
3363 native endianness. The range is not consumed.
3366 T = The integral type to convert the first `T.sizeof` bytes to.
3367 endianness = The endianness that the bytes are assumed to be in.
3368 range = The range to read from.
3369 index = The index to start reading from (instead of starting at the
3370 front). If index is a pointer, then it is updated to the index
3371 after the bytes read. The overloads with index are only
3372 available if `hasSlicing!R` is `true`.
3375 T
peek(T
, Endian endianness
= Endian
.bigEndian
, R
)(R range
)
3376 if (canSwapEndianness
!T
&&
3378 is(ElementType
!R
: const ubyte))
3380 static if (hasSlicing
!R
)
3381 const ubyte[T
.sizeof
] bytes
= range
[0 .. T
.sizeof
];
3384 ubyte[T
.sizeof
] bytes
;
3385 //Make sure that range is not consumed, even if it's a class.
3388 foreach (ref e
; bytes
)
3395 static if (endianness
== Endian
.bigEndian
)
3396 return bigEndianToNative
!T(bytes
);
3398 return littleEndianToNative
!T(bytes
);
3402 T
peek(T
, Endian endianness
= Endian
.bigEndian
, R
)(R range
, size_t index
)
3403 if (canSwapEndianness
!T
&&
3406 is(ElementType
!R
: const ubyte))
3408 return peek
!(T
, endianness
)(range
, &index
);
3412 T
peek(T
, Endian endianness
= Endian
.bigEndian
, R
)(R range
, size_t
* index
)
3413 if (canSwapEndianness
!T
&&
3416 is(ElementType
!R
: const ubyte))
3418 assert(index
, "index must not point to null");
3420 immutable begin
= *index
;
3421 immutable end
= begin
+ T
.sizeof
;
3422 const ubyte[T
.sizeof
] bytes
= range
[begin
.. end
];
3425 static if (endianness
== Endian
.bigEndian
)
3426 return bigEndianToNative
!T(bytes
);
3428 return littleEndianToNative
!T(bytes
);
3434 ubyte[] buffer
= [1, 5, 22, 9, 44, 255, 8];
3435 assert(buffer
.peek
!uint() == 17110537);
3436 assert(buffer
.peek
!ushort() == 261);
3437 assert(buffer
.peek
!ubyte() == 1);
3439 assert(buffer
.peek
!uint(2) == 369700095);
3440 assert(buffer
.peek
!ushort(2) == 5641);
3441 assert(buffer
.peek
!ubyte(2) == 22);
3444 assert(buffer
.peek
!ushort(&index
) == 261);
3447 assert(buffer
.peek
!uint(&index
) == 369700095);
3450 assert(buffer
.peek
!ubyte(&index
) == 8);
3457 import std
.algorithm
.iteration
: filter
;
3458 ubyte[] buffer
= [1, 5, 22, 9, 44, 255, 7];
3459 auto range
= filter
!"true"(buffer
);
3460 assert(range
.peek
!uint() == 17110537);
3461 assert(range
.peek
!ushort() == 261);
3462 assert(range
.peek
!ubyte() == 1);
3469 ubyte[] buffer
= [0, 1];
3470 assert(buffer
.peek
!bool() == false);
3471 assert(buffer
.peek
!bool(1) == true);
3474 assert(buffer
.peek
!bool(&index
) == false);
3477 assert(buffer
.peek
!bool(&index
) == true);
3483 ubyte[] buffer
= [97, 98, 99, 100];
3484 assert(buffer
.peek
!char() == 'a');
3485 assert(buffer
.peek
!char(1) == 'b');
3488 assert(buffer
.peek
!char(&index
) == 'a');
3491 assert(buffer
.peek
!char(&index
) == 'b');
3496 //wchar (16bit - 2x ubyte)
3497 ubyte[] buffer
= [1, 5, 32, 29, 1, 7];
3498 assert(buffer
.peek
!wchar() == 'ą');
3499 assert(buffer
.peek
!wchar(2) == '”');
3500 assert(buffer
.peek
!wchar(4) == 'ć');
3503 assert(buffer
.peek
!wchar(&index
) == 'ą');
3506 assert(buffer
.peek
!wchar(&index
) == '”');
3509 assert(buffer
.peek
!wchar(&index
) == 'ć');
3514 //dchar (32bit - 4x ubyte)
3515 ubyte[] buffer
= [0, 0, 1, 5, 0, 0, 32, 29, 0, 0, 1, 7];
3516 assert(buffer
.peek
!dchar() == 'ą');
3517 assert(buffer
.peek
!dchar(4) == '”');
3518 assert(buffer
.peek
!dchar(8) == 'ć');
3521 assert(buffer
.peek
!dchar(&index
) == 'ą');
3524 assert(buffer
.peek
!dchar(&index
) == '”');
3527 assert(buffer
.peek
!dchar(&index
) == 'ć');
3528 assert(index
== 12);
3532 //float (32bit - 4x ubyte)
3533 ubyte[] buffer
= [66, 0, 0, 0, 65, 200, 0, 0];
3534 assert(buffer
.peek
!float()== 32.0);
3535 assert(buffer
.peek
!float(4) == 25.0f);
3538 assert(buffer
.peek
!float(&index
) == 32.0f);
3541 assert(buffer
.peek
!float(&index
) == 25.0f);
3546 //double (64bit - 8x ubyte)
3547 ubyte[] buffer
= [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0];
3548 assert(buffer
.peek
!double() == 32.0);
3549 assert(buffer
.peek
!double(8) == 25.0);
3552 assert(buffer
.peek
!double(&index
) == 32.0);
3555 assert(buffer
.peek
!double(&index
) == 25.0);
3556 assert(index
== 16);
3561 ubyte[] buffer
= [0, 0, 0, 10, 0, 0, 0, 20, 0, 0, 0, 30];
3570 assert(buffer
.peek
!Foo() == Foo
.one
);
3571 assert(buffer
.peek
!Foo(0) == Foo
.one
);
3572 assert(buffer
.peek
!Foo(4) == Foo
.two
);
3573 assert(buffer
.peek
!Foo(8) == Foo
.three
);
3576 assert(buffer
.peek
!Foo(&index
) == Foo
.one
);
3579 assert(buffer
.peek
!Foo(&index
) == Foo
.two
);
3582 assert(buffer
.peek
!Foo(&index
) == Foo
.three
);
3583 assert(index
== 12);
3588 ubyte[] buffer
= [0, 1];
3596 assert(buffer
.peek
!Bool() == Bool
.bfalse
);
3597 assert(buffer
.peek
!Bool(0) == Bool
.bfalse
);
3598 assert(buffer
.peek
!Bool(1) == Bool
.btrue
);
3601 assert(buffer
.peek
!Bool(&index
) == Bool
.bfalse
);
3604 assert(buffer
.peek
!Bool(&index
) == Bool
.btrue
);
3610 ubyte[] buffer
= [66, 0, 0, 0, 65, 200, 0, 0];
3618 assert(buffer
.peek
!Float() == Float
.one
);
3619 assert(buffer
.peek
!Float(0) == Float
.one
);
3620 assert(buffer
.peek
!Float(4) == Float
.two
);
3623 assert(buffer
.peek
!Float(&index
) == Float
.one
);
3626 assert(buffer
.peek
!Float(&index
) == Float
.two
);
3632 ubyte[] buffer
= [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0];
3640 assert(buffer
.peek
!Double() == Double
.one
);
3641 assert(buffer
.peek
!Double(0) == Double
.one
);
3642 assert(buffer
.peek
!Double(8) == Double
.two
);
3645 assert(buffer
.peek
!Double(&index
) == Double
.one
);
3648 assert(buffer
.peek
!Double(&index
) == Double
.two
);
3649 assert(index
== 16);
3654 ubyte[] buffer
= [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0];
3662 static assert(!__traits(compiles
, buffer
.peek
!Real()));
3667 Takes a range of `ubyte`s and converts the first `T.sizeof` bytes to
3668 `T`. The value returned is converted from the given endianness to the
3669 native endianness. The `T.sizeof` bytes which are read are consumed from
3673 T = The integral type to convert the first `T.sizeof` bytes to.
3674 endianness = The endianness that the bytes are assumed to be in.
3675 range = The range to read from.
3677 T
read(T
, Endian endianness
= Endian
.bigEndian
, R
)(ref R range
)
3678 if (canSwapEndianness
!T
&& isInputRange
!R
&& is(ElementType
!R
: const ubyte))
3680 static if (hasSlicing
!R
&& is(typeof(R
.init
[0 .. 0]) : const(ubyte)[]))
3682 const ubyte[T
.sizeof
] bytes
= range
[0 .. T
.sizeof
];
3683 range
.popFrontN(T
.sizeof
);
3687 ubyte[T
.sizeof
] bytes
;
3689 foreach (ref e
; bytes
)
3696 static if (endianness
== Endian
.bigEndian
)
3697 return bigEndianToNative
!T(bytes
);
3699 return littleEndianToNative
!T(bytes
);
3705 import std
.range
.primitives
: empty
;
3706 ubyte[] buffer
= [1, 5, 22, 9, 44, 255, 8];
3707 assert(buffer
.length
== 7);
3709 assert(buffer
.read
!ushort() == 261);
3710 assert(buffer
.length
== 5);
3712 assert(buffer
.read
!uint() == 369700095);
3713 assert(buffer
.length
== 1);
3715 assert(buffer
.read
!ubyte() == 8);
3716 assert(buffer
.empty
);
3723 ubyte[] buffer
= [0, 1];
3724 assert(buffer
.length
== 2);
3726 assert(buffer
.read
!bool() == false);
3727 assert(buffer
.length
== 1);
3729 assert(buffer
.read
!bool() == true);
3730 assert(buffer
.empty
);
3735 ubyte[] buffer
= [97, 98, 99];
3736 assert(buffer
.length
== 3);
3738 assert(buffer
.read
!char() == 'a');
3739 assert(buffer
.length
== 2);
3741 assert(buffer
.read
!char() == 'b');
3742 assert(buffer
.length
== 1);
3744 assert(buffer
.read
!char() == 'c');
3745 assert(buffer
.empty
);
3749 //wchar (16bit - 2x ubyte)
3750 ubyte[] buffer
= [1, 5, 32, 29, 1, 7];
3751 assert(buffer
.length
== 6);
3753 assert(buffer
.read
!wchar() == 'ą');
3754 assert(buffer
.length
== 4);
3756 assert(buffer
.read
!wchar() == '”');
3757 assert(buffer
.length
== 2);
3759 assert(buffer
.read
!wchar() == 'ć');
3760 assert(buffer
.empty
);
3764 //dchar (32bit - 4x ubyte)
3765 ubyte[] buffer
= [0, 0, 1, 5, 0, 0, 32, 29, 0, 0, 1, 7];
3766 assert(buffer
.length
== 12);
3768 assert(buffer
.read
!dchar() == 'ą');
3769 assert(buffer
.length
== 8);
3771 assert(buffer
.read
!dchar() == '”');
3772 assert(buffer
.length
== 4);
3774 assert(buffer
.read
!dchar() == 'ć');
3775 assert(buffer
.empty
);
3779 //float (32bit - 4x ubyte)
3780 ubyte[] buffer
= [66, 0, 0, 0, 65, 200, 0, 0];
3781 assert(buffer
.length
== 8);
3783 assert(buffer
.read
!float()== 32.0);
3784 assert(buffer
.length
== 4);
3786 assert(buffer
.read
!float() == 25.0f);
3787 assert(buffer
.empty
);
3791 //double (64bit - 8x ubyte)
3792 ubyte[] buffer
= [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0];
3793 assert(buffer
.length
== 16);
3795 assert(buffer
.read
!double() == 32.0);
3796 assert(buffer
.length
== 8);
3798 assert(buffer
.read
!double() == 25.0);
3799 assert(buffer
.empty
);
3804 ubyte[] buffer
= [0, 0, 0, 10, 0, 0, 0, 20, 0, 0, 0, 30];
3805 assert(buffer
.length
== 12);
3814 assert(buffer
.read
!Foo() == Foo
.one
);
3815 assert(buffer
.length
== 8);
3817 assert(buffer
.read
!Foo() == Foo
.two
);
3818 assert(buffer
.length
== 4);
3820 assert(buffer
.read
!Foo() == Foo
.three
);
3821 assert(buffer
.empty
);
3826 ubyte[] buffer
= [0, 1];
3827 assert(buffer
.length
== 2);
3835 assert(buffer
.read
!Bool() == Bool
.bfalse
);
3836 assert(buffer
.length
== 1);
3838 assert(buffer
.read
!Bool() == Bool
.btrue
);
3839 assert(buffer
.empty
);
3844 ubyte[] buffer
= [66, 0, 0, 0, 65, 200, 0, 0];
3845 assert(buffer
.length
== 8);
3853 assert(buffer
.read
!Float() == Float
.one
);
3854 assert(buffer
.length
== 4);
3856 assert(buffer
.read
!Float() == Float
.two
);
3857 assert(buffer
.empty
);
3862 ubyte[] buffer
= [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0];
3863 assert(buffer
.length
== 16);
3871 assert(buffer
.read
!Double() == Double
.one
);
3872 assert(buffer
.length
== 8);
3874 assert(buffer
.read
!Double() == Double
.two
);
3875 assert(buffer
.empty
);
3880 ubyte[] buffer
= [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0];
3888 static assert(!__traits(compiles
, buffer
.read
!Real()));
3892 // https://issues.dlang.org/show_bug.cgi?id=17247
3898 @property bool empty() { return impl
.empty
; }
3899 @property ubyte front() { return impl
.front
; }
3900 void popFront() { impl
.popFront(); }
3901 @property UbyteRange
save() { return this; }
3903 // N.B. support slicing but do not return ubyte[] slices.
3904 UbyteRange
opSlice(size_t start
, size_t end
)
3906 return UbyteRange(impl
[start
.. end
]);
3908 @property size_t
length() { return impl
.length
; }
3909 alias opDollar
= length
;
3911 static assert(hasSlicing
!UbyteRange
);
3913 auto r
= UbyteRange([0x01, 0x00, 0x00, 0x00]);
3914 int x
= r
.read
!(int, Endian
.littleEndian
)();
3920 Takes an integral value, converts it to the given endianness, and writes it
3921 to the given range of `ubyte`s as a sequence of `T.sizeof` `ubyte`s
3922 starting at index. `hasSlicing!R` must be `true`.
3925 T = The integral type to convert the first `T.sizeof` bytes to.
3926 endianness = The endianness to _write the bytes in.
3927 range = The range to _write to.
3928 value = The value to _write.
3929 index = The index to start writing to. If index is a pointer, then it
3930 is updated to the index after the bytes read.
3932 void write(T
, Endian endianness
= Endian
.bigEndian
, R
)(R range
, const T value
, size_t index
)
3933 if (canSwapEndianness
!T
&&
3936 is(ElementType
!R
: ubyte))
3938 write
!(T
, endianness
)(range
, value
, &index
);
3942 void write(T
, Endian endianness
= Endian
.bigEndian
, R
)(R range
, const T value
, size_t
* index
)
3943 if (canSwapEndianness
!T
&&
3946 is(ElementType
!R
: ubyte))
3948 assert(index
, "index must not point to null");
3950 static if (endianness
== Endian
.bigEndian
)
3951 immutable bytes
= nativeToBigEndian
!T(value
);
3953 immutable bytes
= nativeToLittleEndian
!T(value
);
3955 immutable begin
= *index
;
3956 immutable end
= begin
+ T
.sizeof
;
3958 range
[begin
.. end
] = bytes
[0 .. T
.sizeof
];
3964 ubyte[] buffer
= [0, 0, 0, 0, 0, 0, 0, 0];
3965 buffer
.write
!uint(29110231u, 0);
3966 assert(buffer
== [1, 188, 47, 215, 0, 0, 0, 0]);
3968 buffer
.write
!ushort(927, 0);
3969 assert(buffer
== [3, 159, 47, 215, 0, 0, 0, 0]);
3971 buffer
.write
!ubyte(42, 0);
3972 assert(buffer
== [42, 159, 47, 215, 0, 0, 0, 0]);
3978 ubyte[] buffer
= [0, 0, 0, 0, 0, 0, 0, 0, 0];
3979 buffer
.write
!uint(142700095u, 2);
3980 assert(buffer
== [0, 0, 8, 129, 110, 63, 0, 0, 0]);
3982 buffer
.write
!ushort(19839, 2);
3983 assert(buffer
== [0, 0, 77, 127, 110, 63, 0, 0, 0]);
3985 buffer
.write
!ubyte(132, 2);
3986 assert(buffer
== [0, 0, 132, 127, 110, 63, 0, 0, 0]);
3992 ubyte[] buffer
= [0, 0, 0, 0, 0, 0, 0, 0];
3994 buffer
.write
!ushort(261, &index
);
3995 assert(buffer
== [1, 5, 0, 0, 0, 0, 0, 0]);
3998 buffer
.write
!uint(369700095u, &index
);
3999 assert(buffer
== [1, 5, 22, 9, 44, 255, 0, 0]);
4002 buffer
.write
!ubyte(8, &index
);
4003 assert(buffer
== [1, 5, 22, 9, 44, 255, 8, 0]);
4010 ubyte[] buffer
= [0, 0];
4011 buffer
.write
!bool(false, 0);
4012 assert(buffer
== [0, 0]);
4014 buffer
.write
!bool(true, 0);
4015 assert(buffer
== [1, 0]);
4017 buffer
.write
!bool(true, 1);
4018 assert(buffer
== [1, 1]);
4020 buffer
.write
!bool(false, 1);
4021 assert(buffer
== [1, 0]);
4024 buffer
.write
!bool(false, &index
);
4025 assert(buffer
== [0, 0]);
4028 buffer
.write
!bool(true, &index
);
4029 assert(buffer
== [0, 1]);
4036 ubyte[] buffer
= [0, 0, 0];
4038 buffer
.write
!char('a', 0);
4039 assert(buffer
== [97, 0, 0]);
4041 buffer
.write
!char('b', 1);
4042 assert(buffer
== [97, 98, 0]);
4045 buffer
.write
!char('a', &index
);
4046 assert(buffer
== [97, 98, 0]);
4049 buffer
.write
!char('b', &index
);
4050 assert(buffer
== [97, 98, 0]);
4053 buffer
.write
!char('c', &index
);
4054 assert(buffer
== [97, 98, 99]);
4058 /// wchar (16bit - 2x ubyte)
4061 ubyte[] buffer
= [0, 0, 0, 0];
4063 buffer
.write
!wchar('ą', 0);
4064 assert(buffer
== [1, 5, 0, 0]);
4066 buffer
.write
!wchar('”', 2);
4067 assert(buffer
== [1, 5, 32, 29]);
4070 buffer
.write
!wchar('ć', &index
);
4071 assert(buffer
== [1, 7, 32, 29]);
4074 buffer
.write
!wchar('ą', &index
);
4075 assert(buffer
== [1, 7, 1, 5]);
4079 /// dchar (32bit - 4x ubyte)
4082 ubyte[] buffer
= [0, 0, 0, 0, 0, 0, 0, 0];
4084 buffer
.write
!dchar('ą', 0);
4085 assert(buffer
== [0, 0, 1, 5, 0, 0, 0, 0]);
4087 buffer
.write
!dchar('”', 4);
4088 assert(buffer
== [0, 0, 1, 5, 0, 0, 32, 29]);
4091 buffer
.write
!dchar('ć', &index
);
4092 assert(buffer
== [0, 0, 1, 7, 0, 0, 32, 29]);
4095 buffer
.write
!dchar('ą', &index
);
4096 assert(buffer
== [0, 0, 1, 7, 0, 0, 1, 5]);
4100 /// float (32bit - 4x ubyte)
4103 ubyte[] buffer
= [0, 0, 0, 0, 0, 0, 0, 0];
4105 buffer
.write
!float(32.0f, 0);
4106 assert(buffer
== [66, 0, 0, 0, 0, 0, 0, 0]);
4108 buffer
.write
!float(25.0f, 4);
4109 assert(buffer
== [66, 0, 0, 0, 65, 200, 0, 0]);
4112 buffer
.write
!float(25.0f, &index
);
4113 assert(buffer
== [65, 200, 0, 0, 65, 200, 0, 0]);
4116 buffer
.write
!float(32.0f, &index
);
4117 assert(buffer
== [65, 200, 0, 0, 66, 0, 0, 0]);
4121 /// double (64bit - 8x ubyte)
4124 ubyte[] buffer
= [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4126 buffer
.write
!double(32.0, 0);
4127 assert(buffer
== [64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
4129 buffer
.write
!double(25.0, 8);
4130 assert(buffer
== [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0]);
4133 buffer
.write
!double(25.0, &index
);
4134 assert(buffer
== [64, 57, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0]);
4137 buffer
.write
!double(32.0, &index
);
4138 assert(buffer
== [64, 57, 0, 0, 0, 0, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0]);
4139 assert(index
== 16);
4145 ubyte[] buffer
= [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4154 buffer
.write
!Foo(Foo
.one
, 0);
4155 assert(buffer
== [0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0]);
4157 buffer
.write
!Foo(Foo
.two
, 4);
4158 assert(buffer
== [0, 0, 0, 10, 0, 0, 0, 20, 0, 0, 0, 0]);
4160 buffer
.write
!Foo(Foo
.three
, 8);
4161 assert(buffer
== [0, 0, 0, 10, 0, 0, 0, 20, 0, 0, 0, 30]);
4164 buffer
.write
!Foo(Foo
.three
, &index
);
4165 assert(buffer
== [0, 0, 0, 30, 0, 0, 0, 20, 0, 0, 0, 30]);
4168 buffer
.write
!Foo(Foo
.one
, &index
);
4169 assert(buffer
== [0, 0, 0, 30, 0, 0, 0, 10, 0, 0, 0, 30]);
4172 buffer
.write
!Foo(Foo
.two
, &index
);
4173 assert(buffer
== [0, 0, 0, 30, 0, 0, 0, 10, 0, 0, 0, 20]);
4174 assert(index
== 12);
4180 ubyte[] buffer
= [0, 0];
4188 buffer
.write
!Bool(Bool
.btrue
, 0);
4189 assert(buffer
== [1, 0]);
4191 buffer
.write
!Bool(Bool
.btrue
, 1);
4192 assert(buffer
== [1, 1]);
4195 buffer
.write
!Bool(Bool
.bfalse
, &index
);
4196 assert(buffer
== [0, 1]);
4199 buffer
.write
!Bool(Bool
.bfalse
, &index
);
4200 assert(buffer
== [0, 0]);
4207 ubyte[] buffer
= [0, 0, 0, 0, 0, 0, 0, 0];
4215 buffer
.write
!Float(Float
.one
, 0);
4216 assert(buffer
== [66, 0, 0, 0, 0, 0, 0, 0]);
4218 buffer
.write
!Float(Float
.two
, 4);
4219 assert(buffer
== [66, 0, 0, 0, 65, 200, 0, 0]);
4222 buffer
.write
!Float(Float
.two
, &index
);
4223 assert(buffer
== [65, 200, 0, 0, 65, 200, 0, 0]);
4226 buffer
.write
!Float(Float
.one
, &index
);
4227 assert(buffer
== [65, 200, 0, 0, 66, 0, 0, 0]);
4234 ubyte[] buffer
= [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4242 buffer
.write
!Double(Double
.one
, 0);
4243 assert(buffer
== [64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
4245 buffer
.write
!Double(Double
.two
, 8);
4246 assert(buffer
== [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0]);
4249 buffer
.write
!Double(Double
.two
, &index
);
4250 assert(buffer
== [64, 57, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0]);
4253 buffer
.write
!Double(Double
.one
, &index
);
4254 assert(buffer
== [64, 57, 0, 0, 0, 0, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0]);
4255 assert(index
== 16);
4261 ubyte[] buffer
= [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4269 static assert(!__traits(compiles
, buffer
.write
!Real(Real
.one
)));
4274 Takes an integral value, converts it to the given endianness, and appends
4275 it to the given range of `ubyte`s (using `put`) as a sequence of
4276 `T.sizeof` `ubyte`s starting at index. `hasSlicing!R` must be
4280 T = The integral type to convert the first `T.sizeof` bytes to.
4281 endianness = The endianness to write the bytes in.
4282 range = The range to _append to.
4283 value = The value to _append.
4285 void append(T
, Endian endianness
= Endian
.bigEndian
, R
)(R range
, const T value
)
4286 if (canSwapEndianness
!T
&& isOutputRange
!(R
, ubyte))
4288 static if (endianness
== Endian
.bigEndian
)
4289 immutable bytes
= nativeToBigEndian
!T(value
);
4291 immutable bytes
= nativeToLittleEndian
!T(value
);
4293 put(range
, bytes
[]);
4300 auto buffer
= appender
!(const ubyte[])();
4301 buffer
.append
!ushort(261);
4302 assert(buffer
.data
== [1, 5]);
4304 buffer
.append
!uint(369700095u);
4305 assert(buffer
.data
== [1, 5, 22, 9, 44, 255]);
4307 buffer
.append
!ubyte(8);
4308 assert(buffer
.data
== [1, 5, 22, 9, 44, 255, 8]);
4314 import std
.array
: appender
;
4315 auto buffer
= appender
!(const ubyte[])();
4317 buffer
.append
!bool(true);
4318 assert(buffer
.data
== [1]);
4320 buffer
.append
!bool(false);
4321 assert(buffer
.data
== [1, 0]);
4324 /// char wchar dchar
4327 import std
.array
: appender
;
4328 auto buffer
= appender
!(const ubyte[])();
4330 buffer
.append
!char('a');
4331 assert(buffer
.data
== [97]);
4333 buffer
.append
!char('b');
4334 assert(buffer
.data
== [97, 98]);
4336 buffer
.append
!wchar('ą');
4337 assert(buffer
.data
== [97, 98, 1, 5]);
4339 buffer
.append
!dchar('ą');
4340 assert(buffer
.data
== [97, 98, 1, 5, 0, 0, 1, 5]);
4346 import std
.array
: appender
;
4347 auto buffer
= appender
!(const ubyte[])();
4349 buffer
.append
!float(32.0f);
4350 assert(buffer
.data
== [66, 0, 0, 0]);
4352 buffer
.append
!double(32.0);
4353 assert(buffer
.data
== [66, 0, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0]);
4359 import std
.array
: appender
;
4360 auto buffer
= appender
!(const ubyte[])();
4369 buffer
.append
!Foo(Foo
.one
);
4370 assert(buffer
.data
== [0, 0, 0, 10]);
4372 buffer
.append
!Foo(Foo
.two
);
4373 assert(buffer
.data
== [0, 0, 0, 10, 0, 0, 0, 20]);
4375 buffer
.append
!Foo(Foo
.three
);
4376 assert(buffer
.data
== [0, 0, 0, 10, 0, 0, 0, 20, 0, 0, 0, 30]);
4382 import std
.array
: appender
;
4383 auto buffer
= appender
!(const ubyte[])();
4391 buffer
.append
!Bool(Bool
.btrue
);
4392 assert(buffer
.data
== [1]);
4394 buffer
.append
!Bool(Bool
.bfalse
);
4395 assert(buffer
.data
== [1, 0]);
4397 buffer
.append
!Bool(Bool
.btrue
);
4398 assert(buffer
.data
== [1, 0, 1]);
4404 import std
.array
: appender
;
4405 auto buffer
= appender
!(const ubyte[])();
4413 buffer
.append
!Float(Float
.one
);
4414 assert(buffer
.data
== [66, 0, 0, 0]);
4416 buffer
.append
!Float(Float
.two
);
4417 assert(buffer
.data
== [66, 0, 0, 0, 65, 200, 0, 0]);
4423 import std
.array
: appender
;
4424 auto buffer
= appender
!(const ubyte[])();
4432 buffer
.append
!Double(Double
.one
);
4433 assert(buffer
.data
== [64, 64, 0, 0, 0, 0, 0, 0]);
4435 buffer
.append
!Double(Double
.two
);
4436 assert(buffer
.data
== [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0]);
4442 import std
.array
: appender
;
4443 auto buffer
= appender
!(const ubyte[])();
4451 static assert(!__traits(compiles
, buffer
.append
!Real(Real
.one
)));
4457 import std
.format
: format
;
4458 import std
.meta
: AliasSeq
;
4459 static foreach (endianness
; [Endian
.bigEndian
, Endian
.littleEndian
])
4461 auto toWrite
= appender
!(ubyte[])();
4462 alias Types
= AliasSeq
!(uint, int, long, ulong, short, ubyte, ushort, byte, uint);
4463 ulong[] values
= [42, -11, long.max
, 1098911981329L, 16, 255, 19012, 2, 17];
4464 assert(Types
.length
== values
.length
);
4468 static foreach (T
; Types
)
4470 toWrite
.append
!(T
, endianness
)(cast(T
) values
[index
++]);
4474 auto toRead
= toWrite
.data
;
4475 assert(toRead
.length
== length
);
4478 static foreach (T
; Types
)
4480 assert(toRead
.peek
!(T
, endianness
)() == values
[index
], format("Failed Index: %s", index
));
4481 assert(toRead
.peek
!(T
, endianness
)(0) == values
[index
], format("Failed Index: %s", index
));
4482 assert(toRead
.length
== length
,
4483 format("Failed Index [%s], Actual Length: %s", index
, toRead
.length
));
4484 assert(toRead
.read
!(T
, endianness
)() == values
[index
], format("Failed Index: %s", index
));
4486 assert(toRead
.length
== length
,
4487 format("Failed Index [%s], Actual Length: %s", index
, toRead
.length
));
4490 assert(toRead
.empty
);
4495 Counts the number of set bits in the binary representation of `value`.
4496 For signed integers, the sign bit is included in the count.
4498 private uint countBitsSet(T
)(const T value
)
4501 static if (T
.sizeof
== 8)
4503 import core
.bitop
: popcnt
;
4504 const c
= popcnt(cast(ulong) value
);
4506 else static if (T
.sizeof
== 4)
4508 import core
.bitop
: popcnt
;
4509 const c
= popcnt(cast(uint) value
);
4511 // http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
4512 else static if (T
.sizeof
== 2)
4514 uint c
= value
- ((value
>> 1) & 0x5555);
4515 c
= ((c
>> 2) & 0x3333) + (c
& 0X3333);
4516 c
= ((c
>> 4) + c
) & 0x0F0F;
4517 c
= ((c
>> 8) + c
) & 0x00FF;
4519 else static if (T
.sizeof
== 1)
4521 uint c
= value
- ((value
>> 1) & 0x55);
4522 c
= ((c
>> 2) & 0x33) + (c
& 0X33);
4523 c
= ((c
>> 4) + c
) & 0x0F;
4527 static assert(false, "countBitsSet only supports 1, 2, 4, or 8 byte sized integers.");
4529 return cast(uint) c
;
4534 assert(countBitsSet(1) == 1);
4535 assert(countBitsSet(0) == 0);
4536 assert(countBitsSet(int.min
) == 1);
4537 assert(countBitsSet(uint.max
) == 32);
4543 static foreach (T
; AliasSeq
!(byte, ubyte, short, ushort, int, uint, long, ulong))
4545 assert(countBitsSet(cast(T
) 0) == 0);
4546 assert(countBitsSet(cast(T
) 1) == 1);
4547 assert(countBitsSet(cast(T
) 2) == 1);
4548 assert(countBitsSet(cast(T
) 3) == 2);
4549 assert(countBitsSet(cast(T
) 4) == 1);
4550 assert(countBitsSet(cast(T
) 5) == 2);
4551 assert(countBitsSet(cast(T
) 127) == 7);
4552 static if (isSigned
!T
)
4554 assert(countBitsSet(cast(T
)-1) == 8 * T
.sizeof
);
4555 assert(countBitsSet(T
.min
) == 1);
4559 assert(countBitsSet(T
.max
) == 8 * T
.sizeof
);
4561 // Check CTFE compiles.
4562 static assert(countBitsSet(cast(T
) 1) == 1);
4564 assert(countBitsSet(1_000_000) == 7);
4565 foreach (i
; 0 .. 63)
4566 assert(countBitsSet(1UL << i
) == 1);
4569 private struct BitsSet(T
)
4571 static assert(T
.sizeof
<= 8, "bitsSet assumes T is no more than 64-bit.");
4575 this(T value
, size_t startIndex
= 0)
4578 // Further calculation is only valid and needed when the range is non-empty.
4582 import core
.bitop
: bsf;
4583 immutable trailingZerosCount
= bsf(value
);
4584 _value
>>>= trailingZerosCount
;
4585 _index
= startIndex
+ trailingZerosCount
;
4588 @property size_t
front() const
4593 @property bool empty() const
4600 assert(_value
, "Cannot call popFront on empty range.");
4603 // Further calculation is only valid and needed when the range is non-empty.
4607 import core
.bitop
: bsf;
4608 immutable trailingZerosCount
= bsf(_value
);
4609 _value
>>>= trailingZerosCount
;
4610 _index
+= trailingZerosCount
+ 1;
4613 @property BitsSet
save() const
4618 @property size_t
length() const
4620 return countBitsSet(_value
);
4624 private size_t _index
;
4628 Range that iterates the indices of the set bits in `value`.
4629 Index 0 corresponds to the least significant bit.
4630 For signed integers, the highest index corresponds to the sign bit.
4632 auto bitsSet(T
)(const T value
) @nogc pure nothrow
4635 return BitsSet
!T(value
);
4641 import std
.algorithm
.comparison
: equal
;
4642 import std
.range
: iota
;
4644 assert(bitsSet(1).equal([0]));
4645 assert(bitsSet(5).equal([0, 2]));
4646 assert(bitsSet(-1).equal(iota(32)));
4647 assert(bitsSet(int.min
).equal([31]));
4652 import std
.algorithm
.comparison
: equal
;
4653 import std
.range
: iota
;
4656 static foreach (T
; AliasSeq
!(byte, ubyte, short, ushort, int, uint, long, ulong))
4658 assert(bitsSet(cast(T
) 0).empty
);
4659 assert(bitsSet(cast(T
) 1).equal([0]));
4660 assert(bitsSet(cast(T
) 2).equal([1]));
4661 assert(bitsSet(cast(T
) 3).equal([0, 1]));
4662 assert(bitsSet(cast(T
) 4).equal([2]));
4663 assert(bitsSet(cast(T
) 5).equal([0, 2]));
4664 assert(bitsSet(cast(T
) 127).equal(iota(7)));
4665 static if (isSigned
!T
)
4667 assert(bitsSet(cast(T
)-1).equal(iota(8 * T
.sizeof
)));
4668 assert(bitsSet(T
.min
).equal([8 * T
.sizeof
- 1]));
4672 assert(bitsSet(T
.max
).equal(iota(8 * T
.sizeof
)));
4675 assert(bitsSet(1_000_000).equal([6, 9, 14, 16, 17, 18, 19]));
4676 foreach (i
; 0 .. 63)
4677 assert(bitsSet(1UL << i
).equal([i
]));
4680 // Fix https://issues.dlang.org/show_bug.cgi?id=24095
4681 @safe @nogc pure unittest
4691 mixin(bitfields
!(Bar
, "bar", 1, ubyte, "", 7,));
4696 assert(foo
.bar
== Bar
.a
);
4698 assert(foo
.bar
== Bar
.b
);