d: Merge dmd. druntime e770945277, phobos 6d6e0b9b9
[official-gcc.git] / libphobos / src / std / bitmanip.d
blobc9813e35476dfb94610b8a7ff51fa291a7c806be
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 import std.conv : to;
168 static assert(false, "Field widths must sum to 8, 16, 32, or 64, not " ~ to!string(Size));
169 alias StoreType = ulong; // just to avoid another error msg
172 enum createStorageAndFields
173 = "private " ~ StoreType.stringof ~ " " ~ Name ~ ";"
174 ~ createFields!(Name, 0, Ts);
177 private template createFields(string store, size_t offset, Ts...)
179 static if (Ts.length > 0)
180 enum createFields
181 = createAccessors!(store, Ts[0], Ts[1], Ts[2], offset)
182 ~ createFields!(store, offset + Ts[2], Ts[3 .. $]);
183 else
184 enum createFields = "";
187 private ulong getBitsForAlign(ulong a)
189 ulong bits = 0;
190 while ((a & 0x01) == 0)
192 bits++;
193 a >>= 1;
196 assert(a == 1, "alignment is not a power of 2");
197 return bits;
200 private template createReferenceAccessor(string store, T, ulong bits, string name)
202 enum storage = "private void* " ~ store ~ "_ptr;\n";
203 enum storage_accessor = "@property ref size_t " ~ store ~ "() return @trusted pure nothrow @nogc const { "
204 ~ "return *cast(size_t*) &" ~ store ~ "_ptr;}\n"
205 ~ "@property void " ~ store ~ "(size_t v) @trusted pure nothrow @nogc { "
206 ~ "" ~ store ~ "_ptr = cast(void*) v;}\n";
208 enum mask = (1UL << bits) - 1;
209 // getter
210 enum ref_accessor = "@property "~T.stringof~" "~name~"() @trusted pure nothrow @nogc const { auto result = "
211 ~ "("~store~" & "~myToString(~mask)~"); "
212 ~ "return cast("~T.stringof~") cast(void*) result;}\n"
213 // setter
214 ~"@property void "~name~"("~T.stringof~" v) @trusted pure nothrow @nogc { "
215 ~"assert(((cast(typeof("~store~")) cast(void*) v) & "~myToString(mask)
216 ~`) == 0, "Value not properly aligned for '`~name~`'"); `
217 ~store~" = cast(typeof("~store~"))"
218 ~" (("~store~" & (cast(typeof("~store~")) "~myToString(mask)~"))"
219 ~" | ((cast(typeof("~store~")) cast(void*) v) & (cast(typeof("~store~")) "~myToString(~mask)~")));}\n";
221 enum createReferenceAccessor = storage ~ storage_accessor ~ ref_accessor;
224 private template sizeOfBitField(T...)
226 static if (T.length < 2)
227 enum sizeOfBitField = 0;
228 else
229 enum sizeOfBitField = T[2] + sizeOfBitField!(T[3 .. $]);
232 private template createTaggedReference(T, ulong a, string name, Ts...)
234 static assert(
235 sizeOfBitField!Ts <= getBitsForAlign(a),
236 "Fields must fit in the bits know to be zero because of alignment."
238 enum StoreName = createStoreName!(T, name, 0, Ts);
239 enum createTaggedReference
240 = createReferenceAccessor!(StoreName, T, sizeOfBitField!Ts, name)
241 ~ createFields!(StoreName, 0, Ts, size_t, "", T.sizeof * 8 - sizeOfBitField!Ts);
245 Allows creating `bitfields` inside `structs`, `classes` and `unions`.
247 A `bitfield` consists of one or more entries with a fixed number of
248 bits reserved for each of the entries. The types of the entries can
249 be `bool`s, integral types or enumerated types, arbitrarily mixed.
250 The most efficient type to store in `bitfields` is `bool`, followed
251 by unsigned types, followed by signed types.
253 Each non-`bool` entry of the `bitfield` will be represented by the
254 number of bits specified by the user. The minimum and the maximum
255 numbers that represent this domain can be queried by using the name
256 of the variable followed by `_min` or `_max`.
258 Limitation: The number of bits in a `bitfield` is limited to 8, 16,
259 32 or 64. If padding is needed, an entry should be explicitly
260 allocated with an empty name.
262 Implementation_details: `Bitfields` are internally stored in an
263 `ubyte`, `ushort`, `uint` or `ulong` depending on the number of bits
264 used. The bits are filled in the order given by the parameters,
265 starting with the lowest significant bit. The name of the (private)
266 variable used for saving the `bitfield` is created by concatenating
267 all of the variable names, each preceded by an underscore, and
268 a suffix `_bf`.
270 Params: T = A list of template parameters divided into chunks of 3
271 items. Each chunk consists (in this order) of a type, a
272 name and a number. Together they define an entry
273 of the `bitfield`: a variable of the given type and name,
274 which can hold as many bits as the number denotes.
276 Returns: A string that can be used in a `mixin` to add the `bitfield`.
278 See_Also: $(REF BitFlags, std,typecons)
280 string bitfields(T...)()
282 static assert(T.length % 3 == 0,
283 "Wrong number of arguments (" ~ T.length.stringof ~ "): Must be a multiple of 3");
285 static foreach (i, ARG; T)
287 static if (i % 3 == 0)
288 static assert(is (typeof({ARG tmp = cast (ARG)0; if (ARG.min < 0) {} }())),
289 "Integral type or `bool` expected, found " ~ ARG.stringof);
291 // would be nice to check for valid variable names too
292 static if (i % 3 == 1)
293 static assert(is (typeof(ARG) : string),
294 "Variable name expected, found " ~ ARG.stringof);
296 static if (i % 3 == 2)
298 static assert(is (typeof({ulong tmp = ARG;}())),
299 "Integral value expected, found " ~ ARG.stringof);
301 static if (T[i-1] != "")
303 static assert(!is (T[i-2] : bool) || ARG <= 1,
304 "Type `bool` is only allowed for single-bit fields");
306 static assert(ARG >= 0 && ARG <= T[i-2].sizeof * 8,
307 "Wrong size of bitfield: " ~ ARG.stringof);
312 return createStorageAndFields!T;
316 Create a `bitfield` pack of eight bits, which fit in
317 one `ubyte`. The `bitfields` are allocated starting from the
318 least significant bit, i.e. `x` occupies the two least significant bits
319 of the `bitfields` storage.
321 @safe unittest
323 struct A
325 int a;
326 mixin(bitfields!(
327 uint, "x", 2,
328 int, "y", 3,
329 uint, "z", 2,
330 bool, "flag", 1));
333 A obj;
334 obj.x = 2;
335 obj.z = obj.x;
337 assert(obj.x == 2);
338 assert(obj.y == 0);
339 assert(obj.z == 2);
340 assert(obj.flag == false);
344 The sum of all bit lengths in one `bitfield` instantiation
345 must be exactly 8, 16, 32, or 64. If padding is needed, just allocate
346 one bitfield with an empty name.
348 @safe unittest
350 struct A
352 mixin(bitfields!(
353 bool, "flag1", 1,
354 bool, "flag2", 1,
355 uint, "", 6));
358 A a;
359 assert(a.flag1 == 0);
360 a.flag1 = 1;
361 assert(a.flag1 == 1);
362 a.flag1 = 0;
363 assert(a.flag1 == 0);
366 /// enums can be used too
367 @safe unittest
369 enum ABC { A, B, C }
370 struct EnumTest
372 mixin(bitfields!(
373 ABC, "x", 2,
374 bool, "y", 1,
375 ubyte, "z", 5));
379 @safe pure nothrow @nogc
380 unittest
382 // Degenerate bitfields tests mixed with range tests
383 // https://issues.dlang.org/show_bug.cgi?id=8474
384 // https://issues.dlang.org/show_bug.cgi?id=11160
385 struct Test1
387 mixin(bitfields!(uint, "a", 32,
388 uint, "b", 4,
389 uint, "c", 4,
390 uint, "d", 8,
391 uint, "e", 16,));
393 static assert(Test1.b_min == 0);
394 static assert(Test1.b_max == 15);
397 struct Test2
399 mixin(bitfields!(bool, "a", 0,
400 ulong, "b", 64));
402 static assert(Test2.b_min == ulong.min);
403 static assert(Test2.b_max == ulong.max);
406 struct Test1b
408 mixin(bitfields!(bool, "a", 0,
409 int, "b", 8));
412 struct Test2b
414 mixin(bitfields!(int, "a", 32,
415 int, "b", 4,
416 int, "c", 4,
417 int, "d", 8,
418 int, "e", 16,));
420 static assert(Test2b.b_min == -8);
421 static assert(Test2b.b_max == 7);
424 struct Test3b
426 mixin(bitfields!(bool, "a", 0,
427 long, "b", 64));
429 static assert(Test3b.b_min == long.min);
430 static assert(Test3b.b_max == long.max);
433 struct Test4b
435 mixin(bitfields!(long, "a", 32,
436 int, "b", 32));
439 // Sign extension tests
440 Test2b t2b;
441 Test4b t4b;
442 t2b.b = -5; assert(t2b.b == -5);
443 t2b.d = -5; assert(t2b.d == -5);
444 t2b.e = -5; assert(t2b.e == -5);
445 t4b.a = -5; assert(t4b.a == -5L);
448 // https://issues.dlang.org/show_bug.cgi?id=6686
449 @safe unittest
451 union S {
452 ulong bits = ulong.max;
453 mixin (bitfields!(
454 ulong, "back", 31,
455 ulong, "front", 33)
458 S num;
460 num.bits = ulong.max;
461 num.back = 1;
462 assert(num.bits == 0xFFFF_FFFF_8000_0001uL);
465 // https://issues.dlang.org/show_bug.cgi?id=5942
466 @safe unittest
468 struct S
470 mixin(bitfields!(
471 int, "a" , 32,
472 int, "b" , 32
476 S data;
477 data.b = 42;
478 data.a = 1;
479 assert(data.b == 42);
482 @safe unittest
484 struct Test
486 mixin(bitfields!(bool, "a", 1,
487 uint, "b", 3,
488 short, "c", 4));
491 @safe void test() pure nothrow
493 Test t;
495 t.a = true;
496 t.b = 5;
497 t.c = 2;
499 assert(t.a);
500 assert(t.b == 5);
501 assert(t.c == 2);
504 test();
507 @safe unittest
510 static struct Integrals {
511 bool checkExpectations(bool eb, int ei, short es) { return b == eb && i == ei && s == es; }
513 mixin(bitfields!(
514 bool, "b", 1,
515 uint, "i", 3,
516 short, "s", 4));
518 Integrals i;
519 assert(i.checkExpectations(false, 0, 0));
520 i.b = true;
521 assert(i.checkExpectations(true, 0, 0));
522 i.i = 7;
523 assert(i.checkExpectations(true, 7, 0));
524 i.s = -8;
525 assert(i.checkExpectations(true, 7, -8));
526 i.s = 7;
527 assert(i.checkExpectations(true, 7, 7));
530 //https://issues.dlang.org/show_bug.cgi?id=8876
532 struct MoreIntegrals {
533 bool checkExpectations(uint eu, ushort es, uint ei) { return u == eu && s == es && i == ei; }
535 mixin(bitfields!(
536 uint, "u", 24,
537 short, "s", 16,
538 int, "i", 24));
541 MoreIntegrals i;
542 assert(i.checkExpectations(0, 0, 0));
543 i.s = 20;
544 assert(i.checkExpectations(0, 20, 0));
545 i.i = 72;
546 assert(i.checkExpectations(0, 20, 72));
547 i.u = 8;
548 assert(i.checkExpectations(8, 20, 72));
549 i.s = 7;
550 assert(i.checkExpectations(8, 7, 72));
553 enum A { True, False }
554 enum B { One, Two, Three, Four }
555 static struct Enums {
556 bool checkExpectations(A ea, B eb) { return a == ea && b == eb; }
558 mixin(bitfields!(
559 A, "a", 1,
560 B, "b", 2,
561 uint, "", 5));
563 Enums e;
564 assert(e.checkExpectations(A.True, B.One));
565 e.a = A.False;
566 assert(e.checkExpectations(A.False, B.One));
567 e.b = B.Three;
568 assert(e.checkExpectations(A.False, B.Three));
570 static struct SingleMember {
571 bool checkExpectations(bool eb) { return b == eb; }
573 mixin(bitfields!(
574 bool, "b", 1,
575 uint, "", 7));
577 SingleMember f;
578 assert(f.checkExpectations(false));
579 f.b = true;
580 assert(f.checkExpectations(true));
583 // https://issues.dlang.org/show_bug.cgi?id=12477
584 @system unittest
586 import core.exception : AssertError;
587 import std.algorithm.searching : canFind;
589 static struct S
591 mixin(bitfields!(
592 uint, "a", 6,
593 int, "b", 2));
596 S s;
598 try { s.a = uint.max; assert(0); }
599 catch (AssertError ae)
600 { assert(ae.msg.canFind("Value is greater than the maximum value of bitfield 'a'"), ae.msg); }
602 try { s.b = int.min; assert(0); }
603 catch (AssertError ae)
604 { assert(ae.msg.canFind("Value is smaller than the minimum value of bitfield 'b'"), ae.msg); }
607 // https://issues.dlang.org/show_bug.cgi?id=15305
608 @safe unittest
610 struct S {
611 mixin(bitfields!(
612 bool, "alice", 1,
613 ulong, "bob", 63,
617 S s;
618 s.bob = long.max - 1;
619 s.alice = false;
620 assert(s.bob == long.max - 1);
623 // https://issues.dlang.org/show_bug.cgi?id=21634
624 @safe unittest
626 struct A
628 mixin(bitfields!(int, "", 1,
629 int, "gshared", 7));
633 // https://issues.dlang.org/show_bug.cgi?id=21725
634 @safe unittest
636 struct S
638 mixin(bitfields!(
639 uint, q{foo}, 4,
640 uint, null, 4,
646 This string mixin generator allows one to create tagged pointers inside $(D_PARAM struct)s and $(D_PARAM class)es.
648 A tagged pointer uses the bits known to be zero in a normal pointer or class reference to store extra information.
649 For example, a pointer to an integer must be 4-byte aligned, so there are 2 bits that are always known to be zero.
650 One can store a 2-bit integer there.
652 The example above creates a tagged pointer in the struct A. The pointer is of type
653 `uint*` as specified by the first argument, and is named x, as specified by the second
654 argument.
656 Following arguments works the same way as `bitfield`'s. The bitfield must fit into the
657 bits known to be zero because of the pointer alignment.
660 template taggedPointer(T : T*, string name, Ts...) {
661 enum taggedPointer = createTaggedReference!(T*, T.alignof, name, Ts);
665 @safe unittest
667 struct A
669 int a;
670 mixin(taggedPointer!(
671 uint*, "x",
672 bool, "b1", 1,
673 bool, "b2", 1));
675 A obj;
676 obj.x = new uint;
677 obj.b1 = true;
678 obj.b2 = false;
681 @system unittest
683 struct Test5
685 mixin(taggedPointer!(
686 int*, "a",
687 uint, "b", 2));
690 Test5 t5;
691 t5.a = null;
692 t5.b = 3;
693 assert(t5.a is null);
694 assert(t5.b == 3);
696 int myint = 42;
697 t5.a = &myint;
698 assert(t5.a is &myint);
699 assert(t5.b == 3);
703 This string mixin generator allows one to create tagged class reference inside $(D_PARAM struct)s and $(D_PARAM class)es.
705 A tagged class reference uses the bits known to be zero in a normal class reference to store extra information.
706 For example, a pointer to an integer must be 4-byte aligned, so there are 2 bits that are always known to be zero.
707 One can store a 2-bit integer there.
709 The example above creates a tagged reference to an Object in the struct A. This expects the same parameters
710 as `taggedPointer`, except the first argument which must be a class type instead of a pointer type.
713 template taggedClassRef(T, string name, Ts...)
714 if (is(T == class))
716 enum taggedClassRef = createTaggedReference!(T, 8, name, Ts);
720 @safe unittest
722 struct A
724 int a;
725 mixin(taggedClassRef!(
726 Object, "o",
727 uint, "i", 2));
729 A obj;
730 obj.o = new Object();
731 obj.i = 3;
734 @system unittest
736 struct Test6
738 mixin(taggedClassRef!(
739 Object, "o",
740 bool, "b", 1));
743 Test6 t6;
744 t6.o = null;
745 t6.b = false;
746 assert(t6.o is null);
747 assert(t6.b == false);
749 auto o = new Object();
750 t6.o = o;
751 t6.b = true;
752 assert(t6.o is o);
753 assert(t6.b == true);
756 @safe unittest
758 static assert(!__traits(compiles,
759 taggedPointer!(
760 int*, "a",
761 uint, "b", 3)));
763 static assert(!__traits(compiles,
764 taggedClassRef!(
765 Object, "a",
766 uint, "b", 4)));
768 struct S {
769 mixin(taggedClassRef!(
770 Object, "a",
771 bool, "b", 1));
774 const S s;
775 void bar(S s) {}
777 static assert(!__traits(compiles, bar(s)));
780 private struct FloatingPointRepresentation(T)
782 static if (is(T == float))
784 enum uint bias = 127, fractionBits = 23, exponentBits = 8, signBits = 1;
785 alias FractionType = uint;
786 alias ExponentType = ubyte;
788 else
790 enum uint bias = 1023, fractionBits = 52, exponentBits = 11, signBits = 1;
791 alias FractionType = ulong;
792 alias ExponentType = ushort;
795 union
797 T value;
798 mixin(bitfields!(
799 FractionType, "fraction", fractionBits,
800 ExponentType, "exponent", exponentBits,
801 bool, "sign", signBits));
806 Allows manipulating the fraction, exponent, and sign parts of a
807 `float` separately. The definition is:
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 ----
824 alias FloatRep = FloatingPointRepresentation!float;
827 @safe unittest
829 FloatRep rep = {value: 0};
830 assert(rep.fraction == 0);
831 assert(rep.exponent == 0);
832 assert(!rep.sign);
834 rep.value = 42;
835 assert(rep.fraction == 2621440);
836 assert(rep.exponent == 132);
837 assert(!rep.sign);
839 rep.value = 10;
840 assert(rep.fraction == 2097152);
841 assert(rep.exponent == 130);
845 @safe unittest
847 FloatRep rep = {value: 1};
848 assert(rep.fraction == 0);
849 assert(rep.exponent == 127);
850 assert(!rep.sign);
852 rep.exponent = 126;
853 assert(rep.value == 0.5);
855 rep.exponent = 130;
856 assert(rep.value == 8);
860 @safe unittest
862 FloatRep rep = {value: 1};
863 rep.value = -0.5;
864 assert(rep.fraction == 0);
865 assert(rep.exponent == 126);
866 assert(rep.sign);
868 rep.value = -1. / 3;
869 assert(rep.fraction == 2796203);
870 assert(rep.exponent == 125);
871 assert(rep.sign);
875 Allows manipulating the fraction, exponent, and sign parts of a
876 `double` separately. The definition is:
878 ----
879 struct DoubleRep
881 union
883 double value;
884 mixin(bitfields!(
885 ulong, "fraction", 52,
886 ushort, "exponent", 11,
887 bool, "sign", 1));
889 enum uint bias = 1023, signBits = 1, fractionBits = 52, exponentBits = 11;
891 ----
893 alias DoubleRep = FloatingPointRepresentation!double;
896 @safe unittest
898 DoubleRep rep = {value: 0};
899 assert(rep.fraction == 0);
900 assert(rep.exponent == 0);
901 assert(!rep.sign);
903 rep.value = 42;
904 assert(rep.fraction == 1407374883553280);
905 assert(rep.exponent == 1028);
906 assert(!rep.sign);
908 rep.value = 10;
909 assert(rep.fraction == 1125899906842624);
910 assert(rep.exponent == 1026);
914 @safe unittest
916 DoubleRep rep = {value: 1};
917 assert(rep.fraction == 0);
918 assert(rep.exponent == 1023);
919 assert(!rep.sign);
921 rep.exponent = 1022;
922 assert(rep.value == 0.5);
924 rep.exponent = 1026;
925 assert(rep.value == 8);
929 @safe unittest
931 DoubleRep rep = {value: 1};
932 rep.value = -0.5;
933 assert(rep.fraction == 0);
934 assert(rep.exponent == 1022);
935 assert(rep.sign);
937 rep.value = -1. / 3;
938 assert(rep.fraction == 1501199875790165);
939 assert(rep.exponent == 1021);
940 assert(rep.sign);
943 /// Reading
944 @safe unittest
946 DoubleRep x;
947 x.value = 1.0;
948 assert(x.fraction == 0 && x.exponent == 1023 && !x.sign);
949 x.value = -0.5;
950 assert(x.fraction == 0 && x.exponent == 1022 && x.sign);
951 x.value = 0.5;
952 assert(x.fraction == 0 && x.exponent == 1022 && !x.sign);
955 /// Writing
956 @safe unittest
958 DoubleRep x;
959 x.fraction = 1125899906842624;
960 x.exponent = 1025;
961 x.sign = true;
962 assert(x.value == -5.0);
966 A dynamic array of bits. Each bit in a `BitArray` can be manipulated individually
967 or by the standard bitwise operators `&`, `|`, `^`, `~`, `>>`, `<<` and also by
968 other effective member functions; most of them work relative to the `BitArray`'s
969 dimension (see $(LREF dim)), instead of its $(LREF length).
971 struct BitArray
973 private:
975 import core.bitop : btc, bts, btr, bsf, bt;
976 import std.format.spec : FormatSpec;
978 size_t _len;
979 size_t* _ptr;
980 enum bitsPerSizeT = size_t.sizeof * 8;
982 @property size_t fullWords() const scope @safe @nogc pure nothrow
984 return _len / bitsPerSizeT;
986 // Number of bits after the last full word
987 @property size_t endBits() const scope @safe @nogc pure nothrow
989 return _len % bitsPerSizeT;
991 // Bit mask to extract the bits after the last full word
992 @property size_t endMask() const scope @safe @nogc pure nothrow
994 return (size_t(1) << endBits) - 1;
996 static size_t lenToDim(size_t len) @nogc pure nothrow @safe
998 return (len + (bitsPerSizeT-1)) / bitsPerSizeT;
1001 public:
1003 Creates a `BitArray` from a `bool` array, such that `bool` values read
1004 from left to right correspond to subsequent bits in the `BitArray`.
1006 Params: ba = Source array of `bool` values.
1008 this(in bool[] ba) nothrow pure
1010 length = ba.length;
1011 foreach (i, b; ba)
1013 this[i] = b;
1018 @system unittest
1020 import std.algorithm.comparison : equal;
1022 bool[] input = [true, false, false, true, true];
1023 auto a = BitArray(input);
1024 assert(a.length == 5);
1025 assert(a.bitsSet.equal([0, 3, 4]));
1027 // This also works because an implicit cast to bool[] occurs for this array.
1028 auto b = BitArray([0, 0, 1]);
1029 assert(b.length == 3);
1030 assert(b.bitsSet.equal([2]));
1034 @system unittest
1036 import std.algorithm.comparison : equal;
1037 import std.array : array;
1038 import std.range : iota, repeat;
1040 BitArray a = true.repeat(70).array;
1041 assert(a.length == 70);
1042 assert(a.bitsSet.equal(iota(0, 70)));
1046 Creates a `BitArray` from the raw contents of the source array. The
1047 source array is not copied but simply acts as the underlying array
1048 of bits, which stores data as `size_t` units.
1050 That means a particular care should be taken when passing an array
1051 of a type different than `size_t`, firstly because its length should
1052 be a multiple of `size_t.sizeof`, and secondly because how the bits
1053 are mapped:
1055 size_t[] source = [1, 2, 3, 3424234, 724398, 230947, 389492];
1056 enum sbits = size_t.sizeof * 8;
1057 auto ba = BitArray(source, source.length * sbits);
1058 foreach (n; 0 .. source.length * sbits)
1060 auto nth_bit = cast(bool) (source[n / sbits] & (1L << (n % sbits)));
1061 assert(ba[n] == nth_bit);
1064 The least significant bit in any `size_t` unit is the starting bit of this
1065 unit, and the most significant bit is the last bit of this unit. Therefore,
1066 passing e.g. an array of `int`s may result in a different `BitArray`
1067 depending on the processor's endianness.
1069 This constructor is the inverse of $(LREF opCast).
1071 Params:
1072 v = Source array. `v.length` must be a multple of `size_t.sizeof`.
1073 numbits = Number of bits to be mapped from the source array, i.e.
1074 length of the created `BitArray`.
1076 this(void[] v, size_t numbits) @nogc nothrow pure
1079 assert(numbits <= v.length * 8,
1080 "numbits must be less than or equal to v.length * 8");
1081 assert(v.length % size_t.sizeof == 0,
1082 "v.length must be a multiple of the size of size_t");
1086 _ptr = cast(size_t*) v.ptr;
1087 _len = numbits;
1091 @system unittest
1093 import std.algorithm.comparison : equal;
1095 auto a = BitArray([1, 0, 0, 1, 1]);
1097 // Inverse of the cast.
1098 auto v = cast(void[]) a;
1099 auto b = BitArray(v, a.length);
1101 assert(b.length == 5);
1102 assert(b.bitsSet.equal([0, 3, 4]));
1104 // a and b share the underlying data.
1105 a[0] = 0;
1106 assert(b[0] == 0);
1107 assert(a == b);
1111 @system unittest
1113 import std.algorithm.comparison : equal;
1115 size_t[] source = [0b1100, 0b0011];
1116 enum sbits = size_t.sizeof * 8;
1117 auto ba = BitArray(source, source.length * sbits);
1118 // The least significant bit in each unit is this unit's starting bit.
1119 assert(ba.bitsSet.equal([2, 3, sbits, sbits + 1]));
1123 @system unittest
1125 // Example from the doc for this constructor.
1126 static immutable size_t[] sourceData = [1, 0b101, 3, 3424234, 724398, 230947, 389492];
1127 size_t[] source = sourceData.dup;
1128 enum sbits = size_t.sizeof * 8;
1129 auto ba = BitArray(source, source.length * sbits);
1130 foreach (n; 0 .. source.length * sbits)
1132 auto nth_bit = cast(bool) (source[n / sbits] & (1L << (n % sbits)));
1133 assert(ba[n] == nth_bit);
1136 // Example of mapping only part of the array.
1137 import std.algorithm.comparison : equal;
1139 auto bc = BitArray(source, sbits + 1);
1140 assert(bc.bitsSet.equal([0, sbits]));
1141 // Source array has not been modified.
1142 assert(source == sourceData);
1145 // Deliberately undocumented: raw initialization of bit array.
1146 this(size_t len, size_t* ptr) @nogc nothrow pure
1148 _len = len;
1149 _ptr = ptr;
1153 Returns: Dimension i.e. the number of native words backing this `BitArray`.
1155 Technically, this is the length of the underlying array storing bits, which
1156 is equal to `ceil(length / (size_t.sizeof * 8))`, as bits are packed into
1157 `size_t` units.
1159 @property size_t dim() const @nogc nothrow pure @safe
1161 return lenToDim(_len);
1165 Returns: Number of bits in the `BitArray`.
1167 @property size_t length() const @nogc nothrow pure @safe
1169 return _len;
1172 /**********************************************
1173 * Sets the amount of bits in the `BitArray`.
1174 * $(RED Warning: increasing length may overwrite bits in
1175 * the final word of the current underlying data regardless
1176 * of whether it is shared between BitArray objects. i.e. D
1177 * dynamic array extension semantics are not followed.)
1179 @property size_t length(size_t newlen) pure nothrow @system
1181 if (newlen != _len)
1183 size_t olddim = dim;
1184 immutable newdim = lenToDim(newlen);
1186 if (newdim != olddim)
1188 // Create a fake array so we can use D's realloc machinery
1189 auto b = _ptr[0 .. olddim];
1190 b.length = newdim; // realloc
1191 _ptr = b.ptr;
1194 auto oldlen = _len;
1195 _len = newlen;
1196 if (oldlen < newlen)
1198 auto end = ((oldlen / bitsPerSizeT) + 1) * bitsPerSizeT;
1199 if (end > newlen)
1200 end = newlen;
1201 this[oldlen .. end] = 0;
1204 return _len;
1207 // https://issues.dlang.org/show_bug.cgi?id=20240
1208 @system unittest
1210 BitArray ba;
1212 ba.length = 1;
1213 ba[0] = 1;
1214 ba.length = 0;
1215 ba.length = 1;
1216 assert(ba[0] == 0); // OK
1218 ba.length = 2;
1219 ba[1] = 1;
1220 ba.length = 1;
1221 ba.length = 2;
1222 assert(ba[1] == 0); // Fail
1225 /**********************************************
1226 * Gets the `i`'th bit in the `BitArray`.
1228 bool opIndex(size_t i) const @nogc pure nothrow
1231 assert(i < _len, "i must be less than the length");
1235 return cast(bool) bt(_ptr, i);
1239 @system unittest
1241 static void fun(const BitArray arr)
1243 auto x = arr[0];
1244 assert(x == 1);
1246 BitArray a;
1247 a.length = 3;
1248 a[0] = 1;
1249 fun(a);
1252 /**********************************************
1253 * Sets the `i`'th bit in the `BitArray`.
1255 bool opIndexAssign(bool b, size_t i) @nogc pure nothrow
1258 assert(i < _len, "i must be less than the length");
1262 if (b)
1263 bts(_ptr, i);
1264 else
1265 btr(_ptr, i);
1266 return b;
1270 Sets all the values in the `BitArray` to the
1271 value specified by `val`.
1273 void opSliceAssign(bool val) @nogc pure nothrow
1275 _ptr[0 .. fullWords] = val ? ~size_t(0) : 0;
1276 if (endBits)
1278 if (val)
1279 _ptr[fullWords] |= endMask;
1280 else
1281 _ptr[fullWords] &= ~endMask;
1286 @system pure nothrow unittest
1288 import std.algorithm.comparison : equal;
1290 auto b = BitArray([1, 0, 1, 0, 1, 1]);
1292 b[] = true;
1293 // all bits are set
1294 assert(b.bitsSet.equal([0, 1, 2, 3, 4, 5]));
1296 b[] = false;
1297 // none of the bits are set
1298 assert(b.bitsSet.empty);
1302 Sets the bits of a slice of `BitArray` starting
1303 at index `start` and ends at index ($D end - 1)
1304 with the values specified by `val`.
1306 void opSliceAssign(bool val, size_t start, size_t end) @nogc pure nothrow
1309 assert(start <= end, "start must be less or equal to end");
1310 assert(end <= length, "end must be less or equal to the length");
1314 size_t startBlock = start / bitsPerSizeT;
1315 size_t endBlock = end / bitsPerSizeT;
1316 size_t startOffset = start % bitsPerSizeT;
1317 size_t endOffset = end % bitsPerSizeT;
1319 if (startBlock == endBlock)
1321 size_t startBlockMask = ~((size_t(1) << startOffset) - 1);
1322 size_t endBlockMask = (size_t(1) << endOffset) - 1;
1323 size_t joinMask = startBlockMask & endBlockMask;
1324 if (val)
1325 _ptr[startBlock] |= joinMask;
1326 else
1327 _ptr[startBlock] &= ~joinMask;
1328 return;
1331 if (startOffset != 0)
1333 size_t startBlockMask = ~((size_t(1) << startOffset) - 1);
1334 if (val)
1335 _ptr[startBlock] |= startBlockMask;
1336 else
1337 _ptr[startBlock] &= ~startBlockMask;
1338 ++startBlock;
1340 if (endOffset != 0)
1342 size_t endBlockMask = (size_t(1) << endOffset) - 1;
1343 if (val)
1344 _ptr[endBlock] |= endBlockMask;
1345 else
1346 _ptr[endBlock] &= ~endBlockMask;
1348 _ptr[startBlock .. endBlock] = size_t(0) - size_t(val);
1352 @system pure nothrow unittest
1354 import std.algorithm.comparison : equal;
1355 import std.range : iota;
1356 import std.stdio;
1358 auto b = BitArray([1, 0, 0, 0, 1, 1, 0]);
1359 b[1 .. 3] = true;
1360 assert(b.bitsSet.equal([0, 1, 2, 4, 5]));
1362 bool[72] bitArray;
1363 auto b1 = BitArray(bitArray);
1364 b1[63 .. 67] = true;
1365 assert(b1.bitsSet.equal([63, 64, 65, 66]));
1366 b1[63 .. 67] = false;
1367 assert(b1.bitsSet.empty);
1368 b1[0 .. 64] = true;
1369 assert(b1.bitsSet.equal(iota(0, 64)));
1370 b1[0 .. 64] = false;
1371 assert(b1.bitsSet.empty);
1373 bool[256] bitArray2;
1374 auto b2 = BitArray(bitArray2);
1375 b2[3 .. 245] = true;
1376 assert(b2.bitsSet.equal(iota(3, 245)));
1377 b2[3 .. 245] = false;
1378 assert(b2.bitsSet.empty);
1382 Flips all the bits in the `BitArray`
1384 void flip() @nogc pure nothrow
1386 foreach (i; 0 .. fullWords)
1387 _ptr[i] = ~_ptr[i];
1389 if (endBits)
1390 _ptr[fullWords] = (~_ptr[fullWords]) & endMask;
1394 @system pure nothrow unittest
1396 import std.algorithm.comparison : equal;
1397 import std.range : iota;
1399 // positions 0, 2, 4 are set
1400 auto b = BitArray([1, 0, 1, 0, 1, 0]);
1401 b.flip();
1402 // after flipping, positions 1, 3, 5 are set
1403 assert(b.bitsSet.equal([1, 3, 5]));
1405 bool[270] bits;
1406 auto b1 = BitArray(bits);
1407 b1.flip();
1408 assert(b1.bitsSet.equal(iota(0, 270)));
1412 Flips a single bit, specified by `pos`
1414 void flip(size_t pos) @nogc pure nothrow
1416 bt(_ptr, pos) ? btr(_ptr, pos) : bts(_ptr, pos);
1420 @system pure nothrow unittest
1422 auto ax = BitArray([1, 0, 0, 1]);
1423 ax.flip(0);
1424 assert(ax[0] == 0);
1426 bool[200] y;
1427 y[90 .. 130] = true;
1428 auto ay = BitArray(y);
1429 ay.flip(100);
1430 assert(ay[100] == 0);
1433 /**********************************************
1434 * Counts all the set bits in the `BitArray`
1436 size_t count() const scope @safe @nogc pure nothrow
1438 if (_ptr)
1440 size_t bitCount;
1441 foreach (i; 0 .. fullWords)
1442 bitCount += (() @trusted => countBitsSet(_ptr[i]))();
1443 if (endBits)
1444 bitCount += (() @trusted => countBitsSet(_ptr[fullWords] & endMask))();
1445 return bitCount;
1447 else
1449 return 0;
1454 @system pure nothrow unittest
1456 auto a = BitArray([0, 1, 1, 0, 0, 1, 1]);
1457 assert(a.count == 4);
1459 BitArray b;
1460 assert(b.count == 0);
1462 bool[200] boolArray;
1463 boolArray[45 .. 130] = true;
1464 auto c = BitArray(boolArray);
1465 assert(c.count == 85);
1468 /**********************************************
1469 * Duplicates the `BitArray` and its contents.
1471 @property BitArray dup() const pure nothrow
1473 BitArray ba;
1475 auto b = _ptr[0 .. dim].dup;
1476 ba._len = _len;
1477 ba._ptr = b.ptr;
1478 return ba;
1482 @system unittest
1484 BitArray a;
1485 BitArray b;
1487 a.length = 3;
1488 a[0] = 1; a[1] = 0; a[2] = 1;
1489 b = a.dup;
1490 assert(b.length == 3);
1491 foreach (i; 0 .. 3)
1492 assert(b[i] == (((i ^ 1) & 1) ? true : false));
1495 /**********************************************
1496 * Support for `foreach` loops for `BitArray`.
1498 int opApply(scope int delegate(ref bool) dg)
1500 int result;
1502 foreach (i; 0 .. _len)
1504 bool b = opIndex(i);
1505 result = dg(b);
1506 this[i] = b;
1507 if (result)
1508 break;
1510 return result;
1513 /** ditto */
1514 int opApply(scope int delegate(bool) dg) const
1516 int result;
1518 foreach (i; 0 .. _len)
1520 immutable b = opIndex(i);
1521 result = dg(b);
1522 if (result)
1523 break;
1525 return result;
1528 /** ditto */
1529 int opApply(scope int delegate(size_t, ref bool) dg)
1531 int result;
1533 foreach (i; 0 .. _len)
1535 bool b = opIndex(i);
1536 result = dg(i, b);
1537 this[i] = b;
1538 if (result)
1539 break;
1541 return result;
1544 /** ditto */
1545 int opApply(scope int delegate(size_t, bool) dg) const
1547 int result;
1549 foreach (i; 0 .. _len)
1551 immutable b = opIndex(i);
1552 result = dg(i, b);
1553 if (result)
1554 break;
1556 return result;
1560 @system unittest
1562 bool[] ba = [1,0,1];
1564 auto a = BitArray(ba);
1566 int i;
1567 foreach (b;a)
1569 switch (i)
1571 case 0: assert(b == true); break;
1572 case 1: assert(b == false); break;
1573 case 2: assert(b == true); break;
1574 default: assert(0);
1576 i++;
1579 foreach (j,b;a)
1581 switch (j)
1583 case 0: assert(b == true); break;
1584 case 1: assert(b == false); break;
1585 case 2: assert(b == true); break;
1586 default: assert(0);
1592 /**********************************************
1593 * Reverses the bits of the `BitArray`.
1595 @property BitArray reverse() @nogc pure nothrow return
1596 out (result)
1598 assert(result == this, "the result must be equal to this");
1602 if (_len >= 2)
1604 bool t;
1605 size_t lo, hi;
1607 lo = 0;
1608 hi = _len - 1;
1609 for (; lo < hi; lo++, hi--)
1611 t = this[lo];
1612 this[lo] = this[hi];
1613 this[hi] = t;
1616 return this;
1620 @system unittest
1622 BitArray b;
1623 bool[5] data = [1,0,1,1,0];
1625 b = BitArray(data);
1626 b.reverse;
1627 foreach (i; 0 .. data.length)
1628 assert(b[i] == data[4 - i]);
1632 /**********************************************
1633 * Sorts the `BitArray`'s elements.
1635 @property BitArray sort() @nogc pure nothrow return
1636 out (result)
1638 assert(result == this, "the result must be equal to this");
1642 if (_len >= 2)
1644 size_t lo, hi;
1646 lo = 0;
1647 hi = _len - 1;
1648 while (1)
1650 while (1)
1652 if (lo >= hi)
1653 goto Ldone;
1654 if (this[lo] == true)
1655 break;
1656 lo++;
1659 while (1)
1661 if (lo >= hi)
1662 goto Ldone;
1663 if (this[hi] == false)
1664 break;
1665 hi--;
1668 this[lo] = false;
1669 this[hi] = true;
1671 lo++;
1672 hi--;
1675 Ldone:
1676 return this;
1680 @system unittest
1682 size_t x = 0b1100011000;
1683 auto ba = BitArray(10, &x);
1684 ba.sort;
1685 foreach (i; 0 .. 6)
1686 assert(ba[i] == false);
1687 foreach (i; 6 .. 10)
1688 assert(ba[i] == true);
1692 /***************************************
1693 * Support for operators == and != for `BitArray`.
1695 bool opEquals(const ref BitArray a2) const @nogc pure nothrow
1697 if (this.length != a2.length)
1698 return false;
1699 auto p1 = this._ptr;
1700 auto p2 = a2._ptr;
1702 if (p1[0 .. fullWords] != p2[0 .. fullWords])
1703 return false;
1705 if (!endBits)
1706 return true;
1708 auto i = fullWords;
1709 return (p1[i] & endMask) == (p2[i] & endMask);
1713 @system unittest
1715 bool[] ba = [1,0,1,0,1];
1716 bool[] bb = [1,0,1];
1717 bool[] bc = [1,0,1,0,1,0,1];
1718 bool[] bd = [1,0,1,1,1];
1719 bool[] be = [1,0,1,0,1];
1720 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];
1721 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];
1723 auto a = BitArray(ba);
1724 auto b = BitArray(bb);
1725 auto c = BitArray(bc);
1726 auto d = BitArray(bd);
1727 auto e = BitArray(be);
1728 auto f = BitArray(bf);
1729 auto g = BitArray(bg);
1731 assert(a != b);
1732 assert(a != c);
1733 assert(a != d);
1734 assert(a == e);
1735 assert(f != g);
1738 /***************************************
1739 * Supports comparison operators for `BitArray`.
1741 int opCmp(BitArray a2) const @nogc pure nothrow
1743 const lesser = this.length < a2.length ? &this : &a2;
1744 immutable fullWords = lesser.fullWords;
1745 immutable endBits = lesser.endBits;
1746 auto p1 = this._ptr;
1747 auto p2 = a2._ptr;
1749 foreach (i; 0 .. fullWords)
1751 if (p1[i] != p2[i])
1753 return p1[i] & (size_t(1) << bsf(p1[i] ^ p2[i])) ? 1 : -1;
1757 if (endBits)
1759 immutable i = fullWords;
1760 immutable diff = p1[i] ^ p2[i];
1761 if (diff)
1763 immutable index = bsf(diff);
1764 if (index < endBits)
1766 return p1[i] & (size_t(1) << index) ? 1 : -1;
1771 // Standard:
1772 // A bool value can be implicitly converted to any integral type,
1773 // with false becoming 0 and true becoming 1
1774 return (this.length > a2.length) - (this.length < a2.length);
1778 @system unittest
1780 bool[] ba = [1,0,1,0,1];
1781 bool[] bb = [1,0,1];
1782 bool[] bc = [1,0,1,0,1,0,1];
1783 bool[] bd = [1,0,1,1,1];
1784 bool[] be = [1,0,1,0,1];
1785 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];
1786 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];
1788 auto a = BitArray(ba);
1789 auto b = BitArray(bb);
1790 auto c = BitArray(bc);
1791 auto d = BitArray(bd);
1792 auto e = BitArray(be);
1793 auto f = BitArray(bf);
1794 auto g = BitArray(bg);
1796 assert(a > b);
1797 assert(a >= b);
1798 assert(a < c);
1799 assert(a <= c);
1800 assert(a < d);
1801 assert(a <= d);
1802 assert(a == e);
1803 assert(a <= e);
1804 assert(a >= e);
1805 assert(f < g);
1806 assert(g <= g);
1809 @system unittest
1811 bool[] v;
1812 foreach (i; 1 .. 256)
1814 v.length = i;
1815 v[] = false;
1816 auto x = BitArray(v);
1817 v[i-1] = true;
1818 auto y = BitArray(v);
1819 assert(x < y);
1820 assert(x <= y);
1823 BitArray a1, a2;
1825 for (size_t len = 4; len <= 256; len <<= 1)
1827 a1.length = a2.length = len;
1828 a1[len-2] = a2[len-1] = true;
1829 assert(a1 > a2);
1830 a1[len-2] = a2[len-1] = false;
1833 foreach (j; 1 .. a1.length)
1835 a1[j-1] = a2[j] = true;
1836 assert(a1 > a2);
1837 a1[j-1] = a2[j] = false;
1841 /***************************************
1842 * Support for hashing for `BitArray`.
1844 size_t toHash() const @nogc pure nothrow
1846 size_t hash = 3557;
1847 auto fullBytes = _len / 8;
1848 foreach (i; 0 .. fullBytes)
1850 hash *= 3559;
1851 hash += (cast(byte*) this._ptr)[i];
1853 foreach (i; 8*fullBytes .. _len)
1855 hash *= 3571;
1856 hash += this[i];
1858 return hash;
1861 /***************************************
1862 * Convert to `void[]`.
1864 inout(void)[] opCast(T : const void[])() inout @nogc pure nothrow
1866 return cast(inout void[]) _ptr[0 .. dim];
1869 /***************************************
1870 * Convert to `size_t[]`.
1872 inout(size_t)[] opCast(T : const size_t[])() inout @nogc pure nothrow
1874 return _ptr[0 .. dim];
1878 @system unittest
1880 import std.array : array;
1881 import std.range : repeat, take;
1883 // bit array with 300 elements
1884 auto a = BitArray(true.repeat.take(300).array);
1885 size_t[] v = cast(size_t[]) a;
1886 const blockSize = size_t.sizeof * 8;
1887 assert(v.length == (a.length + blockSize - 1) / blockSize);
1890 // https://issues.dlang.org/show_bug.cgi?id=20606
1891 @system unittest
1893 import std.meta : AliasSeq;
1895 static foreach (alias T; AliasSeq!(void, size_t))
1897 BitArray m;
1898 T[] ma = cast(T[]) m;
1900 const BitArray c;
1901 const(T)[] ca = cast(const T[]) c;
1903 immutable BitArray i;
1904 immutable(T)[] ia = cast(immutable T[]) i;
1906 // Cross-mutability
1907 ca = cast(const T[]) m;
1908 ca = cast(const T[]) i;
1910 // Invalid cast don't compile
1911 static assert(!is(typeof(cast(T[]) c)));
1912 static assert(!is(typeof(cast(T[]) i)));
1913 static assert(!is(typeof(cast(immutable T[]) m)));
1914 static assert(!is(typeof(cast(immutable T[]) c)));
1918 /***************************************
1919 * Support for unary operator ~ for `BitArray`.
1921 BitArray opUnary(string op)() const pure nothrow
1922 if (op == "~")
1924 auto dim = this.dim;
1926 BitArray result;
1927 result.length = _len;
1929 result._ptr[0 .. dim] = ~this._ptr[0 .. dim];
1931 // Avoid putting garbage in extra bits
1932 // Remove once we zero on length extension
1933 if (endBits)
1934 result._ptr[dim - 1] &= endMask;
1936 return result;
1940 @system unittest
1942 bool[] ba = [1,0,1,0,1];
1944 auto a = BitArray(ba);
1945 BitArray b = ~a;
1947 assert(b[0] == 0);
1948 assert(b[1] == 1);
1949 assert(b[2] == 0);
1950 assert(b[3] == 1);
1951 assert(b[4] == 0);
1955 /***************************************
1956 * Support for binary bitwise operators for `BitArray`.
1958 BitArray opBinary(string op)(const BitArray e2) const pure nothrow
1959 if (op == "-" || op == "&" || op == "|" || op == "^")
1962 assert(e2.length == _len, "e2 must have the same length as this");
1966 auto dim = this.dim;
1968 BitArray result;
1969 result.length = _len;
1971 static if (op == "-")
1972 result._ptr[0 .. dim] = this._ptr[0 .. dim] & ~e2._ptr[0 .. dim];
1973 else
1974 mixin("result._ptr[0 .. dim] = this._ptr[0 .. dim]"~op~" e2._ptr[0 .. dim];");
1976 // Avoid putting garbage in extra bits
1977 // Remove once we zero on length extension
1978 if (endBits)
1979 result._ptr[dim - 1] &= endMask;
1981 return result;
1985 @system unittest
1987 static bool[] ba = [1,0,1,0,1];
1988 static bool[] bb = [1,0,1,1,0];
1990 auto a = BitArray(ba);
1991 auto b = BitArray(bb);
1993 BitArray c = a & b;
1995 assert(c[0] == 1);
1996 assert(c[1] == 0);
1997 assert(c[2] == 1);
1998 assert(c[3] == 0);
1999 assert(c[4] == 0);
2003 @system unittest
2005 bool[] ba = [1,0,1,0,1];
2006 bool[] bb = [1,0,1,1,0];
2008 auto a = BitArray(ba);
2009 auto b = BitArray(bb);
2011 BitArray c = a | b;
2013 assert(c[0] == 1);
2014 assert(c[1] == 0);
2015 assert(c[2] == 1);
2016 assert(c[3] == 1);
2017 assert(c[4] == 1);
2021 @system unittest
2023 bool[] ba = [1,0,1,0,1];
2024 bool[] bb = [1,0,1,1,0];
2026 auto a = BitArray(ba);
2027 auto b = BitArray(bb);
2029 BitArray c = a ^ b;
2031 assert(c[0] == 0);
2032 assert(c[1] == 0);
2033 assert(c[2] == 0);
2034 assert(c[3] == 1);
2035 assert(c[4] == 1);
2039 @system unittest
2041 bool[] ba = [1,0,1,0,1];
2042 bool[] bb = [1,0,1,1,0];
2044 auto a = BitArray(ba);
2045 auto b = BitArray(bb);
2047 BitArray c = a - b;
2049 assert(c[0] == 0);
2050 assert(c[1] == 0);
2051 assert(c[2] == 0);
2052 assert(c[3] == 0);
2053 assert(c[4] == 1);
2057 /***************************************
2058 * Support for operator op= for `BitArray`.
2060 BitArray opOpAssign(string op)(const BitArray e2) @nogc pure nothrow return scope
2061 if (op == "-" || op == "&" || op == "|" || op == "^")
2064 assert(e2.length == _len, "e2 must have the same length as this");
2068 foreach (i; 0 .. fullWords)
2070 static if (op == "-")
2071 _ptr[i] &= ~e2._ptr[i];
2072 else
2073 mixin("_ptr[i] "~op~"= e2._ptr[i];");
2075 if (!endBits)
2076 return this;
2078 size_t i = fullWords;
2079 size_t endWord = _ptr[i];
2080 static if (op == "-")
2081 endWord &= ~e2._ptr[i];
2082 else
2083 mixin("endWord "~op~"= e2._ptr[i];");
2084 _ptr[i] = (_ptr[i] & ~endMask) | (endWord & endMask);
2086 return this;
2090 @system unittest
2092 bool[] ba = [1,0,1,0,1,1,0,1,0,1];
2093 bool[] bb = [1,0,1,1,0];
2094 auto a = BitArray(ba);
2095 auto b = BitArray(bb);
2096 BitArray c = a;
2097 c.length = 5;
2098 c &= b;
2099 assert(a[5] == 1);
2100 assert(a[6] == 0);
2101 assert(a[7] == 1);
2102 assert(a[8] == 0);
2103 assert(a[9] == 1);
2107 @system unittest
2109 bool[] ba = [1,0,1,0,1];
2110 bool[] bb = [1,0,1,1,0];
2112 auto a = BitArray(ba);
2113 auto b = BitArray(bb);
2115 a &= b;
2116 assert(a[0] == 1);
2117 assert(a[1] == 0);
2118 assert(a[2] == 1);
2119 assert(a[3] == 0);
2120 assert(a[4] == 0);
2124 @system unittest
2126 bool[] ba = [1,0,1,0,1];
2127 bool[] bb = [1,0,1,1,0];
2129 auto a = BitArray(ba);
2130 auto b = BitArray(bb);
2132 a |= b;
2133 assert(a[0] == 1);
2134 assert(a[1] == 0);
2135 assert(a[2] == 1);
2136 assert(a[3] == 1);
2137 assert(a[4] == 1);
2141 @system unittest
2143 bool[] ba = [1,0,1,0,1];
2144 bool[] bb = [1,0,1,1,0];
2146 auto a = BitArray(ba);
2147 auto b = BitArray(bb);
2149 a ^= b;
2150 assert(a[0] == 0);
2151 assert(a[1] == 0);
2152 assert(a[2] == 0);
2153 assert(a[3] == 1);
2154 assert(a[4] == 1);
2158 @system unittest
2160 bool[] ba = [1,0,1,0,1];
2161 bool[] bb = [1,0,1,1,0];
2163 auto a = BitArray(ba);
2164 auto b = BitArray(bb);
2166 a -= b;
2167 assert(a[0] == 0);
2168 assert(a[1] == 0);
2169 assert(a[2] == 0);
2170 assert(a[3] == 0);
2171 assert(a[4] == 1);
2174 /***************************************
2175 * Support for operator ~= for `BitArray`.
2176 * $(RED Warning: This will overwrite a bit in the final word
2177 * of the current underlying data regardless of whether it is
2178 * shared between BitArray objects. i.e. D dynamic array
2179 * concatenation semantics are not followed)
2181 BitArray opOpAssign(string op)(bool b) pure nothrow return scope
2182 if (op == "~")
2184 length = _len + 1;
2185 this[_len - 1] = b;
2186 return this;
2190 @system unittest
2192 bool[] ba = [1,0,1,0,1];
2194 auto a = BitArray(ba);
2195 BitArray b;
2197 b = (a ~= true);
2198 assert(a[0] == 1);
2199 assert(a[1] == 0);
2200 assert(a[2] == 1);
2201 assert(a[3] == 0);
2202 assert(a[4] == 1);
2203 assert(a[5] == 1);
2205 assert(b == a);
2208 /***************************************
2209 * ditto
2211 BitArray opOpAssign(string op)(BitArray b) pure nothrow return scope
2212 if (op == "~")
2214 auto istart = _len;
2215 length = _len + b.length;
2216 for (auto i = istart; i < _len; i++)
2217 this[i] = b[i - istart];
2218 return this;
2222 @system unittest
2224 bool[] ba = [1,0];
2225 bool[] bb = [0,1,0];
2227 auto a = BitArray(ba);
2228 auto b = BitArray(bb);
2229 BitArray c;
2231 c = (a ~= b);
2232 assert(a.length == 5);
2233 assert(a[0] == 1);
2234 assert(a[1] == 0);
2235 assert(a[2] == 0);
2236 assert(a[3] == 1);
2237 assert(a[4] == 0);
2239 assert(c == a);
2242 /***************************************
2243 * Support for binary operator ~ for `BitArray`.
2245 BitArray opBinary(string op)(bool b) const pure nothrow
2246 if (op == "~")
2248 BitArray r;
2250 r = this.dup;
2251 r.length = _len + 1;
2252 r[_len] = b;
2253 return r;
2256 /** ditto */
2257 BitArray opBinaryRight(string op)(bool b) const pure nothrow
2258 if (op == "~")
2260 BitArray r;
2262 r.length = _len + 1;
2263 r[0] = b;
2264 foreach (i; 0 .. _len)
2265 r[1 + i] = this[i];
2266 return r;
2269 /** ditto */
2270 BitArray opBinary(string op)(BitArray b) const pure nothrow
2271 if (op == "~")
2273 BitArray r;
2275 r = this.dup;
2276 r ~= b;
2277 return r;
2281 @system unittest
2283 bool[] ba = [1,0];
2284 bool[] bb = [0,1,0];
2286 auto a = BitArray(ba);
2287 auto b = BitArray(bb);
2288 BitArray c;
2290 c = (a ~ b);
2291 assert(c.length == 5);
2292 assert(c[0] == 1);
2293 assert(c[1] == 0);
2294 assert(c[2] == 0);
2295 assert(c[3] == 1);
2296 assert(c[4] == 0);
2298 c = (a ~ true);
2299 assert(c.length == 3);
2300 assert(c[0] == 1);
2301 assert(c[1] == 0);
2302 assert(c[2] == 1);
2304 c = (false ~ a);
2305 assert(c.length == 3);
2306 assert(c[0] == 0);
2307 assert(c[1] == 1);
2308 assert(c[2] == 0);
2311 // Rolls double word (upper, lower) to the right by n bits and returns the
2312 // lower word of the result.
2313 private static size_t rollRight()(size_t upper, size_t lower, size_t nbits)
2314 pure @safe nothrow @nogc
2317 assert(nbits < bitsPerSizeT, "nbits must be less than bitsPerSizeT");
2321 if (nbits == 0)
2322 return lower;
2323 return (upper << (bitsPerSizeT - nbits)) | (lower >> nbits);
2326 @safe unittest
2328 static if (size_t.sizeof == 8)
2330 size_t x = 0x12345678_90ABCDEF;
2331 size_t y = 0xFEDBCA09_87654321;
2333 assert(rollRight(x, y, 32) == 0x90ABCDEF_FEDBCA09);
2334 assert(rollRight(y, x, 4) == 0x11234567_890ABCDE);
2336 else static if (size_t.sizeof == 4)
2338 size_t x = 0x12345678;
2339 size_t y = 0x90ABCDEF;
2341 assert(rollRight(x, y, 16) == 0x567890AB);
2342 assert(rollRight(y, x, 4) == 0xF1234567);
2344 else
2345 static assert(0, "Unsupported size_t width");
2348 // Rolls double word (upper, lower) to the left by n bits and returns the
2349 // upper word of the result.
2350 private static size_t rollLeft()(size_t upper, size_t lower, size_t nbits)
2351 pure @safe nothrow @nogc
2354 assert(nbits < bitsPerSizeT, "nbits must be less than bitsPerSizeT");
2358 if (nbits == 0)
2359 return upper;
2360 return (upper << nbits) | (lower >> (bitsPerSizeT - nbits));
2363 @safe unittest
2365 static if (size_t.sizeof == 8)
2367 size_t x = 0x12345678_90ABCDEF;
2368 size_t y = 0xFEDBCA09_87654321;
2370 assert(rollLeft(x, y, 32) == 0x90ABCDEF_FEDBCA09);
2371 assert(rollLeft(y, x, 4) == 0xEDBCA098_76543211);
2373 else static if (size_t.sizeof == 4)
2375 size_t x = 0x12345678;
2376 size_t y = 0x90ABCDEF;
2378 assert(rollLeft(x, y, 16) == 0x567890AB);
2379 assert(rollLeft(y, x, 4) == 0x0ABCDEF1);
2384 * Operator `<<=` support.
2386 * Shifts all the bits in the array to the left by the given number of
2387 * bits. The leftmost bits are dropped, and 0's are appended to the end
2388 * to fill up the vacant bits.
2390 * $(RED Warning: unused bits in the final word up to the next word
2391 * boundary may be overwritten by this operation. It does not attempt to
2392 * preserve bits past the end of the array.)
2394 void opOpAssign(string op)(size_t nbits) @nogc pure nothrow
2395 if (op == "<<")
2397 size_t wordsToShift = nbits / bitsPerSizeT;
2398 size_t bitsToShift = nbits % bitsPerSizeT;
2400 if (wordsToShift < dim)
2402 foreach_reverse (i; 1 .. dim - wordsToShift)
2404 _ptr[i + wordsToShift] = rollLeft(_ptr[i], _ptr[i-1],
2405 bitsToShift);
2407 _ptr[wordsToShift] = rollLeft(_ptr[0], 0, bitsToShift);
2410 import std.algorithm.comparison : min;
2411 foreach (i; 0 .. min(wordsToShift, dim))
2413 _ptr[i] = 0;
2418 * Operator `>>=` support.
2420 * Shifts all the bits in the array to the right by the given number of
2421 * bits. The rightmost bits are dropped, and 0's are inserted at the back
2422 * to fill up the vacant bits.
2424 * $(RED Warning: unused bits in the final word up to the next word
2425 * boundary may be overwritten by this operation. It does not attempt to
2426 * preserve bits past the end of the array.)
2428 void opOpAssign(string op)(size_t nbits) @nogc pure nothrow
2429 if (op == ">>")
2431 size_t wordsToShift = nbits / bitsPerSizeT;
2432 size_t bitsToShift = nbits % bitsPerSizeT;
2434 if (wordsToShift + 1 < dim)
2436 foreach (i; 0 .. dim - wordsToShift - 1)
2438 _ptr[i] = rollRight(_ptr[i + wordsToShift + 1],
2439 _ptr[i + wordsToShift], bitsToShift);
2443 // The last word needs some care, as it must shift in 0's from past the
2444 // end of the array.
2445 if (wordsToShift < dim)
2447 if (bitsToShift == 0)
2448 _ptr[dim - wordsToShift - 1] = _ptr[dim - 1];
2449 else
2451 // Special case: if endBits == 0, then also endMask == 0.
2452 size_t lastWord = (endBits ? (_ptr[fullWords] & endMask) : _ptr[fullWords - 1]);
2453 _ptr[dim - wordsToShift - 1] = rollRight(0, lastWord, bitsToShift);
2457 import std.algorithm.comparison : min;
2458 foreach (i; 0 .. min(wordsToShift, dim))
2460 _ptr[dim - i - 1] = 0;
2464 // https://issues.dlang.org/show_bug.cgi?id=17467
2465 @system unittest
2467 import std.algorithm.comparison : equal;
2468 import std.range : iota;
2470 bool[] buf = new bool[64*3];
2471 buf[0 .. 64] = true;
2472 BitArray b = BitArray(buf);
2473 assert(equal(b.bitsSet, iota(0, 64)));
2474 b <<= 64;
2475 assert(equal(b.bitsSet, iota(64, 128)));
2477 buf = new bool[64*3];
2478 buf[64*2 .. 64*3] = true;
2479 b = BitArray(buf);
2480 assert(equal(b.bitsSet, iota(64*2, 64*3)));
2481 b >>= 64;
2482 assert(equal(b.bitsSet, iota(64, 128)));
2485 // https://issues.dlang.org/show_bug.cgi?id=18134
2486 // shifting right when length is a multiple of 8 * size_t.sizeof.
2487 @system unittest
2489 import std.algorithm.comparison : equal;
2490 import std.array : array;
2491 import std.range : repeat, iota;
2493 immutable r = size_t.sizeof * 8;
2495 BitArray a = true.repeat(r / 2).array;
2496 a >>= 0;
2497 assert(a.bitsSet.equal(iota(0, r / 2)));
2498 a >>= 1;
2499 assert(a.bitsSet.equal(iota(0, r / 2 - 1)));
2501 BitArray b = true.repeat(r).array;
2502 b >>= 0;
2503 assert(b.bitsSet.equal(iota(0, r)));
2504 b >>= 1;
2505 assert(b.bitsSet.equal(iota(0, r - 1)));
2507 BitArray c = true.repeat(2 * r).array;
2508 c >>= 0;
2509 assert(c.bitsSet.equal(iota(0, 2 * r)));
2510 c >>= 10;
2511 assert(c.bitsSet.equal(iota(0, 2 * r - 10)));
2515 @system unittest
2517 import std.format : format;
2519 auto b = BitArray([1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1]);
2521 b <<= 1;
2522 assert(format("%b", b) == "01100_10101101");
2524 b >>= 1;
2525 assert(format("%b", b) == "11001_01011010");
2527 b <<= 4;
2528 assert(format("%b", b) == "00001_10010101");
2530 b >>= 5;
2531 assert(format("%b", b) == "10010_10100000");
2533 b <<= 13;
2534 assert(format("%b", b) == "00000_00000000");
2536 b = BitArray([1, 0, 1, 1, 0, 1, 1, 1]);
2537 b >>= 8;
2538 assert(format("%b", b) == "00000000");
2542 // Test multi-word case
2543 @system unittest
2545 import std.format : format;
2547 // This has to be long enough to occupy more than one size_t. On 64-bit
2548 // machines, this would be at least 64 bits.
2549 auto b = BitArray([
2550 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,
2551 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
2552 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0,
2553 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
2554 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1,
2556 b <<= 8;
2557 assert(format("%b", b) ==
2558 "00000000_10000000_"~
2559 "11000000_11100000_"~
2560 "11110000_11111000_"~
2561 "11111100_11111110_"~
2562 "11111111_10101010");
2564 // Test right shift of more than one size_t's worth of bits
2565 b <<= 68;
2566 assert(format("%b", b) ==
2567 "00000000_00000000_"~
2568 "00000000_00000000_"~
2569 "00000000_00000000_"~
2570 "00000000_00000000_"~
2571 "00000000_00001000");
2573 b = BitArray([
2574 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,
2575 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
2576 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0,
2577 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
2578 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1,
2580 b >>= 8;
2581 assert(format("%b", b) ==
2582 "11000000_11100000_"~
2583 "11110000_11111000_"~
2584 "11111100_11111110_"~
2585 "11111111_10101010_"~
2586 "01010101_00000000");
2588 // Test left shift of more than 1 size_t's worth of bits
2589 b >>= 68;
2590 assert(format("%b", b) ==
2591 "01010000_00000000_"~
2592 "00000000_00000000_"~
2593 "00000000_00000000_"~
2594 "00000000_00000000_"~
2595 "00000000_00000000");
2598 /***************************************
2599 * Return a string representation of this BitArray.
2601 * Two format specifiers are supported:
2602 * $(LI $(B %s) which prints the bits as an array, and)
2603 * $(LI $(B %b) which prints the bits as 8-bit byte packets)
2604 * separated with an underscore.
2606 * Params:
2607 * sink = A `char` accepting
2608 * $(REF_ALTTEXT output range, isOutputRange, std, range, primitives).
2609 * fmt = A $(REF FormatSpec, std,format) which controls how the data
2610 * is displayed.
2612 void toString(W)(ref W sink, scope const ref FormatSpec!char fmt) const
2613 if (isOutputRange!(W, char))
2615 const spec = fmt.spec;
2616 switch (spec)
2618 case 'b':
2619 return formatBitString(sink);
2620 case 's':
2621 return formatBitArray(sink);
2622 default:
2623 throw new Exception("Unknown format specifier: %" ~ spec);
2628 @system pure unittest
2630 import std.format : format;
2632 auto b = BitArray([0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1]);
2634 auto s1 = format("%s", b);
2635 assert(s1 == "[0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1]");
2637 auto s2 = format("%b", b);
2638 assert(s2 == "00001111_00001111");
2641 /***************************************
2642 * Return a lazy range of the indices of set bits.
2644 @property auto bitsSet() const nothrow
2646 import std.algorithm.iteration : filter, map, joiner;
2647 import std.range : iota, chain;
2649 return chain(
2650 iota(fullWords)
2651 .filter!(i => _ptr[i])()
2652 .map!(i => BitsSet!size_t(_ptr[i], i * bitsPerSizeT))()
2653 .joiner(),
2654 iota(fullWords * bitsPerSizeT, _len)
2655 .filter!(i => this[i])()
2660 @system unittest
2662 import std.algorithm.comparison : equal;
2664 auto b1 = BitArray([0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1]);
2665 assert(b1.bitsSet.equal([4, 5, 6, 7, 12, 13, 14, 15]));
2667 BitArray b2;
2668 b2.length = 1000;
2669 b2[333] = true;
2670 b2[666] = true;
2671 b2[999] = true;
2672 assert(b2.bitsSet.equal([333, 666, 999]));
2675 @system unittest
2677 import std.algorithm.comparison : equal;
2678 import std.range : iota;
2680 BitArray b;
2681 enum wordBits = size_t.sizeof * 8;
2682 b = BitArray([size_t.max], 0);
2683 assert(b.bitsSet.empty);
2684 b = BitArray([size_t.max], 1);
2685 assert(b.bitsSet.equal([0]));
2686 b = BitArray([size_t.max], wordBits);
2687 assert(b.bitsSet.equal(iota(wordBits)));
2688 b = BitArray([size_t.max, size_t.max], wordBits);
2689 assert(b.bitsSet.equal(iota(wordBits)));
2690 b = BitArray([size_t.max, size_t.max], wordBits + 1);
2691 assert(b.bitsSet.equal(iota(wordBits + 1)));
2692 b = BitArray([size_t.max, size_t.max], wordBits * 2);
2693 assert(b.bitsSet.equal(iota(wordBits * 2)));
2696 // https://issues.dlang.org/show_bug.cgi?id=20241
2697 @system unittest
2699 BitArray ba;
2700 ba.length = 2;
2701 ba[1] = 1;
2702 ba.length = 1;
2703 assert(ba.bitsSet.empty);
2706 private void formatBitString(Writer)(auto ref Writer sink) const
2708 if (!length)
2709 return;
2711 auto leftover = _len % 8;
2712 foreach (idx; 0 .. leftover)
2714 put(sink, cast(char)(this[idx] + '0'));
2717 if (leftover && _len > 8)
2718 put(sink, "_");
2720 size_t count;
2721 foreach (idx; leftover .. _len)
2723 put(sink, cast(char)(this[idx] + '0'));
2724 if (++count == 8 && idx != _len - 1)
2726 put(sink, "_");
2727 count = 0;
2732 private void formatBitArray(Writer)(auto ref Writer sink) const
2734 put(sink, "[");
2735 foreach (idx; 0 .. _len)
2737 put(sink, cast(char)(this[idx] + '0'));
2738 if (idx + 1 < _len)
2739 put(sink, ", ");
2741 put(sink, "]");
2744 // https://issues.dlang.org/show_bug.cgi?id=20639
2745 // Separate @nogc test because public tests use array literals
2746 // (and workarounds needlessly uglify those examples)
2747 @system @nogc unittest
2749 size_t[2] buffer;
2750 BitArray b = BitArray(buffer[], buffer.sizeof * 8);
2752 b[] = true;
2753 b[0 .. 1] = true;
2754 b.flip();
2755 b.flip(1);
2756 cast(void) b.count();
2760 /// Slicing & bitsSet
2761 @system unittest
2763 import std.algorithm.comparison : equal;
2764 import std.range : iota;
2766 bool[] buf = new bool[64 * 3];
2767 buf[0 .. 64] = true;
2768 BitArray b = BitArray(buf);
2769 assert(b.bitsSet.equal(iota(0, 64)));
2770 b <<= 64;
2771 assert(b.bitsSet.equal(iota(64, 128)));
2774 /// Concatenation and appending
2775 @system unittest
2777 import std.algorithm.comparison : equal;
2779 auto b = BitArray([1, 0]);
2780 b ~= true;
2781 assert(b[2] == 1);
2782 b ~= BitArray([0, 1]);
2783 auto c = BitArray([1, 0, 1, 0, 1]);
2784 assert(b == c);
2785 assert(b.bitsSet.equal([0, 2, 4]));
2788 /// Bit flipping
2789 @system unittest
2791 import std.algorithm.comparison : equal;
2793 auto b = BitArray([1, 1, 0, 1]);
2794 b &= BitArray([0, 1, 1, 0]);
2795 assert(b.bitsSet.equal([1]));
2796 b.flip;
2797 assert(b.bitsSet.equal([0, 2, 3]));
2800 /// String format of bitarrays
2801 @system unittest
2803 import std.format : format;
2804 auto b = BitArray([1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1]);
2805 assert(format("%b", b) == "1_00001111_00001111");
2809 @system unittest
2811 import std.format : format;
2813 BitArray b;
2815 b = BitArray([]);
2816 assert(format("%s", b) == "[]");
2817 assert(format("%b", b) is null);
2819 b = BitArray([1]);
2820 assert(format("%s", b) == "[1]");
2821 assert(format("%b", b) == "1");
2823 b = BitArray([0, 0, 0, 0]);
2824 assert(format("%b", b) == "0000");
2826 b = BitArray([0, 0, 0, 0, 1, 1, 1, 1]);
2827 assert(format("%s", b) == "[0, 0, 0, 0, 1, 1, 1, 1]");
2828 assert(format("%b", b) == "00001111");
2830 b = BitArray([0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1]);
2831 assert(format("%s", b) == "[0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1]");
2832 assert(format("%b", b) == "00001111_00001111");
2834 b = BitArray([1, 0, 0, 0, 0, 1, 1, 1, 1]);
2835 assert(format("%b", b) == "1_00001111");
2837 b = BitArray([1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1]);
2838 assert(format("%b", b) == "1_00001111_00001111");
2841 @system unittest
2843 BitArray a;
2844 a.length = 5;
2845 foreach (ref bool b; a)
2847 assert(b == 0);
2848 b = 1;
2850 foreach (bool b; a)
2851 assert(b == 1);
2855 Swaps the endianness of the given integral value or character.
2857 T swapEndian(T)(const T val) @safe pure nothrow @nogc
2858 if (isIntegral!T || isSomeChar!T || isBoolean!T)
2860 import core.bitop : bswap, byteswap;
2861 static if (val.sizeof == 1)
2862 return val;
2863 else static if (T.sizeof == 2)
2864 return cast(T) byteswap(cast(ushort) val);
2865 else static if (T.sizeof == 4)
2866 return cast(T) bswap(cast(uint) val);
2867 else static if (T.sizeof == 8)
2868 return cast(T) bswap(cast(ulong) val);
2869 else
2870 static assert(0, T.stringof ~ " unsupported by swapEndian.");
2874 @safe unittest
2876 assert(42.swapEndian == 704643072);
2877 assert(42.swapEndian.swapEndian == 42); // reflexive
2878 assert(1.swapEndian == 16777216);
2880 assert(true.swapEndian == true);
2881 assert(byte(10).swapEndian == 10);
2882 assert(char(10).swapEndian == 10);
2884 assert(ushort(10).swapEndian == 2560);
2885 assert(long(10).swapEndian == 720575940379279360);
2886 assert(ulong(10).swapEndian == 720575940379279360);
2889 @safe unittest
2891 import std.meta;
2892 import std.stdio;
2893 static foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, int, uint, long, ulong, char, wchar, dchar))
2895 scope(failure) writeln("Failed type: ", T.stringof);
2896 T val;
2897 const T cval;
2898 immutable T ival;
2900 assert(swapEndian(swapEndian(val)) == val);
2901 assert(swapEndian(swapEndian(cval)) == cval);
2902 assert(swapEndian(swapEndian(ival)) == ival);
2903 assert(swapEndian(swapEndian(T.min)) == T.min);
2904 assert(swapEndian(swapEndian(T.max)) == T.max);
2906 // Check CTFE compiles.
2907 static assert(swapEndian(swapEndian(T(1))) is T(1));
2909 foreach (i; 2 .. 10)
2911 immutable T maxI = cast(T)(T.max / i);
2912 immutable T minI = cast(T)(T.min / i);
2914 assert(swapEndian(swapEndian(maxI)) == maxI);
2916 static if (isSigned!T)
2917 assert(swapEndian(swapEndian(minI)) == minI);
2920 static if (isSigned!T)
2921 assert(swapEndian(swapEndian(cast(T) 0)) == 0);
2923 // used to trigger https://issues.dlang.org/show_bug.cgi?id=6354
2924 static if (T.sizeof > 1 && isUnsigned!T)
2926 T left = 0xffU;
2927 left <<= (T.sizeof - 1) * 8;
2928 T right = 0xffU;
2930 for (size_t i = 1; i < T.sizeof; ++i)
2932 assert(swapEndian(left) == right);
2933 assert(swapEndian(right) == left);
2934 left >>= 8;
2935 right <<= 8;
2942 private union EndianSwapper(T)
2943 if (canSwapEndianness!T)
2945 T value;
2946 ubyte[T.sizeof] array;
2948 static if (is(immutable FloatingPointTypeOf!(T) == immutable float))
2949 uint intValue;
2950 else static if (is(immutable FloatingPointTypeOf!(T) == immutable double))
2951 ulong intValue;
2955 // Can't use EndianSwapper union during CTFE.
2956 private auto ctfeRead(T)(const ubyte[T.sizeof] array)
2957 if (__traits(isIntegral, T))
2959 Unqual!T result;
2960 version (LittleEndian)
2961 foreach_reverse (b; array)
2962 result = cast(Unqual!T) ((result << 8) | b);
2963 else
2964 foreach (b; array)
2965 result = cast(Unqual!T) ((result << 8) | b);
2966 return cast(T) result;
2969 // Can't use EndianSwapper union during CTFE.
2970 private auto ctfeBytes(T)(const T value)
2971 if (__traits(isIntegral, T))
2973 ubyte[T.sizeof] result;
2974 Unqual!T tmp = value;
2975 version (LittleEndian)
2977 foreach (i; 0 .. T.sizeof)
2979 result[i] = cast(ubyte) tmp;
2980 tmp = cast(Unqual!T) (tmp >>> 8);
2983 else
2985 foreach_reverse (i; 0 .. T.sizeof)
2987 result[i] = cast(ubyte) tmp;
2988 tmp = cast(Unqual!T) (tmp >>> 8);
2991 return result;
2995 Converts the given value from the native endianness to big endian and
2996 returns it as a `ubyte[n]` where `n` is the size of the given type.
2998 Returning a `ubyte[n]` helps prevent accidentally using a swapped value
2999 as a regular one (and in the case of floating point values, it's necessary,
3000 because the FPU will mess up any swapped floating point values. So, you
3001 can't actually have swapped floating point values as floating point values).
3003 `real` is not supported, because its size is implementation-dependent
3004 and therefore could vary from machine to machine (which could make it
3005 unusable if you tried to transfer it to another machine).
3007 auto nativeToBigEndian(T)(const T val) @safe pure nothrow @nogc
3008 if (canSwapEndianness!T)
3010 version (LittleEndian)
3011 return nativeToEndianImpl!true(val);
3012 else
3013 return nativeToEndianImpl!false(val);
3017 @safe unittest
3019 int i = 12345;
3020 ubyte[4] swappedI = nativeToBigEndian(i);
3021 assert(i == bigEndianToNative!int(swappedI));
3023 float f = 123.45f;
3024 ubyte[4] swappedF = nativeToBigEndian(f);
3025 assert(f == bigEndianToNative!float(swappedF));
3027 const float cf = 123.45f;
3028 ubyte[4] swappedCF = nativeToBigEndian(cf);
3029 assert(cf == bigEndianToNative!float(swappedCF));
3031 double d = 123.45;
3032 ubyte[8] swappedD = nativeToBigEndian(d);
3033 assert(d == bigEndianToNative!double(swappedD));
3035 const double cd = 123.45;
3036 ubyte[8] swappedCD = nativeToBigEndian(cd);
3037 assert(cd == bigEndianToNative!double(swappedCD));
3040 private auto nativeToEndianImpl(bool swap, T)(const T val) @safe pure nothrow @nogc
3041 if (__traits(isIntegral, T))
3043 if (!__ctfe)
3045 static if (swap)
3046 return EndianSwapper!T(swapEndian(val)).array;
3047 else
3048 return EndianSwapper!T(val).array;
3050 else
3052 // Can't use EndianSwapper in CTFE.
3053 static if (swap)
3054 return ctfeBytes(swapEndian(val));
3055 else
3056 return ctfeBytes(val);
3060 @safe unittest
3062 import std.meta;
3063 import std.stdio;
3064 static foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, int, uint, long, ulong,
3065 char, wchar, dchar
3066 /* The trouble here is with floats and doubles being compared against nan
3067 * using a bit compare. There are two kinds of nans, quiet and signaling.
3068 * When a nan passes through the x87, it converts signaling to quiet.
3069 * When a nan passes through the XMM, it does not convert signaling to quiet.
3070 * float.init is a signaling nan.
3071 * The binary API sometimes passes the data through the XMM, sometimes through
3072 * the x87, meaning these will fail the 'is' bit compare under some circumstances.
3073 * I cannot think of a fix for this that makes consistent sense.
3075 /*,float, double*/))
3077 scope(failure) writeln("Failed type: ", T.stringof);
3078 T val;
3079 const T cval;
3080 immutable T ival;
3082 //is instead of == because of NaN for floating point values.
3083 assert(bigEndianToNative!T(nativeToBigEndian(val)) is val);
3084 assert(bigEndianToNative!T(nativeToBigEndian(cval)) is cval);
3085 assert(bigEndianToNative!T(nativeToBigEndian(ival)) is ival);
3086 assert(bigEndianToNative!T(nativeToBigEndian(T.min)) == T.min);
3087 assert(bigEndianToNative!T(nativeToBigEndian(T.max)) == T.max);
3089 //Check CTFE compiles.
3090 static assert(bigEndianToNative!T(nativeToBigEndian(T(1))) is T(1));
3092 static if (isSigned!T)
3093 assert(bigEndianToNative!T(nativeToBigEndian(cast(T) 0)) == 0);
3095 static if (!is(T == bool))
3097 foreach (i; [2, 4, 6, 7, 9, 11])
3099 immutable T maxI = cast(T)(T.max / i);
3100 immutable T minI = cast(T)(T.min / i);
3102 assert(bigEndianToNative!T(nativeToBigEndian(maxI)) == maxI);
3104 static if (T.sizeof > 1)
3105 assert(nativeToBigEndian(maxI) != nativeToLittleEndian(maxI));
3106 else
3107 assert(nativeToBigEndian(maxI) == nativeToLittleEndian(maxI));
3109 static if (isSigned!T)
3111 assert(bigEndianToNative!T(nativeToBigEndian(minI)) == minI);
3113 static if (T.sizeof > 1)
3114 assert(nativeToBigEndian(minI) != nativeToLittleEndian(minI));
3115 else
3116 assert(nativeToBigEndian(minI) == nativeToLittleEndian(minI));
3121 static if (isUnsigned!T || T.sizeof == 1 || is(T == wchar))
3122 assert(nativeToBigEndian(T.max) == nativeToLittleEndian(T.max));
3123 else
3124 assert(nativeToBigEndian(T.max) != nativeToLittleEndian(T.max));
3126 static if (isUnsigned!T || T.sizeof == 1 || isSomeChar!T)
3127 assert(nativeToBigEndian(T.min) == nativeToLittleEndian(T.min));
3128 else
3129 assert(nativeToBigEndian(T.min) != nativeToLittleEndian(T.min));
3135 Converts the given value from big endian to the native endianness and
3136 returns it. The value is given as a `ubyte[n]` where `n` is the size
3137 of the target type. You must give the target type as a template argument,
3138 because there are multiple types with the same size and so the type of the
3139 argument is not enough to determine the return type.
3141 Taking a `ubyte[n]` helps prevent accidentally using a swapped value
3142 as a regular one (and in the case of floating point values, it's necessary,
3143 because the FPU will mess up any swapped floating point values. So, you
3144 can't actually have swapped floating point values as floating point values).
3146 T bigEndianToNative(T, size_t n)(ubyte[n] val) @safe pure nothrow @nogc
3147 if (canSwapEndianness!T && n == T.sizeof)
3149 version (LittleEndian)
3150 return endianToNativeImpl!(true, T, n)(val);
3151 else
3152 return endianToNativeImpl!(false, T, n)(val);
3156 @safe unittest
3158 ushort i = 12345;
3159 ubyte[2] swappedI = nativeToBigEndian(i);
3160 assert(i == bigEndianToNative!ushort(swappedI));
3162 dchar c = 'D';
3163 ubyte[4] swappedC = nativeToBigEndian(c);
3164 assert(c == bigEndianToNative!dchar(swappedC));
3168 Converts the given value from the native endianness to little endian and
3169 returns it as a `ubyte[n]` where `n` is the size of the given type.
3171 Returning a `ubyte[n]` helps prevent accidentally using a swapped value
3172 as a regular one (and in the case of floating point values, it's necessary,
3173 because the FPU will mess up any swapped floating point values. So, you
3174 can't actually have swapped floating point values as floating point values).
3176 auto nativeToLittleEndian(T)(const T val) @safe pure nothrow @nogc
3177 if (canSwapEndianness!T)
3179 version (BigEndian)
3180 return nativeToEndianImpl!true(val);
3181 else
3182 return nativeToEndianImpl!false(val);
3186 @safe unittest
3188 int i = 12345;
3189 ubyte[4] swappedI = nativeToLittleEndian(i);
3190 assert(i == littleEndianToNative!int(swappedI));
3192 double d = 123.45;
3193 ubyte[8] swappedD = nativeToLittleEndian(d);
3194 assert(d == littleEndianToNative!double(swappedD));
3197 @safe unittest
3199 import std.meta;
3200 import std.stdio;
3201 static foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, int, uint, long, ulong,
3202 char, wchar, dchar/*,
3203 float, double*/))
3205 scope(failure) writeln("Failed type: ", T.stringof);
3206 T val;
3207 const T cval;
3208 immutable T ival;
3210 //is instead of == because of NaN for floating point values.
3211 assert(littleEndianToNative!T(nativeToLittleEndian(val)) is val);
3212 assert(littleEndianToNative!T(nativeToLittleEndian(cval)) is cval);
3213 assert(littleEndianToNative!T(nativeToLittleEndian(ival)) is ival);
3214 assert(littleEndianToNative!T(nativeToLittleEndian(T.min)) == T.min);
3215 assert(littleEndianToNative!T(nativeToLittleEndian(T.max)) == T.max);
3217 //Check CTFE compiles.
3218 static assert(littleEndianToNative!T(nativeToLittleEndian(T(1))) is T(1));
3220 static if (isSigned!T)
3221 assert(littleEndianToNative!T(nativeToLittleEndian(cast(T) 0)) == 0);
3223 static if (!is(T == bool))
3225 foreach (i; 2 .. 10)
3227 immutable T maxI = cast(T)(T.max / i);
3228 immutable T minI = cast(T)(T.min / i);
3230 assert(littleEndianToNative!T(nativeToLittleEndian(maxI)) == maxI);
3232 static if (isSigned!T)
3233 assert(littleEndianToNative!T(nativeToLittleEndian(minI)) == minI);
3241 Converts the given value from little endian to the native endianness and
3242 returns it. The value is given as a `ubyte[n]` where `n` is the size
3243 of the target type. You must give the target type as a template argument,
3244 because there are multiple types with the same size and so the type of the
3245 argument is not enough to determine the return type.
3247 Taking a `ubyte[n]` helps prevent accidentally using a swapped value
3248 as a regular one (and in the case of floating point values, it's necessary,
3249 because the FPU will mess up any swapped floating point values. So, you
3250 can't actually have swapped floating point values as floating point values).
3252 `real` is not supported, because its size is implementation-dependent
3253 and therefore could vary from machine to machine (which could make it
3254 unusable if you tried to transfer it to another machine).
3256 T littleEndianToNative(T, size_t n)(ubyte[n] val) @safe pure nothrow @nogc
3257 if (canSwapEndianness!T && n == T.sizeof)
3259 version (BigEndian)
3260 return endianToNativeImpl!(true, T, n)(val);
3261 else
3262 return endianToNativeImpl!(false, T, n)(val);
3266 @safe unittest
3268 ushort i = 12345;
3269 ubyte[2] swappedI = nativeToLittleEndian(i);
3270 assert(i == littleEndianToNative!ushort(swappedI));
3272 dchar c = 'D';
3273 ubyte[4] swappedC = nativeToLittleEndian(c);
3274 assert(c == littleEndianToNative!dchar(swappedC));
3277 private T endianToNativeImpl(bool swap, T, size_t n)(ubyte[n] val) @nogc nothrow pure @safe
3278 if (__traits(isIntegral, T) && n == T.sizeof)
3280 if (!__ctfe)
3282 EndianSwapper!T es = { array: val };
3283 static if (swap)
3284 return swapEndian(es.value);
3285 else
3286 return es.value;
3288 else
3290 static if (swap)
3291 return swapEndian(ctfeRead!T(val));
3292 else
3293 return ctfeRead!T(val);
3297 private auto nativeToEndianImpl(bool swap, T)(const T val) @trusted pure nothrow @nogc
3298 if (isFloatOrDouble!T)
3300 if (!__ctfe)
3302 EndianSwapper!T es = EndianSwapper!T(val);
3303 static if (swap)
3304 es.intValue = swapEndian(es.intValue);
3305 return es.array;
3307 else
3309 static if (T.sizeof == 4)
3310 uint intValue = *cast(const uint*) &val;
3311 else static if (T.sizeof == 8)
3312 ulong intValue = *cast(const ulong*) & val;
3313 static if (swap)
3314 intValue = swapEndian(intValue);
3315 return ctfeBytes(intValue);
3319 private auto endianToNativeImpl(bool swap, T, size_t n)(ubyte[n] val) @trusted pure nothrow @nogc
3320 if (isFloatOrDouble!T && n == T.sizeof)
3322 if (!__ctfe)
3324 EndianSwapper!T es = { array: val };
3325 static if (swap)
3326 es.intValue = swapEndian(es.intValue);
3327 return es.value;
3329 else
3331 static if (n == 4)
3332 uint x = ctfeRead!uint(val);
3333 else static if (n == 8)
3334 ulong x = ctfeRead!ulong(val);
3335 static if (swap)
3336 x = swapEndian(x);
3337 return *cast(T*) &x;
3341 private template isFloatOrDouble(T)
3343 enum isFloatOrDouble = isFloatingPoint!T &&
3344 !is(immutable FloatingPointTypeOf!T == immutable real);
3347 @safe unittest
3349 import std.meta;
3350 static foreach (T; AliasSeq!(float, double))
3352 static assert(isFloatOrDouble!(T));
3353 static assert(isFloatOrDouble!(const T));
3354 static assert(isFloatOrDouble!(immutable T));
3355 static assert(isFloatOrDouble!(shared T));
3356 static assert(isFloatOrDouble!(shared(const T)));
3357 static assert(isFloatOrDouble!(shared(immutable T)));
3360 static assert(!isFloatOrDouble!(real));
3361 static assert(!isFloatOrDouble!(const real));
3362 static assert(!isFloatOrDouble!(immutable real));
3363 static assert(!isFloatOrDouble!(shared real));
3364 static assert(!isFloatOrDouble!(shared(const real)));
3365 static assert(!isFloatOrDouble!(shared(immutable real)));
3368 private template canSwapEndianness(T)
3370 enum canSwapEndianness = isIntegral!T ||
3371 isSomeChar!T ||
3372 isBoolean!T ||
3373 isFloatOrDouble!T;
3376 @safe unittest
3378 import std.meta;
3379 static foreach (T; AliasSeq!(bool, ubyte, byte, ushort, short, uint, int, ulong,
3380 long, char, wchar, dchar, float, double))
3382 static assert(canSwapEndianness!(T));
3383 static assert(canSwapEndianness!(const T));
3384 static assert(canSwapEndianness!(immutable T));
3385 static assert(canSwapEndianness!(shared(T)));
3386 static assert(canSwapEndianness!(shared(const T)));
3387 static assert(canSwapEndianness!(shared(immutable T)));
3391 static foreach (T; AliasSeq!(real, string, wstring, dstring))
3393 static assert(!canSwapEndianness!(T));
3394 static assert(!canSwapEndianness!(const T));
3395 static assert(!canSwapEndianness!(immutable T));
3396 static assert(!canSwapEndianness!(shared(T)));
3397 static assert(!canSwapEndianness!(shared(const T)));
3398 static assert(!canSwapEndianness!(shared(immutable T)));
3403 Takes a range of `ubyte`s and converts the first `T.sizeof` bytes to
3404 `T`. The value returned is converted from the given endianness to the
3405 native endianness. The range is not consumed.
3407 Params:
3408 T = The integral type to convert the first `T.sizeof` bytes to.
3409 endianness = The endianness that the bytes are assumed to be in.
3410 range = The range to read from.
3411 index = The index to start reading from (instead of starting at the
3412 front). If index is a pointer, then it is updated to the index
3413 after the bytes read. The overloads with index are only
3414 available if `hasSlicing!R` is `true`.
3417 T peek(T, Endian endianness = Endian.bigEndian, R)(R range)
3418 if (canSwapEndianness!T &&
3419 isForwardRange!R &&
3420 is(ElementType!R : const ubyte))
3422 static if (hasSlicing!R)
3423 const ubyte[T.sizeof] bytes = range[0 .. T.sizeof];
3424 else
3426 ubyte[T.sizeof] bytes;
3427 //Make sure that range is not consumed, even if it's a class.
3428 range = range.save;
3430 foreach (ref e; bytes)
3432 e = range.front;
3433 range.popFront();
3437 static if (endianness == Endian.bigEndian)
3438 return bigEndianToNative!T(bytes);
3439 else
3440 return littleEndianToNative!T(bytes);
3443 /++ Ditto +/
3444 T peek(T, Endian endianness = Endian.bigEndian, R)(R range, size_t index)
3445 if (canSwapEndianness!T &&
3446 isForwardRange!R &&
3447 hasSlicing!R &&
3448 is(ElementType!R : const ubyte))
3450 return peek!(T, endianness)(range, &index);
3453 /++ Ditto +/
3454 T peek(T, Endian endianness = Endian.bigEndian, R)(R range, size_t* index)
3455 if (canSwapEndianness!T &&
3456 isForwardRange!R &&
3457 hasSlicing!R &&
3458 is(ElementType!R : const ubyte))
3460 assert(index, "index must not point to null");
3462 immutable begin = *index;
3463 immutable end = begin + T.sizeof;
3464 const ubyte[T.sizeof] bytes = range[begin .. end];
3465 *index = end;
3467 static if (endianness == Endian.bigEndian)
3468 return bigEndianToNative!T(bytes);
3469 else
3470 return littleEndianToNative!T(bytes);
3474 @system unittest
3476 ubyte[] buffer = [1, 5, 22, 9, 44, 255, 8];
3477 assert(buffer.peek!uint() == 17110537);
3478 assert(buffer.peek!ushort() == 261);
3479 assert(buffer.peek!ubyte() == 1);
3481 assert(buffer.peek!uint(2) == 369700095);
3482 assert(buffer.peek!ushort(2) == 5641);
3483 assert(buffer.peek!ubyte(2) == 22);
3485 size_t index = 0;
3486 assert(buffer.peek!ushort(&index) == 261);
3487 assert(index == 2);
3489 assert(buffer.peek!uint(&index) == 369700095);
3490 assert(index == 6);
3492 assert(buffer.peek!ubyte(&index) == 8);
3493 assert(index == 7);
3497 @safe unittest
3499 import std.algorithm.iteration : filter;
3500 ubyte[] buffer = [1, 5, 22, 9, 44, 255, 7];
3501 auto range = filter!"true"(buffer);
3502 assert(range.peek!uint() == 17110537);
3503 assert(range.peek!ushort() == 261);
3504 assert(range.peek!ubyte() == 1);
3507 @system unittest
3510 //bool
3511 ubyte[] buffer = [0, 1];
3512 assert(buffer.peek!bool() == false);
3513 assert(buffer.peek!bool(1) == true);
3515 size_t index = 0;
3516 assert(buffer.peek!bool(&index) == false);
3517 assert(index == 1);
3519 assert(buffer.peek!bool(&index) == true);
3520 assert(index == 2);
3524 //char (8bit)
3525 ubyte[] buffer = [97, 98, 99, 100];
3526 assert(buffer.peek!char() == 'a');
3527 assert(buffer.peek!char(1) == 'b');
3529 size_t index = 0;
3530 assert(buffer.peek!char(&index) == 'a');
3531 assert(index == 1);
3533 assert(buffer.peek!char(&index) == 'b');
3534 assert(index == 2);
3538 //wchar (16bit - 2x ubyte)
3539 ubyte[] buffer = [1, 5, 32, 29, 1, 7];
3540 assert(buffer.peek!wchar() == 'ą');
3541 assert(buffer.peek!wchar(2) == '”');
3542 assert(buffer.peek!wchar(4) == 'ć');
3544 size_t index = 0;
3545 assert(buffer.peek!wchar(&index) == 'ą');
3546 assert(index == 2);
3548 assert(buffer.peek!wchar(&index) == '”');
3549 assert(index == 4);
3551 assert(buffer.peek!wchar(&index) == 'ć');
3552 assert(index == 6);
3556 //dchar (32bit - 4x ubyte)
3557 ubyte[] buffer = [0, 0, 1, 5, 0, 0, 32, 29, 0, 0, 1, 7];
3558 assert(buffer.peek!dchar() == 'ą');
3559 assert(buffer.peek!dchar(4) == '”');
3560 assert(buffer.peek!dchar(8) == 'ć');
3562 size_t index = 0;
3563 assert(buffer.peek!dchar(&index) == 'ą');
3564 assert(index == 4);
3566 assert(buffer.peek!dchar(&index) == '”');
3567 assert(index == 8);
3569 assert(buffer.peek!dchar(&index) == 'ć');
3570 assert(index == 12);
3574 //float (32bit - 4x ubyte)
3575 ubyte[] buffer = [66, 0, 0, 0, 65, 200, 0, 0];
3576 assert(buffer.peek!float()== 32.0);
3577 assert(buffer.peek!float(4) == 25.0f);
3579 size_t index = 0;
3580 assert(buffer.peek!float(&index) == 32.0f);
3581 assert(index == 4);
3583 assert(buffer.peek!float(&index) == 25.0f);
3584 assert(index == 8);
3588 //double (64bit - 8x ubyte)
3589 ubyte[] buffer = [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0];
3590 assert(buffer.peek!double() == 32.0);
3591 assert(buffer.peek!double(8) == 25.0);
3593 size_t index = 0;
3594 assert(buffer.peek!double(&index) == 32.0);
3595 assert(index == 8);
3597 assert(buffer.peek!double(&index) == 25.0);
3598 assert(index == 16);
3602 //enum
3603 ubyte[] buffer = [0, 0, 0, 10, 0, 0, 0, 20, 0, 0, 0, 30];
3605 enum Foo
3607 one = 10,
3608 two = 20,
3609 three = 30
3612 assert(buffer.peek!Foo() == Foo.one);
3613 assert(buffer.peek!Foo(0) == Foo.one);
3614 assert(buffer.peek!Foo(4) == Foo.two);
3615 assert(buffer.peek!Foo(8) == Foo.three);
3617 size_t index = 0;
3618 assert(buffer.peek!Foo(&index) == Foo.one);
3619 assert(index == 4);
3621 assert(buffer.peek!Foo(&index) == Foo.two);
3622 assert(index == 8);
3624 assert(buffer.peek!Foo(&index) == Foo.three);
3625 assert(index == 12);
3629 //enum - bool
3630 ubyte[] buffer = [0, 1];
3632 enum Bool: bool
3634 bfalse = false,
3635 btrue = true,
3638 assert(buffer.peek!Bool() == Bool.bfalse);
3639 assert(buffer.peek!Bool(0) == Bool.bfalse);
3640 assert(buffer.peek!Bool(1) == Bool.btrue);
3642 size_t index = 0;
3643 assert(buffer.peek!Bool(&index) == Bool.bfalse);
3644 assert(index == 1);
3646 assert(buffer.peek!Bool(&index) == Bool.btrue);
3647 assert(index == 2);
3651 //enum - float
3652 ubyte[] buffer = [66, 0, 0, 0, 65, 200, 0, 0];
3654 enum Float: float
3656 one = 32.0f,
3657 two = 25.0f
3660 assert(buffer.peek!Float() == Float.one);
3661 assert(buffer.peek!Float(0) == Float.one);
3662 assert(buffer.peek!Float(4) == Float.two);
3664 size_t index = 0;
3665 assert(buffer.peek!Float(&index) == Float.one);
3666 assert(index == 4);
3668 assert(buffer.peek!Float(&index) == Float.two);
3669 assert(index == 8);
3673 //enum - double
3674 ubyte[] buffer = [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0];
3676 enum Double: double
3678 one = 32.0,
3679 two = 25.0
3682 assert(buffer.peek!Double() == Double.one);
3683 assert(buffer.peek!Double(0) == Double.one);
3684 assert(buffer.peek!Double(8) == Double.two);
3686 size_t index = 0;
3687 assert(buffer.peek!Double(&index) == Double.one);
3688 assert(index == 8);
3690 assert(buffer.peek!Double(&index) == Double.two);
3691 assert(index == 16);
3695 //enum - real
3696 ubyte[] buffer = [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0];
3698 enum Real: real
3700 one = 32.0,
3701 two = 25.0
3704 static assert(!__traits(compiles, buffer.peek!Real()));
3709 Takes a range of `ubyte`s and converts the first `T.sizeof` bytes to
3710 `T`. The value returned is converted from the given endianness to the
3711 native endianness. The `T.sizeof` bytes which are read are consumed from
3712 the range.
3714 Params:
3715 T = The integral type to convert the first `T.sizeof` bytes to.
3716 endianness = The endianness that the bytes are assumed to be in.
3717 range = The range to read from.
3719 T read(T, Endian endianness = Endian.bigEndian, R)(ref R range)
3720 if (canSwapEndianness!T && isInputRange!R && is(ElementType!R : const ubyte))
3722 static if (hasSlicing!R && is(typeof(R.init[0 .. 0]) : const(ubyte)[]))
3724 const ubyte[T.sizeof] bytes = range[0 .. T.sizeof];
3725 range.popFrontN(T.sizeof);
3727 else
3729 ubyte[T.sizeof] bytes;
3731 foreach (ref e; bytes)
3733 e = range.front;
3734 range.popFront();
3738 static if (endianness == Endian.bigEndian)
3739 return bigEndianToNative!T(bytes);
3740 else
3741 return littleEndianToNative!T(bytes);
3745 @safe unittest
3747 import std.range.primitives : empty;
3748 ubyte[] buffer = [1, 5, 22, 9, 44, 255, 8];
3749 assert(buffer.length == 7);
3751 assert(buffer.read!ushort() == 261);
3752 assert(buffer.length == 5);
3754 assert(buffer.read!uint() == 369700095);
3755 assert(buffer.length == 1);
3757 assert(buffer.read!ubyte() == 8);
3758 assert(buffer.empty);
3761 @safe unittest
3764 //bool
3765 ubyte[] buffer = [0, 1];
3766 assert(buffer.length == 2);
3768 assert(buffer.read!bool() == false);
3769 assert(buffer.length == 1);
3771 assert(buffer.read!bool() == true);
3772 assert(buffer.empty);
3776 //char (8bit)
3777 ubyte[] buffer = [97, 98, 99];
3778 assert(buffer.length == 3);
3780 assert(buffer.read!char() == 'a');
3781 assert(buffer.length == 2);
3783 assert(buffer.read!char() == 'b');
3784 assert(buffer.length == 1);
3786 assert(buffer.read!char() == 'c');
3787 assert(buffer.empty);
3791 //wchar (16bit - 2x ubyte)
3792 ubyte[] buffer = [1, 5, 32, 29, 1, 7];
3793 assert(buffer.length == 6);
3795 assert(buffer.read!wchar() == 'ą');
3796 assert(buffer.length == 4);
3798 assert(buffer.read!wchar() == '”');
3799 assert(buffer.length == 2);
3801 assert(buffer.read!wchar() == 'ć');
3802 assert(buffer.empty);
3806 //dchar (32bit - 4x ubyte)
3807 ubyte[] buffer = [0, 0, 1, 5, 0, 0, 32, 29, 0, 0, 1, 7];
3808 assert(buffer.length == 12);
3810 assert(buffer.read!dchar() == 'ą');
3811 assert(buffer.length == 8);
3813 assert(buffer.read!dchar() == '”');
3814 assert(buffer.length == 4);
3816 assert(buffer.read!dchar() == 'ć');
3817 assert(buffer.empty);
3821 //float (32bit - 4x ubyte)
3822 ubyte[] buffer = [66, 0, 0, 0, 65, 200, 0, 0];
3823 assert(buffer.length == 8);
3825 assert(buffer.read!float()== 32.0);
3826 assert(buffer.length == 4);
3828 assert(buffer.read!float() == 25.0f);
3829 assert(buffer.empty);
3833 //double (64bit - 8x ubyte)
3834 ubyte[] buffer = [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0];
3835 assert(buffer.length == 16);
3837 assert(buffer.read!double() == 32.0);
3838 assert(buffer.length == 8);
3840 assert(buffer.read!double() == 25.0);
3841 assert(buffer.empty);
3845 //enum - uint
3846 ubyte[] buffer = [0, 0, 0, 10, 0, 0, 0, 20, 0, 0, 0, 30];
3847 assert(buffer.length == 12);
3849 enum Foo
3851 one = 10,
3852 two = 20,
3853 three = 30
3856 assert(buffer.read!Foo() == Foo.one);
3857 assert(buffer.length == 8);
3859 assert(buffer.read!Foo() == Foo.two);
3860 assert(buffer.length == 4);
3862 assert(buffer.read!Foo() == Foo.three);
3863 assert(buffer.empty);
3867 //enum - bool
3868 ubyte[] buffer = [0, 1];
3869 assert(buffer.length == 2);
3871 enum Bool: bool
3873 bfalse = false,
3874 btrue = true,
3877 assert(buffer.read!Bool() == Bool.bfalse);
3878 assert(buffer.length == 1);
3880 assert(buffer.read!Bool() == Bool.btrue);
3881 assert(buffer.empty);
3885 //enum - float
3886 ubyte[] buffer = [66, 0, 0, 0, 65, 200, 0, 0];
3887 assert(buffer.length == 8);
3889 enum Float: float
3891 one = 32.0f,
3892 two = 25.0f
3895 assert(buffer.read!Float() == Float.one);
3896 assert(buffer.length == 4);
3898 assert(buffer.read!Float() == Float.two);
3899 assert(buffer.empty);
3903 //enum - double
3904 ubyte[] buffer = [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0];
3905 assert(buffer.length == 16);
3907 enum Double: double
3909 one = 32.0,
3910 two = 25.0
3913 assert(buffer.read!Double() == Double.one);
3914 assert(buffer.length == 8);
3916 assert(buffer.read!Double() == Double.two);
3917 assert(buffer.empty);
3921 //enum - real
3922 ubyte[] buffer = [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0];
3924 enum Real: real
3926 one = 32.0,
3927 two = 25.0
3930 static assert(!__traits(compiles, buffer.read!Real()));
3934 // https://issues.dlang.org/show_bug.cgi?id=17247
3935 @safe unittest
3937 struct UbyteRange
3939 ubyte[] impl;
3940 @property bool empty() { return impl.empty; }
3941 @property ubyte front() { return impl.front; }
3942 void popFront() { impl.popFront(); }
3943 @property UbyteRange save() { return this; }
3945 // N.B. support slicing but do not return ubyte[] slices.
3946 UbyteRange opSlice(size_t start, size_t end)
3948 return UbyteRange(impl[start .. end]);
3950 @property size_t length() { return impl.length; }
3951 alias opDollar = length;
3953 static assert(hasSlicing!UbyteRange);
3955 auto r = UbyteRange([0x01, 0x00, 0x00, 0x00]);
3956 int x = r.read!(int, Endian.littleEndian)();
3957 assert(x == 1);
3962 Takes an integral value, converts it to the given endianness, and writes it
3963 to the given range of `ubyte`s as a sequence of `T.sizeof` `ubyte`s
3964 starting at index. `hasSlicing!R` must be `true`.
3966 Params:
3967 T = The integral type to convert the first `T.sizeof` bytes to.
3968 endianness = The endianness to _write the bytes in.
3969 range = The range to _write to.
3970 value = The value to _write.
3971 index = The index to start writing to. If index is a pointer, then it
3972 is updated to the index after the bytes read.
3974 void write(T, Endian endianness = Endian.bigEndian, R)(R range, const T value, size_t index)
3975 if (canSwapEndianness!T &&
3976 isForwardRange!R &&
3977 hasSlicing!R &&
3978 is(ElementType!R : ubyte))
3980 write!(T, endianness)(range, value, &index);
3983 /++ Ditto +/
3984 void write(T, Endian endianness = Endian.bigEndian, R)(R range, const T value, size_t* index)
3985 if (canSwapEndianness!T &&
3986 isForwardRange!R &&
3987 hasSlicing!R &&
3988 is(ElementType!R : ubyte))
3990 assert(index, "index must not point to null");
3992 static if (endianness == Endian.bigEndian)
3993 immutable bytes = nativeToBigEndian!T(value);
3994 else
3995 immutable bytes = nativeToLittleEndian!T(value);
3997 immutable begin = *index;
3998 immutable end = begin + T.sizeof;
3999 *index = end;
4000 range[begin .. end] = bytes[0 .. T.sizeof];
4004 @system unittest
4006 ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0];
4007 buffer.write!uint(29110231u, 0);
4008 assert(buffer == [1, 188, 47, 215, 0, 0, 0, 0]);
4010 buffer.write!ushort(927, 0);
4011 assert(buffer == [3, 159, 47, 215, 0, 0, 0, 0]);
4013 buffer.write!ubyte(42, 0);
4014 assert(buffer == [42, 159, 47, 215, 0, 0, 0, 0]);
4018 @system unittest
4020 ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0, 0];
4021 buffer.write!uint(142700095u, 2);
4022 assert(buffer == [0, 0, 8, 129, 110, 63, 0, 0, 0]);
4024 buffer.write!ushort(19839, 2);
4025 assert(buffer == [0, 0, 77, 127, 110, 63, 0, 0, 0]);
4027 buffer.write!ubyte(132, 2);
4028 assert(buffer == [0, 0, 132, 127, 110, 63, 0, 0, 0]);
4032 @system unittest
4034 ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0];
4035 size_t index = 0;
4036 buffer.write!ushort(261, &index);
4037 assert(buffer == [1, 5, 0, 0, 0, 0, 0, 0]);
4038 assert(index == 2);
4040 buffer.write!uint(369700095u, &index);
4041 assert(buffer == [1, 5, 22, 9, 44, 255, 0, 0]);
4042 assert(index == 6);
4044 buffer.write!ubyte(8, &index);
4045 assert(buffer == [1, 5, 22, 9, 44, 255, 8, 0]);
4046 assert(index == 7);
4049 /// bool
4050 @system unittest
4052 ubyte[] buffer = [0, 0];
4053 buffer.write!bool(false, 0);
4054 assert(buffer == [0, 0]);
4056 buffer.write!bool(true, 0);
4057 assert(buffer == [1, 0]);
4059 buffer.write!bool(true, 1);
4060 assert(buffer == [1, 1]);
4062 buffer.write!bool(false, 1);
4063 assert(buffer == [1, 0]);
4065 size_t index = 0;
4066 buffer.write!bool(false, &index);
4067 assert(buffer == [0, 0]);
4068 assert(index == 1);
4070 buffer.write!bool(true, &index);
4071 assert(buffer == [0, 1]);
4072 assert(index == 2);
4075 /// char(8-bit)
4076 @system unittest
4078 ubyte[] buffer = [0, 0, 0];
4080 buffer.write!char('a', 0);
4081 assert(buffer == [97, 0, 0]);
4083 buffer.write!char('b', 1);
4084 assert(buffer == [97, 98, 0]);
4086 size_t index = 0;
4087 buffer.write!char('a', &index);
4088 assert(buffer == [97, 98, 0]);
4089 assert(index == 1);
4091 buffer.write!char('b', &index);
4092 assert(buffer == [97, 98, 0]);
4093 assert(index == 2);
4095 buffer.write!char('c', &index);
4096 assert(buffer == [97, 98, 99]);
4097 assert(index == 3);
4100 /// wchar (16bit - 2x ubyte)
4101 @system unittest
4103 ubyte[] buffer = [0, 0, 0, 0];
4105 buffer.write!wchar('ą', 0);
4106 assert(buffer == [1, 5, 0, 0]);
4108 buffer.write!wchar('”', 2);
4109 assert(buffer == [1, 5, 32, 29]);
4111 size_t index = 0;
4112 buffer.write!wchar('ć', &index);
4113 assert(buffer == [1, 7, 32, 29]);
4114 assert(index == 2);
4116 buffer.write!wchar('ą', &index);
4117 assert(buffer == [1, 7, 1, 5]);
4118 assert(index == 4);
4121 /// dchar (32bit - 4x ubyte)
4122 @system unittest
4124 ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0];
4126 buffer.write!dchar('ą', 0);
4127 assert(buffer == [0, 0, 1, 5, 0, 0, 0, 0]);
4129 buffer.write!dchar('”', 4);
4130 assert(buffer == [0, 0, 1, 5, 0, 0, 32, 29]);
4132 size_t index = 0;
4133 buffer.write!dchar('ć', &index);
4134 assert(buffer == [0, 0, 1, 7, 0, 0, 32, 29]);
4135 assert(index == 4);
4137 buffer.write!dchar('ą', &index);
4138 assert(buffer == [0, 0, 1, 7, 0, 0, 1, 5]);
4139 assert(index == 8);
4142 /// float (32bit - 4x ubyte)
4143 @system unittest
4145 ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0];
4147 buffer.write!float(32.0f, 0);
4148 assert(buffer == [66, 0, 0, 0, 0, 0, 0, 0]);
4150 buffer.write!float(25.0f, 4);
4151 assert(buffer == [66, 0, 0, 0, 65, 200, 0, 0]);
4153 size_t index = 0;
4154 buffer.write!float(25.0f, &index);
4155 assert(buffer == [65, 200, 0, 0, 65, 200, 0, 0]);
4156 assert(index == 4);
4158 buffer.write!float(32.0f, &index);
4159 assert(buffer == [65, 200, 0, 0, 66, 0, 0, 0]);
4160 assert(index == 8);
4163 /// double (64bit - 8x ubyte)
4164 @system unittest
4166 ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4168 buffer.write!double(32.0, 0);
4169 assert(buffer == [64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
4171 buffer.write!double(25.0, 8);
4172 assert(buffer == [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0]);
4174 size_t index = 0;
4175 buffer.write!double(25.0, &index);
4176 assert(buffer == [64, 57, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0]);
4177 assert(index == 8);
4179 buffer.write!double(32.0, &index);
4180 assert(buffer == [64, 57, 0, 0, 0, 0, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0]);
4181 assert(index == 16);
4184 /// enum
4185 @system unittest
4187 ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4189 enum Foo
4191 one = 10,
4192 two = 20,
4193 three = 30
4196 buffer.write!Foo(Foo.one, 0);
4197 assert(buffer == [0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0]);
4199 buffer.write!Foo(Foo.two, 4);
4200 assert(buffer == [0, 0, 0, 10, 0, 0, 0, 20, 0, 0, 0, 0]);
4202 buffer.write!Foo(Foo.three, 8);
4203 assert(buffer == [0, 0, 0, 10, 0, 0, 0, 20, 0, 0, 0, 30]);
4205 size_t index = 0;
4206 buffer.write!Foo(Foo.three, &index);
4207 assert(buffer == [0, 0, 0, 30, 0, 0, 0, 20, 0, 0, 0, 30]);
4208 assert(index == 4);
4210 buffer.write!Foo(Foo.one, &index);
4211 assert(buffer == [0, 0, 0, 30, 0, 0, 0, 10, 0, 0, 0, 30]);
4212 assert(index == 8);
4214 buffer.write!Foo(Foo.two, &index);
4215 assert(buffer == [0, 0, 0, 30, 0, 0, 0, 10, 0, 0, 0, 20]);
4216 assert(index == 12);
4219 // enum - bool
4220 @system unittest
4222 ubyte[] buffer = [0, 0];
4224 enum Bool: bool
4226 bfalse = false,
4227 btrue = true,
4230 buffer.write!Bool(Bool.btrue, 0);
4231 assert(buffer == [1, 0]);
4233 buffer.write!Bool(Bool.btrue, 1);
4234 assert(buffer == [1, 1]);
4236 size_t index = 0;
4237 buffer.write!Bool(Bool.bfalse, &index);
4238 assert(buffer == [0, 1]);
4239 assert(index == 1);
4241 buffer.write!Bool(Bool.bfalse, &index);
4242 assert(buffer == [0, 0]);
4243 assert(index == 2);
4246 /// enum - float
4247 @system unittest
4249 ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0];
4251 enum Float: float
4253 one = 32.0f,
4254 two = 25.0f
4257 buffer.write!Float(Float.one, 0);
4258 assert(buffer == [66, 0, 0, 0, 0, 0, 0, 0]);
4260 buffer.write!Float(Float.two, 4);
4261 assert(buffer == [66, 0, 0, 0, 65, 200, 0, 0]);
4263 size_t index = 0;
4264 buffer.write!Float(Float.two, &index);
4265 assert(buffer == [65, 200, 0, 0, 65, 200, 0, 0]);
4266 assert(index == 4);
4268 buffer.write!Float(Float.one, &index);
4269 assert(buffer == [65, 200, 0, 0, 66, 0, 0, 0]);
4270 assert(index == 8);
4273 /// enum - double
4274 @system unittest
4276 ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4278 enum Double: double
4280 one = 32.0,
4281 two = 25.0
4284 buffer.write!Double(Double.one, 0);
4285 assert(buffer == [64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
4287 buffer.write!Double(Double.two, 8);
4288 assert(buffer == [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0]);
4290 size_t index = 0;
4291 buffer.write!Double(Double.two, &index);
4292 assert(buffer == [64, 57, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0]);
4293 assert(index == 8);
4295 buffer.write!Double(Double.one, &index);
4296 assert(buffer == [64, 57, 0, 0, 0, 0, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0]);
4297 assert(index == 16);
4300 /// enum - real
4301 @system unittest
4303 ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
4305 enum Real: real
4307 one = 32.0,
4308 two = 25.0
4311 static assert(!__traits(compiles, buffer.write!Real(Real.one)));
4316 Takes an integral value, converts it to the given endianness, and appends
4317 it to the given range of `ubyte`s (using `put`) as a sequence of
4318 `T.sizeof` `ubyte`s starting at index. `hasSlicing!R` must be
4319 `true`.
4321 Params:
4322 T = The integral type to convert the first `T.sizeof` bytes to.
4323 endianness = The endianness to write the bytes in.
4324 range = The range to _append to.
4325 value = The value to _append.
4327 void append(T, Endian endianness = Endian.bigEndian, R)(R range, const T value)
4328 if (canSwapEndianness!T && isOutputRange!(R, ubyte))
4330 static if (endianness == Endian.bigEndian)
4331 immutable bytes = nativeToBigEndian!T(value);
4332 else
4333 immutable bytes = nativeToLittleEndian!T(value);
4335 put(range, bytes[]);
4339 @safe unittest
4341 import std.array;
4342 auto buffer = appender!(const ubyte[])();
4343 buffer.append!ushort(261);
4344 assert(buffer.data == [1, 5]);
4346 buffer.append!uint(369700095u);
4347 assert(buffer.data == [1, 5, 22, 9, 44, 255]);
4349 buffer.append!ubyte(8);
4350 assert(buffer.data == [1, 5, 22, 9, 44, 255, 8]);
4353 /// bool
4354 @safe unittest
4356 import std.array : appender;
4357 auto buffer = appender!(const ubyte[])();
4359 buffer.append!bool(true);
4360 assert(buffer.data == [1]);
4362 buffer.append!bool(false);
4363 assert(buffer.data == [1, 0]);
4366 /// char wchar dchar
4367 @safe unittest
4369 import std.array : appender;
4370 auto buffer = appender!(const ubyte[])();
4372 buffer.append!char('a');
4373 assert(buffer.data == [97]);
4375 buffer.append!char('b');
4376 assert(buffer.data == [97, 98]);
4378 buffer.append!wchar('ą');
4379 assert(buffer.data == [97, 98, 1, 5]);
4381 buffer.append!dchar('ą');
4382 assert(buffer.data == [97, 98, 1, 5, 0, 0, 1, 5]);
4385 /// float double
4386 @safe unittest
4388 import std.array : appender;
4389 auto buffer = appender!(const ubyte[])();
4391 buffer.append!float(32.0f);
4392 assert(buffer.data == [66, 0, 0, 0]);
4394 buffer.append!double(32.0);
4395 assert(buffer.data == [66, 0, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0]);
4398 /// enum
4399 @safe unittest
4401 import std.array : appender;
4402 auto buffer = appender!(const ubyte[])();
4404 enum Foo
4406 one = 10,
4407 two = 20,
4408 three = 30
4411 buffer.append!Foo(Foo.one);
4412 assert(buffer.data == [0, 0, 0, 10]);
4414 buffer.append!Foo(Foo.two);
4415 assert(buffer.data == [0, 0, 0, 10, 0, 0, 0, 20]);
4417 buffer.append!Foo(Foo.three);
4418 assert(buffer.data == [0, 0, 0, 10, 0, 0, 0, 20, 0, 0, 0, 30]);
4421 /// enum - bool
4422 @safe unittest
4424 import std.array : appender;
4425 auto buffer = appender!(const ubyte[])();
4427 enum Bool: bool
4429 bfalse = false,
4430 btrue = true,
4433 buffer.append!Bool(Bool.btrue);
4434 assert(buffer.data == [1]);
4436 buffer.append!Bool(Bool.bfalse);
4437 assert(buffer.data == [1, 0]);
4439 buffer.append!Bool(Bool.btrue);
4440 assert(buffer.data == [1, 0, 1]);
4443 /// enum - float
4444 @safe unittest
4446 import std.array : appender;
4447 auto buffer = appender!(const ubyte[])();
4449 enum Float: float
4451 one = 32.0f,
4452 two = 25.0f
4455 buffer.append!Float(Float.one);
4456 assert(buffer.data == [66, 0, 0, 0]);
4458 buffer.append!Float(Float.two);
4459 assert(buffer.data == [66, 0, 0, 0, 65, 200, 0, 0]);
4462 /// enum - double
4463 @safe unittest
4465 import std.array : appender;
4466 auto buffer = appender!(const ubyte[])();
4468 enum Double: double
4470 one = 32.0,
4471 two = 25.0
4474 buffer.append!Double(Double.one);
4475 assert(buffer.data == [64, 64, 0, 0, 0, 0, 0, 0]);
4477 buffer.append!Double(Double.two);
4478 assert(buffer.data == [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0]);
4481 /// enum - real
4482 @safe unittest
4484 import std.array : appender;
4485 auto buffer = appender!(const ubyte[])();
4487 enum Real: real
4489 one = 32.0,
4490 two = 25.0
4493 static assert(!__traits(compiles, buffer.append!Real(Real.one)));
4496 @system unittest
4498 import std.array;
4499 import std.format : format;
4500 import std.meta : AliasSeq;
4501 static foreach (endianness; [Endian.bigEndian, Endian.littleEndian])
4503 auto toWrite = appender!(ubyte[])();
4504 alias Types = AliasSeq!(uint, int, long, ulong, short, ubyte, ushort, byte, uint);
4505 ulong[] values = [42, -11, long.max, 1098911981329L, 16, 255, 19012, 2, 17];
4506 assert(Types.length == values.length);
4508 size_t index = 0;
4509 size_t length = 0;
4510 static foreach (T; Types)
4512 toWrite.append!(T, endianness)(cast(T) values[index++]);
4513 length += T.sizeof;
4516 auto toRead = toWrite.data;
4517 assert(toRead.length == length);
4519 index = 0;
4520 static foreach (T; Types)
4522 assert(toRead.peek!(T, endianness)() == values[index], format("Failed Index: %s", index));
4523 assert(toRead.peek!(T, endianness)(0) == values[index], format("Failed Index: %s", index));
4524 assert(toRead.length == length,
4525 format("Failed Index [%s], Actual Length: %s", index, toRead.length));
4526 assert(toRead.read!(T, endianness)() == values[index], format("Failed Index: %s", index));
4527 length -= T.sizeof;
4528 assert(toRead.length == length,
4529 format("Failed Index [%s], Actual Length: %s", index, toRead.length));
4530 ++index;
4532 assert(toRead.empty);
4537 Counts the number of set bits in the binary representation of `value`.
4538 For signed integers, the sign bit is included in the count.
4540 private uint countBitsSet(T)(const T value)
4541 if (isIntegral!T)
4543 static if (T.sizeof == 8)
4545 import core.bitop : popcnt;
4546 const c = popcnt(cast(ulong) value);
4548 else static if (T.sizeof == 4)
4550 import core.bitop : popcnt;
4551 const c = popcnt(cast(uint) value);
4553 // http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
4554 else static if (T.sizeof == 2)
4556 uint c = value - ((value >> 1) & 0x5555);
4557 c = ((c >> 2) & 0x3333) + (c & 0X3333);
4558 c = ((c >> 4) + c) & 0x0F0F;
4559 c = ((c >> 8) + c) & 0x00FF;
4561 else static if (T.sizeof == 1)
4563 uint c = value - ((value >> 1) & 0x55);
4564 c = ((c >> 2) & 0x33) + (c & 0X33);
4565 c = ((c >> 4) + c) & 0x0F;
4567 else
4569 static assert(false, "countBitsSet only supports 1, 2, 4, or 8 byte sized integers.");
4571 return cast(uint) c;
4574 @safe unittest
4576 assert(countBitsSet(1) == 1);
4577 assert(countBitsSet(0) == 0);
4578 assert(countBitsSet(int.min) == 1);
4579 assert(countBitsSet(uint.max) == 32);
4582 @safe unittest
4584 import std.meta;
4585 static foreach (T; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong))
4587 assert(countBitsSet(cast(T) 0) == 0);
4588 assert(countBitsSet(cast(T) 1) == 1);
4589 assert(countBitsSet(cast(T) 2) == 1);
4590 assert(countBitsSet(cast(T) 3) == 2);
4591 assert(countBitsSet(cast(T) 4) == 1);
4592 assert(countBitsSet(cast(T) 5) == 2);
4593 assert(countBitsSet(cast(T) 127) == 7);
4594 static if (isSigned!T)
4596 assert(countBitsSet(cast(T)-1) == 8 * T.sizeof);
4597 assert(countBitsSet(T.min) == 1);
4599 else
4601 assert(countBitsSet(T.max) == 8 * T.sizeof);
4603 // Check CTFE compiles.
4604 static assert(countBitsSet(cast(T) 1) == 1);
4606 assert(countBitsSet(1_000_000) == 7);
4607 foreach (i; 0 .. 63)
4608 assert(countBitsSet(1UL << i) == 1);
4611 private struct BitsSet(T)
4613 static assert(T.sizeof <= 8, "bitsSet assumes T is no more than 64-bit.");
4615 @nogc pure nothrow:
4617 this(T value, size_t startIndex = 0)
4619 _value = value;
4620 // Further calculation is only valid and needed when the range is non-empty.
4621 if (!_value)
4622 return;
4624 import core.bitop : bsf;
4625 immutable trailingZerosCount = bsf(value);
4626 _value >>>= trailingZerosCount;
4627 _index = startIndex + trailingZerosCount;
4630 @property size_t front() const
4632 return _index;
4635 @property bool empty() const
4637 return !_value;
4640 void popFront()
4642 assert(_value, "Cannot call popFront on empty range.");
4644 _value >>>= 1;
4645 // Further calculation is only valid and needed when the range is non-empty.
4646 if (!_value)
4647 return;
4649 import core.bitop : bsf;
4650 immutable trailingZerosCount = bsf(_value);
4651 _value >>>= trailingZerosCount;
4652 _index += trailingZerosCount + 1;
4655 @property BitsSet save() const
4657 return this;
4660 @property size_t length() const
4662 return countBitsSet(_value);
4665 private T _value;
4666 private size_t _index;
4670 Range that iterates the indices of the set bits in `value`.
4671 Index 0 corresponds to the least significant bit.
4672 For signed integers, the highest index corresponds to the sign bit.
4674 auto bitsSet(T)(const T value) @nogc pure nothrow
4675 if (isIntegral!T)
4677 return BitsSet!T(value);
4681 @safe unittest
4683 import std.algorithm.comparison : equal;
4684 import std.range : iota;
4686 assert(bitsSet(1).equal([0]));
4687 assert(bitsSet(5).equal([0, 2]));
4688 assert(bitsSet(-1).equal(iota(32)));
4689 assert(bitsSet(int.min).equal([31]));
4692 @safe unittest
4694 import std.algorithm.comparison : equal;
4695 import std.range : iota;
4697 import std.meta;
4698 static foreach (T; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong))
4700 assert(bitsSet(cast(T) 0).empty);
4701 assert(bitsSet(cast(T) 1).equal([0]));
4702 assert(bitsSet(cast(T) 2).equal([1]));
4703 assert(bitsSet(cast(T) 3).equal([0, 1]));
4704 assert(bitsSet(cast(T) 4).equal([2]));
4705 assert(bitsSet(cast(T) 5).equal([0, 2]));
4706 assert(bitsSet(cast(T) 127).equal(iota(7)));
4707 static if (isSigned!T)
4709 assert(bitsSet(cast(T)-1).equal(iota(8 * T.sizeof)));
4710 assert(bitsSet(T.min).equal([8 * T.sizeof - 1]));
4712 else
4714 assert(bitsSet(T.max).equal(iota(8 * T.sizeof)));
4717 assert(bitsSet(1_000_000).equal([6, 9, 14, 16, 17, 18, 19]));
4718 foreach (i; 0 .. 63)
4719 assert(bitsSet(1UL << i).equal([i]));