Daily bump.
[gcc.git] / libphobos / src / std / bitmanip.d
blobf8a97dfbf19c989c1f57bdd610b4abd3de8523fc
1 // Written in the D programming language.
3 /**
4 Bit-level manipulation facilities.
6 $(SCRIPT inhibitQuickIndex = 1;)
7 $(DIVC quickindex,
8 $(BOOKTABLE,
9 $(TR $(TH Category) $(TH Functions))
10 $(TR $(TD Bit constructs) $(TD
11 $(LREF BitArray)
12 $(LREF bitfields)
13 $(LREF bitsSet)
15 $(TR $(TD Endianness conversion) $(TD
16 $(LREF bigEndianToNative)
17 $(LREF littleEndianToNative)
18 $(LREF nativeToBigEndian)
19 $(LREF nativeToLittleEndian)
20 $(LREF swapEndian)
22 $(TR $(TD Integral ranges) $(TD
23 $(LREF append)
24 $(LREF peek)
25 $(LREF read)
26 $(LREF write)
28 $(TR $(TD Floating-Point manipulation) $(TD
29 $(LREF DoubleRep)
30 $(LREF FloatRep)
32 $(TR $(TD Tagging) $(TD
33 $(LREF taggedClassRef)
34 $(LREF taggedPointer)
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),
43 Alex Rønne Petersen,
44 Damian Ziemba,
45 Amaury SECHET
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)
54 module std.bitmanip;
56 import std.range.primitives;
57 public import std.system : Endian;
58 import std.traits;
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");
69 @safe pure unittest
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";
90 else
92 enum ulong maskAllElse = ((~0uL) >> (64 - len)) << offset;
93 enum TSize = 8 * T.sizeof;
94 enum SignShift = TSize - len;
96 static if (T.min < 0)
98 enum long minVal = -(1uL << (len - 1));
99 enum ulong maxVal = (1uL << (len - 1)) - 1;
100 enum RightShiftOp = ">>=";
102 else
104 enum ulong minVal = 0;
105 enum ulong maxVal = (~0uL) >> (64 - len);
106 enum RightShiftOp = ">>>=";
109 static if (is(T : bool))
111 enum createAccessors =
112 // getter
113 "@property bool " ~ name ~ "() @safe pure nothrow @nogc const { return "
114 ~"("~store~" & "~myToString(maskAllElse)~") != 0;}\n"
115 // setter
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";
120 else
122 // getter
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"
128 // setter
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"
136 // constants
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";
149 else
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;
165 else
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)
179 enum createFields
180 = createAccessors!(store, Ts[0], Ts[1], Ts[2], offset)
181 ~ createFields!(store, offset + Ts[2], Ts[3 .. $]);
182 else
183 enum createFields = "";
186 private ulong getBitsForAlign(ulong a)
188 ulong bits = 0;
189 while ((a & 0x01) == 0)
191 bits++;
192 a >>= 1;
195 assert(a == 1, "alignment is not a power of 2");
196 return bits;
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;
208 // getter
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"
212 // setter
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;
227 else
228 enum sizeOfBitField = T[2] + sizeOfBitField!(T[3 .. $]);
231 private template createTaggedReference(T, ulong a, string name, Ts...)
233 static assert(
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
267 a suffix `_bf`.
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.
320 @safe unittest
322 struct A
324 int a;
325 mixin(bitfields!(
326 uint, "x", 2,
327 int, "y", 3,
328 uint, "z", 2,
329 bool, "flag", 1));
332 A obj;
333 obj.x = 2;
334 obj.z = obj.x;
336 assert(obj.x == 2);
337 assert(obj.y == 0);
338 assert(obj.z == 2);
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.
347 @safe unittest
349 struct A
351 mixin(bitfields!(
352 bool, "flag1", 1,
353 bool, "flag2", 1,
354 uint, "", 6));
357 A a;
358 assert(a.flag1 == 0);
359 a.flag1 = 1;
360 assert(a.flag1 == 1);
361 a.flag1 = 0;
362 assert(a.flag1 == 0);
365 /// enums can be used too
366 @safe unittest
368 enum ABC { A, B, C }
369 struct EnumTest
371 mixin(bitfields!(
372 ABC, "x", 2,
373 bool, "y", 1,
374 ubyte, "z", 5));
378 @safe pure nothrow @nogc
379 unittest
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
384 struct Test1
386 mixin(bitfields!(uint, "a", 32,
387 uint, "b", 4,
388 uint, "c", 4,
389 uint, "d", 8,
390 uint, "e", 16,));
392 static assert(Test1.b_min == 0);
393 static assert(Test1.b_max == 15);
396 struct Test2
398 mixin(bitfields!(bool, "a", 0,
399 ulong, "b", 64));
401 static assert(Test2.b_min == ulong.min);
402 static assert(Test2.b_max == ulong.max);
405 struct Test1b
407 mixin(bitfields!(bool, "a", 0,
408 int, "b", 8));
411 struct Test2b
413 mixin(bitfields!(int, "a", 32,
414 int, "b", 4,
415 int, "c", 4,
416 int, "d", 8,
417 int, "e", 16,));
419 static assert(Test2b.b_min == -8);
420 static assert(Test2b.b_max == 7);
423 struct Test3b
425 mixin(bitfields!(bool, "a", 0,
426 long, "b", 64));
428 static assert(Test3b.b_min == long.min);
429 static assert(Test3b.b_max == long.max);
432 struct Test4b
434 mixin(bitfields!(long, "a", 32,
435 int, "b", 32));
438 // Sign extension tests
439 Test2b t2b;
440 Test4b t4b;
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
448 @safe unittest
450 union S {
451 ulong bits = ulong.max;
452 mixin (bitfields!(
453 ulong, "back", 31,
454 ulong, "front", 33)
457 S num;
459 num.bits = ulong.max;
460 num.back = 1;
461 assert(num.bits == 0xFFFF_FFFF_8000_0001uL);
464 // https://issues.dlang.org/show_bug.cgi?id=5942
465 @safe unittest
467 struct S
469 mixin(bitfields!(
470 int, "a" , 32,
471 int, "b" , 32
475 S data;
476 data.b = 42;
477 data.a = 1;
478 assert(data.b == 42);
481 @safe unittest
483 struct Test
485 mixin(bitfields!(bool, "a", 1,
486 uint, "b", 3,
487 short, "c", 4));
490 @safe void test() pure nothrow
492 Test t;
494 t.a = true;
495 t.b = 5;
496 t.c = 2;
498 assert(t.a);
499 assert(t.b == 5);
500 assert(t.c == 2);
503 test();
506 @safe unittest
509 static struct Integrals {
510 bool checkExpectations(bool eb, int ei, short es) { return b == eb && i == ei && s == es; }
512 mixin(bitfields!(
513 bool, "b", 1,
514 uint, "i", 3,
515 short, "s", 4));
517 Integrals i;
518 assert(i.checkExpectations(false, 0, 0));
519 i.b = true;
520 assert(i.checkExpectations(true, 0, 0));
521 i.i = 7;
522 assert(i.checkExpectations(true, 7, 0));
523 i.s = -8;
524 assert(i.checkExpectations(true, 7, -8));
525 i.s = 7;
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; }
534 mixin(bitfields!(
535 uint, "u", 24,
536 short, "s", 16,
537 int, "i", 24));
540 MoreIntegrals i;
541 assert(i.checkExpectations(0, 0, 0));
542 i.s = 20;
543 assert(i.checkExpectations(0, 20, 0));
544 i.i = 72;
545 assert(i.checkExpectations(0, 20, 72));
546 i.u = 8;
547 assert(i.checkExpectations(8, 20, 72));
548 i.s = 7;
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; }
557 mixin(bitfields!(
558 A, "a", 1,
559 B, "b", 2,
560 uint, "", 5));
562 Enums e;
563 assert(e.checkExpectations(A.True, B.One));
564 e.a = A.False;
565 assert(e.checkExpectations(A.False, B.One));
566 e.b = B.Three;
567 assert(e.checkExpectations(A.False, B.Three));
569 static struct SingleMember {
570 bool checkExpectations(bool eb) { return b == eb; }
572 mixin(bitfields!(
573 bool, "b", 1,
574 uint, "", 7));
576 SingleMember f;
577 assert(f.checkExpectations(false));
578 f.b = true;
579 assert(f.checkExpectations(true));
582 // https://issues.dlang.org/show_bug.cgi?id=12477
583 @system unittest
585 import core.exception : AssertError;
586 import std.algorithm.searching : canFind;
588 static struct S
590 mixin(bitfields!(
591 uint, "a", 6,
592 int, "b", 2));
595 S s;
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
607 @safe unittest
609 struct S {
610 mixin(bitfields!(
611 bool, "alice", 1,
612 ulong, "bob", 63,
616 S s;
617 s.bob = long.max - 1;
618 s.alice = false;
619 assert(s.bob == long.max - 1);
622 // https://issues.dlang.org/show_bug.cgi?id=21634
623 @safe unittest
625 struct A
627 mixin(bitfields!(int, "", 1,
628 int, "gshared", 7));
632 // https://issues.dlang.org/show_bug.cgi?id=21725
633 @safe unittest
635 struct S
637 mixin(bitfields!(
638 uint, q{foo}, 4,
639 uint, null, 4,
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
653 argument.
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);
664 @safe unittest
666 struct A
668 int a;
669 mixin(taggedPointer!(
670 uint*, "x",
671 bool, "b1", 1,
672 bool, "b2", 1));
674 A obj;
675 obj.x = new uint;
676 obj.b1 = true;
677 obj.b2 = false;
680 @system unittest
682 struct Test5
684 mixin(taggedPointer!(
685 int*, "a",
686 uint, "b", 2));
689 Test5 t5;
690 t5.a = null;
691 t5.b = 3;
692 assert(t5.a is null);
693 assert(t5.b == 3);
695 int myint = 42;
696 t5.a = &myint;
697 assert(t5.a is &myint);
698 assert(t5.b == 3);
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...)
713 if (is(T == class))
715 enum taggedClassRef = createTaggedReference!(T, 8, name, Ts);
719 @safe unittest
721 struct A
723 int a;
724 mixin(taggedClassRef!(
725 Object, "o",
726 uint, "i", 2));
728 A obj;
729 obj.o = new Object();
730 obj.i = 3;
733 @system unittest
735 struct Test6
737 mixin(taggedClassRef!(
738 Object, "o",
739 bool, "b", 1));
742 Test6 t6;
743 t6.o = null;
744 t6.b = false;
745 assert(t6.o is null);
746 assert(t6.b == false);
748 auto o = new Object();
749 t6.o = o;
750 t6.b = true;
751 assert(t6.o is o);
752 assert(t6.b == true);
755 @safe unittest
757 static assert(!__traits(compiles,
758 taggedPointer!(
759 int*, "a",
760 uint, "b", 3)));
762 static assert(!__traits(compiles,
763 taggedClassRef!(
764 Object, "a",
765 uint, "b", 4)));
767 struct S {
768 mixin(taggedClassRef!(
769 Object, "a",
770 bool, "b", 1));
773 const S s;
774 void bar(S s) {}
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;
787 else
789 enum uint bias = 1023, fractionBits = 52, exponentBits = 11, signBits = 1;
790 alias FractionType = ulong;
791 alias ExponentType = ushort;
794 union
796 T value;
797 mixin(bitfields!(
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:
808 $(RUNNABLE_EXAMPLE
809 ----
810 struct FloatRep
812 union
814 float value;
815 mixin(bitfields!(
816 uint, "fraction", 23,
817 ubyte, "exponent", 8,
818 bool, "sign", 1));
820 enum uint bias = 127, fractionBits = 23, exponentBits = 8, signBits = 1;
822 ----
825 alias FloatRep = FloatingPointRepresentation!float;
828 @safe unittest
830 FloatRep rep = {value: 0};
831 assert(rep.fraction == 0);
832 assert(rep.exponent == 0);
833 assert(!rep.sign);
835 rep.value = 42;
836 assert(rep.fraction == 2621440);
837 assert(rep.exponent == 132);
838 assert(!rep.sign);
840 rep.value = 10;
841 assert(rep.fraction == 2097152);
842 assert(rep.exponent == 130);
846 @safe unittest
848 FloatRep rep = {value: 1};
849 assert(rep.fraction == 0);
850 assert(rep.exponent == 127);
851 assert(!rep.sign);
853 rep.exponent = 126;
854 assert(rep.value == 0.5);
856 rep.exponent = 130;
857 assert(rep.value == 8);
861 @safe unittest
863 FloatRep rep = {value: 1};
864 rep.value = -0.5;
865 assert(rep.fraction == 0);
866 assert(rep.exponent == 126);
867 assert(rep.sign);
869 rep.value = -1. / 3;
870 assert(rep.fraction == 2796203);
871 assert(rep.exponent == 125);
872 assert(rep.sign);
876 Allows manipulating the fraction, exponent, and sign parts of a
877 `double` separately. The definition is:
879 $(RUNNABLE_EXAMPLE
880 ----
881 struct DoubleRep
883 union
885 double value;
886 mixin(bitfields!(
887 ulong, "fraction", 52,
888 ushort, "exponent", 11,
889 bool, "sign", 1));
891 enum uint bias = 1023, signBits = 1, fractionBits = 52, exponentBits = 11;
893 ----
896 alias DoubleRep = FloatingPointRepresentation!double;
899 @safe unittest
901 DoubleRep rep = {value: 0};
902 assert(rep.fraction == 0);
903 assert(rep.exponent == 0);
904 assert(!rep.sign);
906 rep.value = 42;
907 assert(rep.fraction == 1407374883553280);
908 assert(rep.exponent == 1028);
909 assert(!rep.sign);
911 rep.value = 10;
912 assert(rep.fraction == 1125899906842624);
913 assert(rep.exponent == 1026);
917 @safe unittest
919 DoubleRep rep = {value: 1};
920 assert(rep.fraction == 0);
921 assert(rep.exponent == 1023);
922 assert(!rep.sign);
924 rep.exponent = 1022;
925 assert(rep.value == 0.5);
927 rep.exponent = 1026;
928 assert(rep.value == 8);
932 @safe unittest
934 DoubleRep rep = {value: 1};
935 rep.value = -0.5;
936 assert(rep.fraction == 0);
937 assert(rep.exponent == 1022);
938 assert(rep.sign);
940 rep.value = -1. / 3;
941 assert(rep.fraction == 1501199875790165);
942 assert(rep.exponent == 1021);
943 assert(rep.sign);
946 /// Reading
947 @safe unittest
949 DoubleRep x;
950 x.value = 1.0;
951 assert(x.fraction == 0 && x.exponent == 1023 && !x.sign);
952 x.value = -0.5;
953 assert(x.fraction == 0 && x.exponent == 1022 && x.sign);
954 x.value = 0.5;
955 assert(x.fraction == 0 && x.exponent == 1022 && !x.sign);
958 /// Writing
959 @safe unittest
961 DoubleRep x;
962 x.fraction = 1125899906842624;
963 x.exponent = 1025;
964 x.sign = true;
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).
974 struct BitArray
976 private:
978 import core.bitop : btc, bts, btr, bsf, bt;
979 import std.format.spec : FormatSpec;
981 size_t _len;
982 size_t* _ptr;
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;
1004 public:
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
1013 length = ba.length;
1014 foreach (i, b; ba)
1016 this[i] = b;
1021 @system unittest
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]));
1037 @system unittest
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
1056 are mapped:
1058 $(RUNNABLE_EXAMPLE
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).
1077 Params:
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;
1093 _len = numbits;
1097 @system unittest
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.
1111 a[0] = 0;
1112 assert(b[0] == 0);
1113 assert(a == b);
1117 @system unittest
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]));
1129 @system unittest
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
1154 _len = len;
1155 _ptr = ptr;
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
1163 `size_t` units.
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
1175 return _len;
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
1187 if (newlen != _len)
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
1197 _ptr = b.ptr;
1200 auto oldlen = _len;
1201 _len = newlen;
1202 if (oldlen < newlen)
1204 auto end = ((oldlen / bitsPerSizeT) + 1) * bitsPerSizeT;
1205 if (end > newlen)
1206 end = newlen;
1207 this[oldlen .. end] = 0;
1210 return _len;
1213 // https://issues.dlang.org/show_bug.cgi?id=20240
1214 @system unittest
1216 BitArray ba;
1218 ba.length = 1;
1219 ba[0] = 1;
1220 ba.length = 0;
1221 ba.length = 1;
1222 assert(ba[0] == 0); // OK
1224 ba.length = 2;
1225 ba[1] = 1;
1226 ba.length = 1;
1227 ba.length = 2;
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);
1245 @system unittest
1247 static void fun(const BitArray arr)
1249 auto x = arr[0];
1250 assert(x == 1);
1252 BitArray a;
1253 a.length = 3;
1254 a[0] = 1;
1255 fun(a);
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");
1268 if (b)
1269 bts(_ptr, i);
1270 else
1271 btr(_ptr, i);
1272 return b;
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;
1282 if (endBits)
1284 if (val)
1285 _ptr[fullWords] |= endMask;
1286 else
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]);
1298 b[] = true;
1299 // all bits are set
1300 assert(b.bitsSet.equal([0, 1, 2, 3, 4, 5]));
1302 b[] = false;
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;
1330 if (val)
1331 _ptr[startBlock] |= joinMask;
1332 else
1333 _ptr[startBlock] &= ~joinMask;
1334 return;
1337 if (startOffset != 0)
1339 size_t startBlockMask = ~((size_t(1) << startOffset) - 1);
1340 if (val)
1341 _ptr[startBlock] |= startBlockMask;
1342 else
1343 _ptr[startBlock] &= ~startBlockMask;
1344 ++startBlock;
1346 if (endOffset != 0)
1348 size_t endBlockMask = (size_t(1) << endOffset) - 1;
1349 if (val)
1350 _ptr[endBlock] |= endBlockMask;
1351 else
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;
1362 import std.stdio;
1364 auto b = BitArray([1, 0, 0, 0, 1, 1, 0]);
1365 b[1 .. 3] = true;
1366 assert(b.bitsSet.equal([0, 1, 2, 4, 5]));
1368 bool[72] bitArray;
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);
1374 b1[0 .. 64] = true;
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)
1393 _ptr[i] = ~_ptr[i];
1395 if (endBits)
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]);
1407 b.flip();
1408 // after flipping, positions 1, 3, 5 are set
1409 assert(b.bitsSet.equal([1, 3, 5]));
1411 bool[270] bits;
1412 auto b1 = BitArray(bits);
1413 b1.flip();
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]);
1429 ax.flip(0);
1430 assert(ax[0] == 0);
1432 bool[200] y;
1433 y[90 .. 130] = true;
1434 auto ay = BitArray(y);
1435 ay.flip(100);
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
1444 if (_ptr)
1446 size_t bitCount;
1447 foreach (i; 0 .. fullWords)
1448 bitCount += (() @trusted => countBitsSet(_ptr[i]))();
1449 if (endBits)
1450 bitCount += (() @trusted => countBitsSet(_ptr[fullWords] & endMask))();
1451 return bitCount;
1453 else
1455 return 0;
1460 @system pure nothrow unittest
1462 auto a = BitArray([0, 1, 1, 0, 0, 1, 1]);
1463 assert(a.count == 4);
1465 BitArray b;
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
1479 BitArray ba;
1481 auto b = _ptr[0 .. dim].dup;
1482 ba._len = _len;
1483 ba._ptr = b.ptr;
1484 return ba;
1488 @system unittest
1490 BitArray a;
1491 BitArray b;
1493 a.length = 3;
1494 a[0] = 1; a[1] = 0; a[2] = 1;
1495 b = a.dup;
1496 assert(b.length == 3);
1497 foreach (i; 0 .. 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)
1506 int result;
1508 foreach (i; 0 .. _len)
1510 bool b = opIndex(i);
1511 result = dg(b);
1512 this[i] = b;
1513 if (result)
1514 break;
1516 return result;
1519 /** ditto */
1520 int opApply(scope int delegate(bool) dg) const
1522 int result;
1524 foreach (i; 0 .. _len)
1526 immutable b = opIndex(i);
1527 result = dg(b);
1528 if (result)
1529 break;
1531 return result;
1534 /** ditto */
1535 int opApply(scope int delegate(size_t, ref bool) dg)
1537 int result;
1539 foreach (i; 0 .. _len)
1541 bool b = opIndex(i);
1542 result = dg(i, b);
1543 this[i] = b;
1544 if (result)
1545 break;
1547 return result;
1550 /** ditto */
1551 int opApply(scope int delegate(size_t, bool) dg) const
1553 int result;
1555 foreach (i; 0 .. _len)
1557 immutable b = opIndex(i);
1558 result = dg(i, b);
1559 if (result)
1560 break;
1562 return result;
1566 @system unittest
1568 bool[] ba = [1,0,1];
1570 auto a = BitArray(ba);
1572 int i;
1573 foreach (b;a)
1575 switch (i)
1577 case 0: assert(b == true); break;
1578 case 1: assert(b == false); break;
1579 case 2: assert(b == true); break;
1580 default: assert(0);
1582 i++;
1585 foreach (j,b;a)
1587 switch (j)
1589 case 0: assert(b == true); break;
1590 case 1: assert(b == false); break;
1591 case 2: assert(b == true); break;
1592 default: assert(0);
1598 /**********************************************
1599 * Reverses the bits of the `BitArray`.
1601 @property BitArray reverse() @nogc pure nothrow return
1602 out (result)
1604 assert(result == this, "the result must be equal to this");
1608 if (_len >= 2)
1610 bool t;
1611 size_t lo, hi;
1613 lo = 0;
1614 hi = _len - 1;
1615 for (; lo < hi; lo++, hi--)
1617 t = this[lo];
1618 this[lo] = this[hi];
1619 this[hi] = t;
1622 return this;
1626 @system unittest
1628 BitArray b;
1629 bool[5] data = [1,0,1,1,0];
1631 b = BitArray(data);
1632 b.reverse;
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
1642 out (result)
1644 assert(result == this, "the result must be equal to this");
1648 if (_len >= 2)
1650 size_t lo, hi;
1652 lo = 0;
1653 hi = _len - 1;
1654 while (1)
1656 while (1)
1658 if (lo >= hi)
1659 goto Ldone;
1660 if (this[lo] == true)
1661 break;
1662 lo++;
1665 while (1)
1667 if (lo >= hi)
1668 goto Ldone;
1669 if (this[hi] == false)
1670 break;
1671 hi--;
1674 this[lo] = false;
1675 this[hi] = true;
1677 lo++;
1678 hi--;
1681 Ldone:
1682 return this;
1686 @system unittest
1688 size_t x = 0b1100011000;
1689 auto ba = BitArray(10, &x);
1690 ba.sort;
1691 foreach (i; 0 .. 6)
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)
1704 return false;
1705 auto p1 = this._ptr;
1706 auto p2 = a2._ptr;
1708 if (p1[0 .. fullWords] != p2[0 .. fullWords])
1709 return false;
1711 if (!endBits)
1712 return true;
1714 auto i = fullWords;
1715 return (p1[i] & endMask) == (p2[i] & endMask);
1719 @system unittest
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);
1737 assert(a != b);
1738 assert(a != c);
1739 assert(a != d);
1740 assert(a == e);
1741 assert(f != g);
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;
1753 auto p2 = a2._ptr;
1755 foreach (i; 0 .. fullWords)
1757 if (p1[i] != p2[i])
1759 return p1[i] & (size_t(1) << bsf(p1[i] ^ p2[i])) ? 1 : -1;
1763 if (endBits)
1765 immutable i = fullWords;
1766 immutable diff = p1[i] ^ p2[i];
1767 if (diff)
1769 immutable index = bsf(diff);
1770 if (index < endBits)
1772 return p1[i] & (size_t(1) << index) ? 1 : -1;
1777 // Standard:
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);
1784 @system unittest
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);
1802 assert(a > b);
1803 assert(a >= b);
1804 assert(a < c);
1805 assert(a <= c);
1806 assert(a < d);
1807 assert(a <= d);
1808 assert(a == e);
1809 assert(a <= e);
1810 assert(a >= e);
1811 assert(f < g);
1812 assert(g <= g);
1815 @system unittest
1817 bool[] v;
1818 foreach (i; 1 .. 256)
1820 v.length = i;
1821 v[] = false;
1822 auto x = BitArray(v);
1823 v[i-1] = true;
1824 auto y = BitArray(v);
1825 assert(x < y);
1826 assert(x <= y);
1829 BitArray a1, a2;
1831 for (size_t len = 4; len <= 256; len <<= 1)
1833 a1.length = a2.length = len;
1834 a1[len-2] = a2[len-1] = true;
1835 assert(a1 > a2);
1836 a1[len-2] = a2[len-1] = false;
1839 foreach (j; 1 .. a1.length)
1841 a1[j-1] = a2[j] = true;
1842 assert(a1 > a2);
1843 a1[j-1] = a2[j] = false;
1847 /***************************************
1848 * Support for hashing for `BitArray`.
1850 size_t toHash() const @nogc pure nothrow
1852 size_t hash = 3557;
1853 auto fullBytes = _len / 8;
1854 foreach (i; 0 .. fullBytes)
1856 hash *= 3559;
1857 hash += (cast(byte*) this._ptr)[i];
1859 foreach (i; 8*fullBytes .. _len)
1861 hash *= 3571;
1862 hash += this[i];
1864 return hash;
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];
1884 @system unittest
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
1897 @system unittest
1899 import std.meta : AliasSeq;
1901 static foreach (alias T; AliasSeq!(void, size_t))
1903 BitArray m;
1904 T[] ma = cast(T[]) m;
1906 const BitArray c;
1907 const(T)[] ca = cast(const T[]) c;
1909 immutable BitArray i;
1910 immutable(T)[] ia = cast(immutable T[]) i;
1912 // Cross-mutability
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
1928 if (op == "~")
1930 auto dim = this.dim;
1932 BitArray result;
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
1939 if (endBits)
1940 result._ptr[dim - 1] &= endMask;
1942 return result;
1946 @system unittest
1948 bool[] ba = [1,0,1,0,1];
1950 auto a = BitArray(ba);
1951 BitArray b = ~a;
1953 assert(b[0] == 0);
1954 assert(b[1] == 1);
1955 assert(b[2] == 0);
1956 assert(b[3] == 1);
1957 assert(b[4] == 0);
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;
1974 BitArray result;
1975 result.length = _len;
1977 static if (op == "-")
1978 result._ptr[0 .. dim] = this._ptr[0 .. dim] & ~e2._ptr[0 .. dim];
1979 else
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
1984 if (endBits)
1985 result._ptr[dim - 1] &= endMask;
1987 return result;
1991 @system unittest
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);
1999 BitArray c = a & b;
2001 assert(c[0] == 1);
2002 assert(c[1] == 0);
2003 assert(c[2] == 1);
2004 assert(c[3] == 0);
2005 assert(c[4] == 0);
2009 @system unittest
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);
2017 BitArray c = a | b;
2019 assert(c[0] == 1);
2020 assert(c[1] == 0);
2021 assert(c[2] == 1);
2022 assert(c[3] == 1);
2023 assert(c[4] == 1);
2027 @system unittest
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);
2035 BitArray c = a ^ b;
2037 assert(c[0] == 0);
2038 assert(c[1] == 0);
2039 assert(c[2] == 0);
2040 assert(c[3] == 1);
2041 assert(c[4] == 1);
2045 @system unittest
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);
2053 BitArray c = a - b;
2055 assert(c[0] == 0);
2056 assert(c[1] == 0);
2057 assert(c[2] == 0);
2058 assert(c[3] == 0);
2059 assert(c[4] == 1);
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];
2078 else
2079 mixin("_ptr[i] "~op~"= e2._ptr[i];");
2081 if (!endBits)
2082 return this;
2084 size_t i = fullWords;
2085 size_t endWord = _ptr[i];
2086 static if (op == "-")
2087 endWord &= ~e2._ptr[i];
2088 else
2089 mixin("endWord "~op~"= e2._ptr[i];");
2090 _ptr[i] = (_ptr[i] & ~endMask) | (endWord & endMask);
2092 return this;
2096 @system unittest
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);
2102 BitArray c = a;
2103 c.length = 5;
2104 c &= b;
2105 assert(a[5] == 1);
2106 assert(a[6] == 0);
2107 assert(a[7] == 1);
2108 assert(a[8] == 0);
2109 assert(a[9] == 1);
2113 @system unittest
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);
2121 a &= b;
2122 assert(a[0] == 1);
2123 assert(a[1] == 0);
2124 assert(a[2] == 1);
2125 assert(a[3] == 0);
2126 assert(a[4] == 0);
2130 @system unittest
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);
2138 a |= b;
2139 assert(a[0] == 1);
2140 assert(a[1] == 0);
2141 assert(a[2] == 1);
2142 assert(a[3] == 1);
2143 assert(a[4] == 1);
2147 @system unittest
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);
2155 a ^= b;
2156 assert(a[0] == 0);
2157 assert(a[1] == 0);
2158 assert(a[2] == 0);
2159 assert(a[3] == 1);
2160 assert(a[4] == 1);
2164 @system unittest
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);
2172 a -= b;
2173 assert(a[0] == 0);
2174 assert(a[1] == 0);
2175 assert(a[2] == 0);
2176 assert(a[3] == 0);
2177 assert(a[4] == 1);
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
2188 if (op == "~")
2190 length = _len + 1;
2191 this[_len - 1] = b;
2192 return this;
2196 @system unittest
2198 bool[] ba = [1,0,1,0,1];
2200 auto a = BitArray(ba);
2201 BitArray b;
2203 b = (a ~= true);
2204 assert(a[0] == 1);
2205 assert(a[1] == 0);
2206 assert(a[2] == 1);
2207 assert(a[3] == 0);
2208 assert(a[4] == 1);
2209 assert(a[5] == 1);
2211 assert(b == a);
2214 /***************************************
2215 * ditto
2217 BitArray opOpAssign(string op)(BitArray b) pure nothrow return scope
2218 if (op == "~")
2220 auto istart = _len;
2221 length = _len + b.length;
2222 for (auto i = istart; i < _len; i++)
2223 this[i] = b[i - istart];
2224 return this;
2228 @system unittest
2230 bool[] ba = [1,0];
2231 bool[] bb = [0,1,0];
2233 auto a = BitArray(ba);
2234 auto b = BitArray(bb);
2235 BitArray c;
2237 c = (a ~= b);
2238 assert(a.length == 5);
2239 assert(a[0] == 1);
2240 assert(a[1] == 0);
2241 assert(a[2] == 0);
2242 assert(a[3] == 1);
2243 assert(a[4] == 0);
2245 assert(c == a);
2248 /***************************************
2249 * Support for binary operator ~ for `BitArray`.
2251 BitArray opBinary(string op)(bool b) const pure nothrow
2252 if (op == "~")
2254 BitArray r;
2256 r = this.dup;
2257 r.length = _len + 1;
2258 r[_len] = b;
2259 return r;
2262 /** ditto */
2263 BitArray opBinaryRight(string op)(bool b) const pure nothrow
2264 if (op == "~")
2266 BitArray r;
2268 r.length = _len + 1;
2269 r[0] = b;
2270 foreach (i; 0 .. _len)
2271 r[1 + i] = this[i];
2272 return r;
2275 /** ditto */
2276 BitArray opBinary(string op)(BitArray b) const pure nothrow
2277 if (op == "~")
2279 BitArray r;
2281 r = this.dup;
2282 r ~= b;
2283 return r;
2287 @system unittest
2289 bool[] ba = [1,0];
2290 bool[] bb = [0,1,0];
2292 auto a = BitArray(ba);
2293 auto b = BitArray(bb);
2294 BitArray c;
2296 c = (a ~ b);
2297 assert(c.length == 5);
2298 assert(c[0] == 1);
2299 assert(c[1] == 0);
2300 assert(c[2] == 0);
2301 assert(c[3] == 1);
2302 assert(c[4] == 0);
2304 c = (a ~ true);
2305 assert(c.length == 3);
2306 assert(c[0] == 1);
2307 assert(c[1] == 0);
2308 assert(c[2] == 1);
2310 c = (false ~ a);
2311 assert(c.length == 3);
2312 assert(c[0] == 0);
2313 assert(c[1] == 1);
2314 assert(c[2] == 0);
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");
2327 if (nbits == 0)
2328 return lower;
2329 return (upper << (bitsPerSizeT - nbits)) | (lower >> nbits);
2332 @safe unittest
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_FEDBCA09);
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);
2350 else
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");
2364 if (nbits == 0)
2365 return upper;
2366 return (upper << nbits) | (lower >> (bitsPerSizeT - nbits));
2369 @safe unittest
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_FEDBCA09);
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
2401 if (op == "<<")
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],
2411 bitsToShift);
2413 _ptr[wordsToShift] = rollLeft(_ptr[0], 0, bitsToShift);
2416 import std.algorithm.comparison : min;
2417 foreach (i; 0 .. min(wordsToShift, dim))
2419 _ptr[i] = 0;
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
2435 if (op == ">>")
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];
2455 else
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
2471 @system unittest
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)));
2480 b <<= 64;
2481 assert(equal(b.bitsSet, iota(64, 128)));
2483 buf = new bool[64*3];
2484 buf[64*2 .. 64*3] = true;
2485 b = BitArray(buf);
2486 assert(equal(b.bitsSet, iota(64*2, 64*3)));
2487 b >>= 64;
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.
2493 @system unittest
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;
2502 a >>= 0;
2503 assert(a.bitsSet.equal(iota(0, r / 2)));
2504 a >>= 1;
2505 assert(a.bitsSet.equal(iota(0, r / 2 - 1)));
2507 BitArray b = true.repeat(r).array;
2508 b >>= 0;
2509 assert(b.bitsSet.equal(iota(0, r)));
2510 b >>= 1;
2511 assert(b.bitsSet.equal(iota(0, r - 1)));
2513 BitArray c = true.repeat(2 * r).array;
2514 c >>= 0;
2515 assert(c.bitsSet.equal(iota(0, 2 * r)));
2516 c >>= 10;
2517 assert(c.bitsSet.equal(iota(0, 2 * r - 10)));
2521 @system unittest
2523 import std.format : format;
2525 auto b = BitArray([1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1]);
2527 b <<= 1;
2528 assert(format("%b", b) == "01100_10101101");
2530 b >>= 1;
2531 assert(format("%b", b) == "11001_01011010");
2533 b <<= 4;
2534 assert(format("%b", b) == "00001_10010101");
2536 b >>= 5;
2537 assert(format("%b", b) == "10010_10100000");
2539 b <<= 13;
2540 assert(format("%b", b) == "00000_00000000");
2542 b = BitArray([1, 0, 1, 1, 0, 1, 1, 1]);
2543 b >>= 8;
2544 assert(format("%b", b) == "00000000");
2548 // Test multi-word case
2549 @system unittest
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.
2555 auto b = BitArray([
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,
2562 b <<= 8;
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
2571 b <<= 68;
2572 assert(format("%b", b) ==
2573 "00000000_00000000_"~
2574 "00000000_00000000_"~
2575 "00000000_00000000_"~
2576 "00000000_00000000_"~
2577 "00000000_00001000");
2579 b = BitArray([
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,
2586 b >>= 8;
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
2595 b >>= 68;
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.
2612 * Params:
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
2616 * is displayed.
2618 void toString(W)(ref W sink, scope const ref FormatSpec!char fmt) const
2619 if (isOutputRange!(W, char))
2621 const spec = fmt.spec;
2622 switch (spec)
2624 case 'b':
2625 return formatBitString(sink);
2626 case 's':
2627 return formatBitArray(sink);
2628 default:
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;
2655 return chain(
2656 iota(fullWords)
2657 .filter!(i => _ptr[i])()
2658 .map!(i => BitsSet!size_t(_ptr[i], i * bitsPerSizeT))()
2659 .joiner(),
2660 iota(fullWords * bitsPerSizeT, _len)
2661 .filter!(i => this[i])()
2666 @system unittest
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]));
2673 BitArray b2;
2674 b2.length = 1000;
2675 b2[333] = true;
2676 b2[666] = true;
2677 b2[999] = true;
2678 assert(b2.bitsSet.equal([333, 666, 999]));
2681 @system unittest
2683 import std.algorithm.comparison : equal;
2684 import std.range : iota;
2686 BitArray b;
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
2703 @system unittest
2705 BitArray ba;
2706 ba.length = 2;
2707 ba[1] = 1;
2708 ba.length = 1;
2709 assert(ba.bitsSet.empty);
2712 private void formatBitString(Writer)(auto ref Writer sink) const
2714 if (!length)
2715 return;
2717 auto leftover = _len % 8;
2718 foreach (idx; 0 .. leftover)
2720 put(sink, cast(char)(this[idx] + '0'));
2723 if (leftover && _len > 8)
2724 put(sink, "_");
2726 size_t count;
2727 foreach (idx; leftover .. _len)
2729 put(sink, cast(char)(this[idx] + '0'));
2730 if (++count == 8 && idx != _len - 1)
2732 put(sink, "_");
2733 count = 0;
2738 private void formatBitArray(Writer)(auto ref Writer sink) const
2740 put(sink, "[");
2741 foreach (idx; 0 .. _len)
2743 put(sink, cast(char)(this[idx] + '0'));
2744 if (idx + 1 < _len)
2745 put(sink, ", ");
2747 put(sink, "]");
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
2755 size_t[2] buffer;
2756 BitArray b = BitArray(buffer[], buffer.sizeof * 8);
2758 b[] = true;
2759 b[0 .. 1] = true;
2760 b.flip();
2761 b.flip(1);
2762 cast(void) b.count();
2766 /// Slicing & bitsSet
2767 @system unittest
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)));
2776 b <<= 64;
2777 assert(b.bitsSet.equal(iota(64, 128)));
2780 /// Concatenation and appending
2781 @system unittest
2783 import std.algorithm.comparison : equal;
2785 auto b = BitArray([1, 0]);
2786 b ~= true;
2787 assert(b[2] == 1);
2788 b ~= BitArray([0, 1]);
2789 auto c = BitArray([1, 0, 1, 0, 1]);
2790 assert(b == c);
2791 assert(b.bitsSet.equal([0, 2, 4]));
2794 /// Bit flipping
2795 @system unittest
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]));
2802 b.flip;
2803 assert(b.bitsSet.equal([0, 2, 3]));
2806 /// String format of bitarrays
2807 @system unittest
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");
2815 @system unittest
2817 import std.format : format;
2819 BitArray b;
2821 b = BitArray([]);
2822 assert(format("%s", b) == "[]");
2823 assert(format("%b", b) is null);
2825 b = BitArray([1]);
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");
2847 @system unittest
2849 BitArray a;
2850 a.length = 5;
2851 foreach (ref bool b; a)
2853 assert(b == 0);
2854 b = 1;
2856 foreach (bool b; a)
2857 assert(b == 1);
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)
2868 return val;
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);
2875 else
2876 static assert(0, T.stringof ~ " unsupported by swapEndian.");
2880 @safe unittest
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);
2895 @safe unittest
2897 import std.meta;
2898 import std.stdio;
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);
2902 T val;
2903 const T cval;
2904 immutable T ival;
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)
2932 T left = 0xffU;
2933 left <<= (T.sizeof - 1) * 8;
2934 T right = 0xffU;
2936 for (size_t i = 1; i < T.sizeof; ++i)
2938 assert(swapEndian(left) == right);
2939 assert(swapEndian(right) == left);
2940 left >>= 8;
2941 right <<= 8;
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);
2966 else
2968 enum len = T.sizeof;
2969 ubyte[len] retval;
2971 static foreach (i; 0 .. len)
2972 retval[i] = cast(ubyte)(val >> (len - i - 1) * 8);
2974 return retval;
2979 @safe unittest
2981 int i = 12345;
2982 ubyte[4] swappedI = nativeToBigEndian(i);
2983 assert(i == bigEndianToNative!int(swappedI));
2985 float f = 123.45f;
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));
2993 double d = 123.45;
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));
3002 @safe unittest
3004 import std.meta;
3005 import std.stdio;
3006 static foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, int, uint, long, ulong,
3007 char, wchar, dchar
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);
3020 T val;
3021 const T cval;
3022 immutable T ival;
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));
3048 else
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));
3057 else
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));
3065 else
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));
3070 else
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;
3096 else
3098 enum len = T.sizeof;
3099 alias U = UnsignedOfSize!len;
3100 U retval;
3102 static foreach (i; 0 .. len)
3103 retval |= (cast(U) val[i]) << (len - i - 1) * 8;
3105 return cast(T) retval;
3110 @safe unittest
3112 ushort i = 12345;
3113 ubyte[2] swappedI = nativeToBigEndian(i);
3114 assert(i == bigEndianToNative!ushort(swappedI));
3116 dchar c = 'D';
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);
3135 else
3137 enum len = T.sizeof;
3138 ubyte[len] retval;
3140 static foreach (i; 0 .. len)
3141 retval[i] = cast(ubyte)(val >> i * 8);
3143 return retval;
3148 @safe unittest
3150 int i = 12345;
3151 ubyte[4] swappedI = nativeToLittleEndian(i);
3152 assert(i == littleEndianToNative!int(swappedI));
3154 float f = 123.45f;
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));
3162 double d = 123.45;
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));
3171 @safe unittest
3173 import std.meta;
3174 import std.stdio;
3175 static foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, int, uint, long, ulong,
3176 char, wchar, dchar/*,
3177 float, double*/))
3179 scope(failure) writeln("Failed type: ", T.stringof);
3180 T val;
3181 const T cval;
3182 immutable T ival;
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;
3238 else
3240 enum len = T.sizeof;
3241 alias U = UnsignedOfSize!len;
3242 U retval;
3244 static foreach (i; 0 .. len)
3245 retval |= (cast(U) val[i]) << i * 8;
3247 return cast(T) retval;
3252 @safe unittest
3254 ushort i = 12345;
3255 ubyte[2] swappedI = nativeToLittleEndian(i);
3256 assert(i == littleEndianToNative!ushort(swappedI));
3258 dchar c = 'D';
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);
3269 @safe unittest
3271 import std.meta;
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 ||
3293 isSomeChar!T ||
3294 isBoolean!T ||
3295 isFloatOrDouble!T;
3298 @safe unittest
3300 import std.meta;
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)
3326 static if (n == 8)
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;
3334 else
3335 alias UnsignedOfSize = void;
3338 @safe unittest
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.
3365 Params:
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 &&
3377 isForwardRange!R &&
3378 is(ElementType!R : const ubyte))
3380 static if (hasSlicing!R)
3381 const ubyte[T.sizeof] bytes = range[0 .. T.sizeof];
3382 else
3384 ubyte[T.sizeof] bytes;
3385 //Make sure that range is not consumed, even if it's a class.
3386 range = range.save;
3388 foreach (ref e; bytes)
3390 e = range.front;
3391 range.popFront();
3395 static if (endianness == Endian.bigEndian)
3396 return bigEndianToNative!T(bytes);
3397 else
3398 return littleEndianToNative!T(bytes);
3401 /++ Ditto +/
3402 T peek(T, Endian endianness = Endian.bigEndian, R)(R range, size_t index)
3403 if (canSwapEndianness!T &&
3404 isForwardRange!R &&
3405 hasSlicing!R &&
3406 is(ElementType!R : const ubyte))
3408 return peek!(T, endianness)(range, &index);
3411 /++ Ditto +/
3412 T peek(T, Endian endianness = Endian.bigEndian, R)(R range, size_t* index)
3413 if (canSwapEndianness!T &&
3414 isForwardRange!R &&
3415 hasSlicing!R &&
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];
3423 *index = end;
3425 static if (endianness == Endian.bigEndian)
3426 return bigEndianToNative!T(bytes);
3427 else
3428 return littleEndianToNative!T(bytes);
3432 @system unittest
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);
3443 size_t index = 0;
3444 assert(buffer.peek!ushort(&index) == 261);
3445 assert(index == 2);
3447 assert(buffer.peek!uint(&index) == 369700095);
3448 assert(index == 6);
3450 assert(buffer.peek!ubyte(&index) == 8);
3451 assert(index == 7);
3455 @safe unittest
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);
3465 @system unittest
3468 //bool
3469 ubyte[] buffer = [0, 1];
3470 assert(buffer.peek!bool() == false);
3471 assert(buffer.peek!bool(1) == true);
3473 size_t index = 0;
3474 assert(buffer.peek!bool(&index) == false);
3475 assert(index == 1);
3477 assert(buffer.peek!bool(&index) == true);
3478 assert(index == 2);
3482 //char (8bit)
3483 ubyte[] buffer = [97, 98, 99, 100];
3484 assert(buffer.peek!char() == 'a');
3485 assert(buffer.peek!char(1) == 'b');
3487 size_t index = 0;
3488 assert(buffer.peek!char(&index) == 'a');
3489 assert(index == 1);
3491 assert(buffer.peek!char(&index) == 'b');
3492 assert(index == 2);
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) == 'ć');
3502 size_t index = 0;
3503 assert(buffer.peek!wchar(&index) == 'ą');
3504 assert(index == 2);
3506 assert(buffer.peek!wchar(&index) == '”');
3507 assert(index == 4);
3509 assert(buffer.peek!wchar(&index) == 'ć');
3510 assert(index == 6);
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) == 'ć');
3520 size_t index = 0;
3521 assert(buffer.peek!dchar(&index) == 'ą');
3522 assert(index == 4);
3524 assert(buffer.peek!dchar(&index) == '”');
3525 assert(index == 8);
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);
3537 size_t index = 0;
3538 assert(buffer.peek!float(&index) == 32.0f);
3539 assert(index == 4);
3541 assert(buffer.peek!float(&index) == 25.0f);
3542 assert(index == 8);
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);
3551 size_t index = 0;
3552 assert(buffer.peek!double(&index) == 32.0);
3553 assert(index == 8);
3555 assert(buffer.peek!double(&index) == 25.0);
3556 assert(index == 16);
3560 //enum
3561 ubyte[] buffer = [0, 0, 0, 10, 0, 0, 0, 20, 0, 0, 0, 30];
3563 enum Foo
3565 one = 10,
3566 two = 20,
3567 three = 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);
3575 size_t index = 0;
3576 assert(buffer.peek!Foo(&index) == Foo.one);
3577 assert(index == 4);
3579 assert(buffer.peek!Foo(&index) == Foo.two);
3580 assert(index == 8);
3582 assert(buffer.peek!Foo(&index) == Foo.three);
3583 assert(index == 12);
3587 //enum - bool
3588 ubyte[] buffer = [0, 1];
3590 enum Bool: bool
3592 bfalse = false,
3593 btrue = true,
3596 assert(buffer.peek!Bool() == Bool.bfalse);
3597 assert(buffer.peek!Bool(0) == Bool.bfalse);
3598 assert(buffer.peek!Bool(1) == Bool.btrue);
3600 size_t index = 0;
3601 assert(buffer.peek!Bool(&index) == Bool.bfalse);
3602 assert(index == 1);
3604 assert(buffer.peek!Bool(&index) == Bool.btrue);
3605 assert(index == 2);
3609 //enum - float
3610 ubyte[] buffer = [66, 0, 0, 0, 65, 200, 0, 0];
3612 enum Float: float
3614 one = 32.0f,
3615 two = 25.0f
3618 assert(buffer.peek!Float() == Float.one);
3619 assert(buffer.peek!Float(0) == Float.one);
3620 assert(buffer.peek!Float(4) == Float.two);
3622 size_t index = 0;
3623 assert(buffer.peek!Float(&index) == Float.one);
3624 assert(index == 4);
3626 assert(buffer.peek!Float(&index) == Float.two);
3627 assert(index == 8);
3631 //enum - double
3632 ubyte[] buffer = [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0];
3634 enum Double: double
3636 one = 32.0,
3637 two = 25.0
3640 assert(buffer.peek!Double() == Double.one);
3641 assert(buffer.peek!Double(0) == Double.one);
3642 assert(buffer.peek!Double(8) == Double.two);
3644 size_t index = 0;
3645 assert(buffer.peek!Double(&index) == Double.one);
3646 assert(index == 8);
3648 assert(buffer.peek!Double(&index) == Double.two);
3649 assert(index == 16);
3653 //enum - real
3654 ubyte[] buffer = [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0];
3656 enum Real: real
3658 one = 32.0,
3659 two = 25.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
3670 the range.
3672 Params:
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);
3685 else
3687 ubyte[T.sizeof] bytes;
3689 foreach (ref e; bytes)
3691 e = range.front;
3692 range.popFront();
3696 static if (endianness == Endian.bigEndian)
3697 return bigEndianToNative!T(bytes);
3698 else
3699 return littleEndianToNative!T(bytes);
3703 @safe unittest
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);
3719 @safe unittest
3722 //bool
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);
3734 //char (8bit)
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);
3803 //enum - uint
3804 ubyte[] buffer = [0, 0, 0, 10, 0, 0, 0, 20, 0, 0, 0, 30];
3805 assert(buffer.length == 12);
3807 enum Foo
3809 one = 10,
3810 two = 20,
3811 three = 30
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);
3825 //enum - bool
3826 ubyte[] buffer = [0, 1];
3827 assert(buffer.length == 2);
3829 enum Bool: bool
3831 bfalse = false,
3832 btrue = true,
3835 assert(buffer.read!Bool() == Bool.bfalse);
3836 assert(buffer.length == 1);
3838 assert(buffer.read!Bool() == Bool.btrue);
3839 assert(buffer.empty);
3843 //enum - float
3844 ubyte[] buffer = [66, 0, 0, 0, 65, 200, 0, 0];
3845 assert(buffer.length == 8);
3847 enum Float: float
3849 one = 32.0f,
3850 two = 25.0f
3853 assert(buffer.read!Float() == Float.one);
3854 assert(buffer.length == 4);
3856 assert(buffer.read!Float() == Float.two);
3857 assert(buffer.empty);
3861 //enum - double
3862 ubyte[] buffer = [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0];
3863 assert(buffer.length == 16);
3865 enum Double: double
3867 one = 32.0,
3868 two = 25.0
3871 assert(buffer.read!Double() == Double.one);
3872 assert(buffer.length == 8);
3874 assert(buffer.read!Double() == Double.two);
3875 assert(buffer.empty);
3879 //enum - real
3880 ubyte[] buffer = [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0];
3882 enum Real: real
3884 one = 32.0,
3885 two = 25.0
3888 static assert(!__traits(compiles, buffer.read!Real()));
3892 // https://issues.dlang.org/show_bug.cgi?id=17247
3893 @safe unittest
3895 struct UbyteRange
3897 ubyte[] impl;
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)();
3915 assert(x == 1);
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`.
3924 Params:
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 &&
3934 isForwardRange!R &&
3935 hasSlicing!R &&
3936 is(ElementType!R : ubyte))
3938 write!(T, endianness)(range, value, &index);
3941 /++ Ditto +/
3942 void write(T, Endian endianness = Endian.bigEndian, R)(R range, const T value, size_t* index)
3943 if (canSwapEndianness!T &&
3944 isForwardRange!R &&
3945 hasSlicing!R &&
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);
3952 else
3953 immutable bytes = nativeToLittleEndian!T(value);
3955 immutable begin = *index;
3956 immutable end = begin + T.sizeof;
3957 *index = end;
3958 range[begin .. end] = bytes[0 .. T.sizeof];
3962 @system unittest
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]);
3976 @system unittest
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]);
3990 @system unittest
3992 ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0];
3993 size_t index = 0;
3994 buffer.write!ushort(261, &index);
3995 assert(buffer == [1, 5, 0, 0, 0, 0, 0, 0]);
3996 assert(index == 2);
3998 buffer.write!uint(369700095u, &index);
3999 assert(buffer == [1, 5, 22, 9, 44, 255, 0, 0]);
4000 assert(index == 6);
4002 buffer.write!ubyte(8, &index);
4003 assert(buffer == [1, 5, 22, 9, 44, 255, 8, 0]);
4004 assert(index == 7);
4007 /// bool
4008 @system unittest
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]);
4023 size_t index = 0;
4024 buffer.write!bool(false, &index);
4025 assert(buffer == [0, 0]);
4026 assert(index == 1);
4028 buffer.write!bool(true, &index);
4029 assert(buffer == [0, 1]);
4030 assert(index == 2);
4033 /// char(8-bit)
4034 @system unittest
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]);
4044 size_t index = 0;
4045 buffer.write!char('a', &index);
4046 assert(buffer == [97, 98, 0]);
4047 assert(index == 1);
4049 buffer.write!char('b', &index);
4050 assert(buffer == [97, 98, 0]);
4051 assert(index == 2);
4053 buffer.write!char('c', &index);
4054 assert(buffer == [97, 98, 99]);
4055 assert(index == 3);
4058 /// wchar (16bit - 2x ubyte)
4059 @system unittest
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]);
4069 size_t index = 0;
4070 buffer.write!wchar('ć', &index);
4071 assert(buffer == [1, 7, 32, 29]);
4072 assert(index == 2);
4074 buffer.write!wchar('ą', &index);
4075 assert(buffer == [1, 7, 1, 5]);
4076 assert(index == 4);
4079 /// dchar (32bit - 4x ubyte)
4080 @system unittest
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]);
4090 size_t index = 0;
4091 buffer.write!dchar('ć', &index);
4092 assert(buffer == [0, 0, 1, 7, 0, 0, 32, 29]);
4093 assert(index == 4);
4095 buffer.write!dchar('ą', &index);
4096 assert(buffer == [0, 0, 1, 7, 0, 0, 1, 5]);
4097 assert(index == 8);
4100 /// float (32bit - 4x ubyte)
4101 @system unittest
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]);
4111 size_t index = 0;
4112 buffer.write!float(25.0f, &index);
4113 assert(buffer == [65, 200, 0, 0, 65, 200, 0, 0]);
4114 assert(index == 4);
4116 buffer.write!float(32.0f, &index);
4117 assert(buffer == [65, 200, 0, 0, 66, 0, 0, 0]);
4118 assert(index == 8);
4121 /// double (64bit - 8x ubyte)
4122 @system unittest
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]);
4132 size_t index = 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]);
4135 assert(index == 8);
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);
4142 /// enum
4143 @system unittest
4145 ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4147 enum Foo
4149 one = 10,
4150 two = 20,
4151 three = 30
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]);
4163 size_t index = 0;
4164 buffer.write!Foo(Foo.three, &index);
4165 assert(buffer == [0, 0, 0, 30, 0, 0, 0, 20, 0, 0, 0, 30]);
4166 assert(index == 4);
4168 buffer.write!Foo(Foo.one, &index);
4169 assert(buffer == [0, 0, 0, 30, 0, 0, 0, 10, 0, 0, 0, 30]);
4170 assert(index == 8);
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);
4177 // enum - bool
4178 @system unittest
4180 ubyte[] buffer = [0, 0];
4182 enum Bool: bool
4184 bfalse = false,
4185 btrue = true,
4188 buffer.write!Bool(Bool.btrue, 0);
4189 assert(buffer == [1, 0]);
4191 buffer.write!Bool(Bool.btrue, 1);
4192 assert(buffer == [1, 1]);
4194 size_t index = 0;
4195 buffer.write!Bool(Bool.bfalse, &index);
4196 assert(buffer == [0, 1]);
4197 assert(index == 1);
4199 buffer.write!Bool(Bool.bfalse, &index);
4200 assert(buffer == [0, 0]);
4201 assert(index == 2);
4204 /// enum - float
4205 @system unittest
4207 ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0];
4209 enum Float: float
4211 one = 32.0f,
4212 two = 25.0f
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]);
4221 size_t index = 0;
4222 buffer.write!Float(Float.two, &index);
4223 assert(buffer == [65, 200, 0, 0, 65, 200, 0, 0]);
4224 assert(index == 4);
4226 buffer.write!Float(Float.one, &index);
4227 assert(buffer == [65, 200, 0, 0, 66, 0, 0, 0]);
4228 assert(index == 8);
4231 /// enum - double
4232 @system unittest
4234 ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4236 enum Double: double
4238 one = 32.0,
4239 two = 25.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]);
4248 size_t index = 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]);
4251 assert(index == 8);
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);
4258 /// enum - real
4259 @system unittest
4261 ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4263 enum Real: real
4265 one = 32.0,
4266 two = 25.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
4277 `true`.
4279 Params:
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);
4290 else
4291 immutable bytes = nativeToLittleEndian!T(value);
4293 put(range, bytes[]);
4297 @safe unittest
4299 import std.array;
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]);
4311 /// bool
4312 @safe unittest
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
4325 @safe unittest
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]);
4343 /// float double
4344 @safe unittest
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]);
4356 /// enum
4357 @safe unittest
4359 import std.array : appender;
4360 auto buffer = appender!(const ubyte[])();
4362 enum Foo
4364 one = 10,
4365 two = 20,
4366 three = 30
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]);
4379 /// enum - bool
4380 @safe unittest
4382 import std.array : appender;
4383 auto buffer = appender!(const ubyte[])();
4385 enum Bool: bool
4387 bfalse = false,
4388 btrue = true,
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]);
4401 /// enum - float
4402 @safe unittest
4404 import std.array : appender;
4405 auto buffer = appender!(const ubyte[])();
4407 enum Float: float
4409 one = 32.0f,
4410 two = 25.0f
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]);
4420 /// enum - double
4421 @safe unittest
4423 import std.array : appender;
4424 auto buffer = appender!(const ubyte[])();
4426 enum Double: double
4428 one = 32.0,
4429 two = 25.0
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]);
4439 /// enum - real
4440 @safe unittest
4442 import std.array : appender;
4443 auto buffer = appender!(const ubyte[])();
4445 enum Real: real
4447 one = 32.0,
4448 two = 25.0
4451 static assert(!__traits(compiles, buffer.append!Real(Real.one)));
4454 @system unittest
4456 import std.array;
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);
4466 size_t index = 0;
4467 size_t length = 0;
4468 static foreach (T; Types)
4470 toWrite.append!(T, endianness)(cast(T) values[index++]);
4471 length += T.sizeof;
4474 auto toRead = toWrite.data;
4475 assert(toRead.length == length);
4477 index = 0;
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));
4485 length -= T.sizeof;
4486 assert(toRead.length == length,
4487 format("Failed Index [%s], Actual Length: %s", index, toRead.length));
4488 ++index;
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)
4499 if (isIntegral!T)
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;
4525 else
4527 static assert(false, "countBitsSet only supports 1, 2, 4, or 8 byte sized integers.");
4529 return cast(uint) c;
4532 @safe unittest
4534 assert(countBitsSet(1) == 1);
4535 assert(countBitsSet(0) == 0);
4536 assert(countBitsSet(int.min) == 1);
4537 assert(countBitsSet(uint.max) == 32);
4540 @safe unittest
4542 import std.meta;
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);
4557 else
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.");
4573 @nogc pure nothrow:
4575 this(T value, size_t startIndex = 0)
4577 _value = value;
4578 // Further calculation is only valid and needed when the range is non-empty.
4579 if (!_value)
4580 return;
4582 import core.bitop : bsf;
4583 immutable trailingZerosCount = bsf(value);
4584 _value >>>= trailingZerosCount;
4585 _index = startIndex + trailingZerosCount;
4588 @property size_t front() const
4590 return _index;
4593 @property bool empty() const
4595 return !_value;
4598 void popFront()
4600 assert(_value, "Cannot call popFront on empty range.");
4602 _value >>>= 1;
4603 // Further calculation is only valid and needed when the range is non-empty.
4604 if (!_value)
4605 return;
4607 import core.bitop : bsf;
4608 immutable trailingZerosCount = bsf(_value);
4609 _value >>>= trailingZerosCount;
4610 _index += trailingZerosCount + 1;
4613 @property BitsSet save() const
4615 return this;
4618 @property size_t length() const
4620 return countBitsSet(_value);
4623 private T _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
4633 if (isIntegral!T)
4635 return BitsSet!T(value);
4639 @safe unittest
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]));
4650 @safe unittest
4652 import std.algorithm.comparison : equal;
4653 import std.range : iota;
4655 import std.meta;
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]));
4670 else
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
4683 enum Bar : bool
4689 struct Foo
4691 mixin(bitfields!(Bar, "bar", 1, ubyte, "", 7,));
4694 Foo foo;
4695 foo.bar = Bar.a;
4696 assert(foo.bar == Bar.a);
4697 foo.bar = Bar.b;
4698 assert(foo.bar == Bar.b);