1// Written in the D programming language.
2
3/**
4Bit-level manipulation facilities.
5
6$(SCRIPT inhibitQuickIndex = 1;)
7$(BOOKTABLE,
8$(TR $(TH Category) $(TH Functions))
9$(TR $(TD Bit constructs) $(TD
10    $(LREF BitArray)
11    $(LREF bitfields)
12    $(LREF bitsSet)
13))
14$(TR $(TD Endianness conversion) $(TD
15    $(LREF bigEndianToNative)
16    $(LREF littleEndianToNative)
17    $(LREF nativeToBigEndian)
18    $(LREF nativeToLittleEndian)
19    $(LREF swapEndian)
20))
21$(TR $(TD Integral ranges) $(TD
22    $(LREF append)
23    $(LREF peek)
24    $(LREF read)
25    $(LREF write)
26))
27$(TR $(TD Floating-Point manipulation) $(TD
28    $(LREF DoubleRep)
29    $(LREF FloatRep)
30))
31$(TR $(TD Tagging) $(TD
32    $(LREF taggedClassRef)
33    $(LREF taggedPointer)
34))
35)
36
37Copyright: Copyright Digital Mars 2007 - 2011.
38License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
39Authors:   $(HTTP digitalmars.com, Walter Bright),
40           $(HTTP erdani.org, Andrei Alexandrescu),
41           Jonathan M Davis,
42           Alex R��nne Petersen,
43           Damian Ziemba,
44           Amaury SECHET
45Source: $(PHOBOSSRC std/_bitmanip.d)
46*/
47/*
48         Copyright Digital Mars 2007 - 2012.
49Distributed under the Boost Software License, Version 1.0.
50   (See accompanying file LICENSE_1_0.txt or copy at
51         http://www.boost.org/LICENSE_1_0.txt)
52*/
53module std.bitmanip;
54
55//debug = bitarray;                // uncomment to turn on debugging printf's
56
57import std.range.primitives;
58public import std.system : Endian;
59import std.traits;
60
61version (unittest)
62{
63    import std.stdio;
64}
65
66
67private string myToString(ulong n)
68{
69    import core.internal.string : UnsignedStringBuf, unsignedToTempString;
70    UnsignedStringBuf buf;
71    auto s = unsignedToTempString(n, buf);
72    return cast(string) s ~ (n > uint.max ? "UL" : "U");
73}
74
75private template createAccessors(
76    string store, T, string name, size_t len, size_t offset)
77{
78    static if (!name.length)
79    {
80        // No need to create any accessor
81        enum result = "";
82    }
83    else static if (len == 0)
84    {
85        // Fields of length 0 are always zero
86        enum result = "enum "~T.stringof~" "~name~" = 0;\n";
87    }
88    else
89    {
90        enum ulong
91            maskAllElse = ((~0uL) >> (64 - len)) << offset,
92            signBitCheck = 1uL << (len - 1);
93
94        static if (T.min < 0)
95        {
96            enum long minVal = -(1uL << (len - 1));
97            enum ulong maxVal = (1uL << (len - 1)) - 1;
98            alias UT = Unsigned!(T);
99            enum UT extendSign = cast(UT)~((~0uL) >> (64 - len));
100        }
101        else
102        {
103            enum ulong minVal = 0;
104            enum ulong maxVal = (~0uL) >> (64 - len);
105            enum extendSign = 0;
106        }
107
108        static if (is(T == bool))
109        {
110            static assert(len == 1);
111            enum result =
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";
119        }
120        else
121        {
122            // getter
123            enum result = "@property "~T.stringof~" "~name~"() @safe pure nothrow @nogc const { auto result = "
124                ~"("~store~" & "
125                ~ myToString(maskAllElse) ~ ") >>"
126                ~ myToString(offset) ~ ";"
127                ~ (T.min < 0
128                   ? "if (result >= " ~ myToString(signBitCheck)
129                   ~ ") result |= " ~ myToString(extendSign) ~ ";"
130                   : "")
131                ~ " return cast("~T.stringof~") result;}\n"
132            // setter
133                ~"@property void "~name~"("~T.stringof~" v) @safe pure nothrow @nogc { "
134                ~"assert(v >= "~name~`_min, "Value is smaller than the minimum value of bitfield '`~name~`'"); `
135                ~"assert(v <= "~name~`_max, "Value is greater than the maximum value of bitfield '`~name~`'"); `
136                ~store~" = cast(typeof("~store~"))"
137                ~" (("~store~" & (-1-cast(typeof("~store~"))"~myToString(maskAllElse)~"))"
138                ~" | ((cast(typeof("~store~")) v << "~myToString(offset)~")"
139                ~" & "~myToString(maskAllElse)~"));}\n"
140            // constants
141                ~"enum "~T.stringof~" "~name~"_min = cast("~T.stringof~")"
142                ~myToString(minVal)~"; "
143                ~" enum "~T.stringof~" "~name~"_max = cast("~T.stringof~")"
144                ~myToString(maxVal)~"; ";
145        }
146    }
147}
148
149private template createStoreName(Ts...)
150{
151    static if (Ts.length < 2)
152        enum createStoreName = "";
153    else
154        enum createStoreName = "_" ~ Ts[1] ~ createStoreName!(Ts[3 .. $]);
155}
156
157private template createStorageAndFields(Ts...)
158{
159    enum Name = createStoreName!Ts;
160    enum Size = sizeOfBitField!Ts;
161    static if (Size == ubyte.sizeof * 8)
162        alias StoreType = ubyte;
163    else static if (Size == ushort.sizeof * 8)
164        alias StoreType = ushort;
165    else static if (Size == uint.sizeof * 8)
166        alias StoreType = uint;
167    else static if (Size == ulong.sizeof * 8)
168        alias StoreType = ulong;
169    else
170    {
171        static assert(false, "Field widths must sum to 8, 16, 32, or 64");
172        alias StoreType = ulong; // just to avoid another error msg
173    }
174    enum result
175        = "private " ~ StoreType.stringof ~ " " ~ Name ~ ";"
176        ~ createFields!(Name, 0, Ts).result;
177}
178
179private template createFields(string store, size_t offset, Ts...)
180{
181    static if (Ts.length > 0)
182        enum result
183            = createAccessors!(store, Ts[0], Ts[1], Ts[2], offset).result
184            ~ createFields!(store, offset + Ts[2], Ts[3 .. $]).result;
185    else
186        enum result = "";
187}
188
189private ulong getBitsForAlign(ulong a)
190{
191    ulong bits = 0;
192    while ((a & 0x01) == 0)
193    {
194        bits++;
195        a >>= 1;
196    }
197
198    assert(a == 1, "alignment is not a power of 2");
199    return bits;
200}
201
202private template createReferenceAccessor(string store, T, ulong bits, string name)
203{
204    enum storage = "private void* " ~ store ~ "_ptr;\n";
205    enum storage_accessor = "@property ref size_t " ~ store ~ "() return @trusted pure nothrow @nogc const { "
206        ~ "return *cast(size_t*) &" ~ store ~ "_ptr;}\n"
207        ~ "@property void " ~ store ~ "(size_t v) @trusted pure nothrow @nogc { "
208        ~ "" ~ store ~ "_ptr = cast(void*) v;}\n";
209
210    enum mask = (1UL << bits) - 1;
211    // getter
212    enum ref_accessor = "@property "~T.stringof~" "~name~"() @trusted pure nothrow @nogc const { auto result = "
213        ~ "("~store~" & "~myToString(~mask)~"); "
214        ~ "return cast("~T.stringof~") cast(void*) result;}\n"
215    // setter
216        ~"@property void "~name~"("~T.stringof~" v) @trusted pure nothrow @nogc { "
217        ~"assert(((cast(typeof("~store~")) cast(void*) v) & "~myToString(mask)
218        ~`) == 0, "Value not properly aligned for '`~name~`'"); `
219        ~store~" = cast(typeof("~store~"))"
220        ~" (("~store~" & (cast(typeof("~store~")) "~myToString(mask)~"))"
221        ~" | ((cast(typeof("~store~")) cast(void*) v) & (cast(typeof("~store~")) "~myToString(~mask)~")));}\n";
222
223    enum result = storage ~ storage_accessor ~ ref_accessor;
224}
225
226private template sizeOfBitField(T...)
227{
228    static if (T.length < 2)
229        enum sizeOfBitField = 0;
230    else
231        enum sizeOfBitField = T[2] + sizeOfBitField!(T[3 .. $]);
232}
233
234private template createTaggedReference(T, ulong a, string name, Ts...)
235{
236    static assert(
237        sizeOfBitField!Ts <= getBitsForAlign(a),
238        "Fields must fit in the bits know to be zero because of alignment."
239    );
240    enum StoreName = createStoreName!(T, name, 0, Ts);
241    enum result
242        = createReferenceAccessor!(StoreName, T, sizeOfBitField!Ts, name).result
243        ~ createFields!(StoreName, 0, Ts, size_t, "", T.sizeof * 8 - sizeOfBitField!Ts).result;
244}
245
246/**
247Allows creating bit fields inside $(D_PARAM struct)s and $(D_PARAM
248class)es.
249
250Example:
251
252----
253struct A
254{
255    int a;
256    mixin(bitfields!(
257        uint, "x",    2,
258        int,  "y",    3,
259        uint, "z",    2,
260        bool, "flag", 1));
261}
262A obj;
263obj.x = 2;
264obj.z = obj.x;
265----
266
267The example above creates a bitfield pack of eight bits, which fit in
268one $(D_PARAM ubyte). The bitfields are allocated starting from the
269least significant bit, i.e. x occupies the two least significant bits
270of the bitfields storage.
271
272The sum of all bit lengths in one $(D_PARAM bitfield) instantiation
273must be exactly 8, 16, 32, or 64. If padding is needed, just allocate
274one bitfield with an empty name.
275
276Example:
277
278----
279struct A
280{
281    mixin(bitfields!(
282        bool, "flag1",    1,
283        bool, "flag2",    1,
284        uint, "",         6));
285}
286----
287
288The type of a bit field can be any integral type or enumerated
289type. The most efficient type to store in bitfields is $(D_PARAM
290bool), followed by unsigned types, followed by signed types.
291*/
292
293template bitfields(T...)
294{
295    enum { bitfields = createStorageAndFields!T.result }
296}
297
298/**
299This string mixin generator allows one to create tagged pointers inside $(D_PARAM struct)s and $(D_PARAM class)es.
300
301A tagged pointer uses the bits known to be zero in a normal pointer or class reference to store extra information.
302For example, a pointer to an integer must be 4-byte aligned, so there are 2 bits that are always known to be zero.
303One can store a 2-bit integer there.
304
305The example above creates a tagged pointer in the struct A. The pointer is of type
306$(D uint*) as specified by the first argument, and is named x, as specified by the second
307argument.
308
309Following arguments works the same way as $(D bitfield)'s. The bitfield must fit into the
310bits known to be zero because of the pointer alignment.
311*/
312
313template taggedPointer(T : T*, string name, Ts...) {
314    enum taggedPointer = createTaggedReference!(T*, T.alignof, name, Ts).result;
315}
316
317///
318@safe unittest
319{
320    struct A
321    {
322        int a;
323        mixin(taggedPointer!(
324            uint*, "x",
325            bool, "b1", 1,
326            bool, "b2", 1));
327    }
328    A obj;
329    obj.x = new uint;
330    obj.b1 = true;
331    obj.b2 = false;
332}
333
334/**
335This string mixin generator allows one to create tagged class reference inside $(D_PARAM struct)s and $(D_PARAM class)es.
336
337A tagged class reference uses the bits known to be zero in a normal class reference to store extra information.
338For example, a pointer to an integer must be 4-byte aligned, so there are 2 bits that are always known to be zero.
339One can store a 2-bit integer there.
340
341The example above creates a tagged reference to an Object in the struct A. This expects the same parameters
342as $(D taggedPointer), except the first argument which must be a class type instead of a pointer type.
343*/
344
345template taggedClassRef(T, string name, Ts...)
346if (is(T == class))
347{
348    enum taggedClassRef = createTaggedReference!(T, 8, name, Ts).result;
349}
350
351///
352@safe unittest
353{
354    struct A
355    {
356        int a;
357        mixin(taggedClassRef!(
358            Object, "o",
359            uint, "i", 2));
360    }
361    A obj;
362    obj.o = new Object();
363    obj.i = 3;
364}
365
366@safe pure nothrow @nogc
367unittest
368{
369    // Degenerate bitfields (#8474 / #11160) tests mixed with range tests
370    struct Test1
371    {
372        mixin(bitfields!(uint, "a", 32,
373                        uint, "b", 4,
374                        uint, "c", 4,
375                        uint, "d", 8,
376                        uint, "e", 16,));
377
378        static assert(Test1.b_min == 0);
379        static assert(Test1.b_max == 15);
380    }
381
382    struct Test2
383    {
384        mixin(bitfields!(bool, "a", 0,
385                        ulong, "b", 64));
386
387        static assert(Test2.b_min == ulong.min);
388        static assert(Test2.b_max == ulong.max);
389    }
390
391    struct Test1b
392    {
393        mixin(bitfields!(bool, "a", 0,
394                        int, "b", 8));
395    }
396
397    struct Test2b
398    {
399        mixin(bitfields!(int, "a", 32,
400                        int, "b", 4,
401                        int, "c", 4,
402                        int, "d", 8,
403                        int, "e", 16,));
404
405        static assert(Test2b.b_min == -8);
406        static assert(Test2b.b_max == 7);
407    }
408
409    struct Test3b
410    {
411        mixin(bitfields!(bool, "a", 0,
412                        long, "b", 64));
413
414        static assert(Test3b.b_min == long.min);
415        static assert(Test3b.b_max == long.max);
416    }
417
418    struct Test4b
419    {
420        mixin(bitfields!(long, "a", 32,
421                        int, "b", 32));
422    }
423
424    // Sign extension tests
425    Test2b t2b;
426    Test4b t4b;
427    t2b.b = -5; assert(t2b.b == -5);
428    t2b.d = -5; assert(t2b.d == -5);
429    t2b.e = -5; assert(t2b.e == -5);
430    t4b.a = -5; assert(t4b.a == -5L);
431}
432
433@system unittest
434{
435    struct Test5
436    {
437        mixin(taggedPointer!(
438            int*, "a",
439            uint, "b", 2));
440    }
441
442    Test5 t5;
443    t5.a = null;
444    t5.b = 3;
445    assert(t5.a is null);
446    assert(t5.b == 3);
447
448    int myint = 42;
449    t5.a = &myint;
450    assert(t5.a is &myint);
451    assert(t5.b == 3);
452
453    struct Test6
454    {
455        mixin(taggedClassRef!(
456            Object, "o",
457            bool, "b", 1));
458    }
459
460    Test6 t6;
461    t6.o = null;
462    t6.b = false;
463    assert(t6.o is null);
464    assert(t6.b == false);
465
466    auto o = new Object();
467    t6.o = o;
468    t6.b = true;
469    assert(t6.o is o);
470    assert(t6.b == true);
471}
472
473@safe unittest
474{
475    static assert(!__traits(compiles,
476        taggedPointer!(
477            int*, "a",
478            uint, "b", 3)));
479
480    static assert(!__traits(compiles,
481        taggedClassRef!(
482            Object, "a",
483            uint, "b", 4)));
484
485    struct S {
486        mixin(taggedClassRef!(
487            Object, "a",
488            bool, "b", 1));
489    }
490
491    const S s;
492    void bar(S s) {}
493
494    static assert(!__traits(compiles, bar(s)));
495}
496
497@safe unittest
498{
499    // Bug #6686
500    union  S {
501        ulong bits = ulong.max;
502        mixin (bitfields!(
503            ulong, "back",  31,
504            ulong, "front", 33)
505        );
506    }
507    S num;
508
509    num.bits = ulong.max;
510    num.back = 1;
511    assert(num.bits == 0xFFFF_FFFF_8000_0001uL);
512}
513
514@safe unittest
515{
516    // Bug #5942
517    struct S
518    {
519        mixin(bitfields!(
520            int, "a" , 32,
521            int, "b" , 32
522        ));
523    }
524
525    S data;
526    data.b = 42;
527    data.a = 1;
528    assert(data.b == 42);
529}
530
531@safe unittest
532{
533    struct Test
534    {
535        mixin(bitfields!(bool, "a", 1,
536                         uint, "b", 3,
537                         short, "c", 4));
538    }
539
540    @safe void test() pure nothrow
541    {
542        Test t;
543
544        t.a = true;
545        t.b = 5;
546        t.c = 2;
547
548        assert(t.a);
549        assert(t.b == 5);
550        assert(t.c == 2);
551    }
552
553    test();
554}
555
556@safe unittest
557{
558    {
559        static struct Integrals {
560            bool checkExpectations(bool eb, int ei, short es) { return b == eb && i == ei && s == es; }
561
562            mixin(bitfields!(
563                      bool, "b", 1,
564                      uint, "i", 3,
565                      short, "s", 4));
566        }
567        Integrals i;
568        assert(i.checkExpectations(false, 0, 0));
569        i.b = true;
570        assert(i.checkExpectations(true, 0, 0));
571        i.i = 7;
572        assert(i.checkExpectations(true, 7, 0));
573        i.s = -8;
574        assert(i.checkExpectations(true, 7, -8));
575        i.s = 7;
576        assert(i.checkExpectations(true, 7, 7));
577    }
578
579    //Bug# 8876
580    {
581        struct MoreIntegrals {
582            bool checkExpectations(uint eu, ushort es, uint ei) { return u == eu && s == es && i == ei; }
583
584            mixin(bitfields!(
585                  uint, "u", 24,
586                  short, "s", 16,
587                  int, "i", 24));
588        }
589
590        MoreIntegrals i;
591        assert(i.checkExpectations(0, 0, 0));
592        i.s = 20;
593        assert(i.checkExpectations(0, 20, 0));
594        i.i = 72;
595        assert(i.checkExpectations(0, 20, 72));
596        i.u = 8;
597        assert(i.checkExpectations(8, 20, 72));
598        i.s = 7;
599        assert(i.checkExpectations(8, 7, 72));
600    }
601
602    enum A { True, False }
603    enum B { One, Two, Three, Four }
604    static struct Enums {
605        bool checkExpectations(A ea, B eb) { return a == ea && b == eb; }
606
607        mixin(bitfields!(
608                  A, "a", 1,
609                  B, "b", 2,
610                  uint, "", 5));
611    }
612    Enums e;
613    assert(e.checkExpectations(A.True, B.One));
614    e.a = A.False;
615    assert(e.checkExpectations(A.False, B.One));
616    e.b = B.Three;
617    assert(e.checkExpectations(A.False, B.Three));
618
619    static struct SingleMember {
620        bool checkExpectations(bool eb) { return b == eb; }
621
622        mixin(bitfields!(
623                  bool, "b", 1,
624                  uint, "", 7));
625    }
626    SingleMember f;
627    assert(f.checkExpectations(false));
628    f.b = true;
629    assert(f.checkExpectations(true));
630}
631
632// Issue 12477
633@system unittest
634{
635    import core.exception : AssertError;
636    import std.algorithm.searching : canFind;
637    import std.bitmanip : bitfields;
638
639    static struct S
640    {
641        mixin(bitfields!(
642            uint, "a", 6,
643            int, "b", 2));
644    }
645
646    S s;
647
648    try { s.a = uint.max; assert(0); }
649    catch (AssertError ae)
650    { assert(ae.msg.canFind("Value is greater than the maximum value of bitfield 'a'"), ae.msg); }
651
652    try { s.b = int.min;  assert(0); }
653    catch (AssertError ae)
654    { assert(ae.msg.canFind("Value is smaller than the minimum value of bitfield 'b'"), ae.msg); }
655}
656
657/**
658   Allows manipulating the fraction, exponent, and sign parts of a
659   $(D_PARAM float) separately. The definition is:
660
661----
662struct FloatRep
663{
664    union
665    {
666        float value;
667        mixin(bitfields!(
668                  uint,  "fraction", 23,
669                  ubyte, "exponent",  8,
670                  bool,  "sign",      1));
671    }
672    enum uint bias = 127, fractionBits = 23, exponentBits = 8, signBits = 1;
673}
674----
675*/
676
677struct FloatRep
678{
679    union
680    {
681        float value;
682        mixin(bitfields!(
683                  uint,  "fraction", 23,
684                  ubyte, "exponent",  8,
685                  bool,  "sign",      1));
686    }
687    enum uint bias = 127, fractionBits = 23, exponentBits = 8, signBits = 1;
688}
689
690/**
691   Allows manipulating the fraction, exponent, and sign parts of a
692   $(D_PARAM double) separately. The definition is:
693
694----
695struct DoubleRep
696{
697    union
698    {
699        double value;
700        mixin(bitfields!(
701                  ulong,   "fraction", 52,
702                  ushort,  "exponent", 11,
703                  bool,    "sign",      1));
704    }
705    enum uint bias = 1023, signBits = 1, fractionBits = 52, exponentBits = 11;
706}
707----
708*/
709
710struct DoubleRep
711{
712    union
713    {
714        double value;
715        mixin(bitfields!(
716                  ulong,  "fraction", 52,
717                  ushort, "exponent", 11,
718                  bool,   "sign",      1));
719    }
720    enum uint bias = 1023, signBits = 1, fractionBits = 52, exponentBits = 11;
721}
722
723@safe unittest
724{
725    // test reading
726    DoubleRep x;
727    x.value = 1.0;
728    assert(x.fraction == 0 && x.exponent == 1023 && !x.sign);
729    x.value = -0.5;
730    assert(x.fraction == 0 && x.exponent == 1022 && x.sign);
731    x.value = 0.5;
732    assert(x.fraction == 0 && x.exponent == 1022 && !x.sign);
733
734    // test writing
735    x.fraction = 1125899906842624;
736    x.exponent = 1025;
737    x.sign = true;
738    assert(x.value == -5.0);
739
740    // test enums
741    enum ABC { A, B, C }
742    struct EnumTest
743    {
744        mixin(bitfields!(
745                  ABC, "x", 2,
746                  bool, "y", 1,
747                  ubyte, "z", 5));
748    }
749}
750
751@safe unittest
752{
753    // Issue #15305
754    struct S {
755            mixin(bitfields!(
756                    bool, "alice", 1,
757                    ulong, "bob", 63,
758            ));
759    }
760
761    S s;
762    s.bob = long.max - 1;
763    s.alice = false;
764    assert(s.bob == long.max - 1);
765}
766
767/**
768 * An array of bits.
769 */
770
771struct BitArray
772{
773private:
774
775    import core.bitop : bts, btr, bsf, bt;
776    import std.format : FormatSpec;
777
778    size_t _len;
779    size_t* _ptr;
780    enum bitsPerSizeT = size_t.sizeof * 8;
781
782    @property size_t fullWords() const @nogc pure nothrow
783    {
784        return _len / bitsPerSizeT;
785    }
786    // Number of bits after the last full word
787    @property size_t endBits() const @nogc pure nothrow
788    {
789        return _len % bitsPerSizeT;
790    }
791    // Bit mask to extract the bits after the last full word
792    @property size_t endMask() const @nogc pure nothrow
793    {
794        return (size_t(1) << endBits) - 1;
795    }
796    static size_t lenToDim(size_t len) @nogc pure nothrow @safe
797    {
798        return (len + (bitsPerSizeT-1)) / bitsPerSizeT;
799    }
800
801public:
802    /**********************************************
803     * Gets the amount of native words backing this $(D BitArray).
804     */
805    @property size_t dim() const @nogc pure nothrow @safe
806    {
807        return lenToDim(_len);
808    }
809
810    /**********************************************
811     * Gets the amount of bits in the $(D BitArray).
812     */
813    @property size_t length() const @nogc pure nothrow @safe
814    {
815        return _len;
816    }
817
818    /**********************************************
819     * Sets the amount of bits in the $(D BitArray).
820     * $(RED Warning: increasing length may overwrite bits in
821     * final word up to the next word boundary. i.e. D dynamic
822     * array extension semantics are not followed.)
823     */
824    @property size_t length(size_t newlen) pure nothrow @system
825    {
826        if (newlen != _len)
827        {
828            size_t olddim = dim;
829            immutable newdim = lenToDim(newlen);
830
831            if (newdim != olddim)
832            {
833                // Create a fake array so we can use D's realloc machinery
834                auto b = _ptr[0 .. olddim];
835                b.length = newdim;                // realloc
836                _ptr = b.ptr;
837            }
838
839            _len = newlen;
840        }
841        return _len;
842    }
843
844    /**********************************************
845     * Gets the $(D i)'th bit in the $(D BitArray).
846     */
847    bool opIndex(size_t i) const @nogc pure nothrow
848    in
849    {
850        assert(i < _len);
851    }
852    body
853    {
854        return cast(bool) bt(_ptr, i);
855    }
856
857    @system unittest
858    {
859        debug(bitarray) printf("BitArray.opIndex.unittest\n");
860
861        void Fun(const BitArray arr)
862        {
863            auto x = arr[0];
864            assert(x == 1);
865        }
866        BitArray a;
867        a.length = 3;
868        a[0] = 1;
869        Fun(a);
870    }
871
872    /**********************************************
873     * Sets the $(D i)'th bit in the $(D BitArray).
874     */
875    bool opIndexAssign(bool b, size_t i) @nogc pure nothrow
876    in
877    {
878        assert(i < _len);
879    }
880    body
881    {
882        if (b)
883            bts(_ptr, i);
884        else
885            btr(_ptr, i);
886        return b;
887    }
888
889    /**********************************************
890     * Duplicates the $(D BitArray) and its contents.
891     */
892    @property BitArray dup() const pure nothrow
893    {
894        BitArray ba;
895
896        auto b = _ptr[0 .. dim].dup;
897        ba._len = _len;
898        ba._ptr = b.ptr;
899        return ba;
900    }
901
902    @system unittest
903    {
904        BitArray a;
905        BitArray b;
906        int i;
907
908        debug(bitarray) printf("BitArray.dup.unittest\n");
909
910        a.length = 3;
911        a[0] = 1; a[1] = 0; a[2] = 1;
912        b = a.dup;
913        assert(b.length == 3);
914        for (i = 0; i < 3; i++)
915        {   debug(bitarray) printf("b[%d] = %d\n", i, b[i]);
916            assert(b[i] == (((i ^ 1) & 1) ? true : false));
917        }
918    }
919
920    /**********************************************
921     * Support for $(D foreach) loops for $(D BitArray).
922     */
923    int opApply(scope int delegate(ref bool) dg)
924    {
925        int result;
926
927        foreach (i; 0 .. _len)
928        {
929            bool b = opIndex(i);
930            result = dg(b);
931            this[i] = b;
932            if (result)
933                break;
934        }
935        return result;
936    }
937
938    /** ditto */
939    int opApply(scope int delegate(bool) dg) const
940    {
941        int result;
942
943        foreach (i; 0 .. _len)
944        {
945            immutable b = opIndex(i);
946            result = dg(b);
947            if (result)
948                break;
949        }
950        return result;
951    }
952
953    /** ditto */
954    int opApply(scope int delegate(size_t, ref bool) dg)
955    {
956        int result;
957
958        foreach (i; 0 .. _len)
959        {
960            bool b = opIndex(i);
961            result = dg(i, b);
962            this[i] = b;
963            if (result)
964                break;
965        }
966        return result;
967    }
968
969    /** ditto */
970    int opApply(scope int delegate(size_t, bool) dg) const
971    {
972        int result;
973
974        foreach (i; 0 .. _len)
975        {
976            immutable b = opIndex(i);
977            result = dg(i, b);
978            if (result)
979                break;
980        }
981        return result;
982    }
983
984    @system unittest
985    {
986        debug(bitarray) printf("BitArray.opApply unittest\n");
987
988        static bool[] ba = [1,0,1];
989
990        auto a = BitArray(ba);
991
992        int i;
993        foreach (b;a)
994        {
995            switch (i)
996            {
997                case 0: assert(b == true); break;
998                case 1: assert(b == false); break;
999                case 2: assert(b == true); break;
1000                default: assert(0);
1001            }
1002            i++;
1003        }
1004
1005        foreach (j,b;a)
1006        {
1007            switch (j)
1008            {
1009                case 0: assert(b == true); break;
1010                case 1: assert(b == false); break;
1011                case 2: assert(b == true); break;
1012                default: assert(0);
1013            }
1014        }
1015    }
1016
1017
1018    /**********************************************
1019     * Reverses the bits of the $(D BitArray).
1020     */
1021    @property BitArray reverse() @nogc pure nothrow
1022    out (result)
1023    {
1024        assert(result == this);
1025    }
1026    body
1027    {
1028        if (_len >= 2)
1029        {
1030            bool t;
1031            size_t lo, hi;
1032
1033            lo = 0;
1034            hi = _len - 1;
1035            for (; lo < hi; lo++, hi--)
1036            {
1037                t = this[lo];
1038                this[lo] = this[hi];
1039                this[hi] = t;
1040            }
1041        }
1042        return this;
1043    }
1044
1045    @system unittest
1046    {
1047        debug(bitarray) printf("BitArray.reverse.unittest\n");
1048
1049        BitArray b;
1050        static bool[5] data = [1,0,1,1,0];
1051        int i;
1052
1053        b = BitArray(data);
1054        b.reverse;
1055        for (i = 0; i < data.length; i++)
1056        {
1057            assert(b[i] == data[4 - i]);
1058        }
1059    }
1060
1061
1062    /**********************************************
1063     * Sorts the $(D BitArray)'s elements.
1064     */
1065    @property BitArray sort() @nogc pure nothrow
1066    out (result)
1067    {
1068        assert(result == this);
1069    }
1070    body
1071    {
1072        if (_len >= 2)
1073        {
1074            size_t lo, hi;
1075
1076            lo = 0;
1077            hi = _len - 1;
1078            while (1)
1079            {
1080                while (1)
1081                {
1082                    if (lo >= hi)
1083                        goto Ldone;
1084                    if (this[lo] == true)
1085                        break;
1086                    lo++;
1087                }
1088
1089                while (1)
1090                {
1091                    if (lo >= hi)
1092                        goto Ldone;
1093                    if (this[hi] == false)
1094                        break;
1095                    hi--;
1096                }
1097
1098                this[lo] = false;
1099                this[hi] = true;
1100
1101                lo++;
1102                hi--;
1103            }
1104        }
1105    Ldone:
1106        return this;
1107    }
1108
1109    @system unittest
1110    {
1111        debug(bitarray) printf("BitArray.sort.unittest\n");
1112
1113        __gshared size_t x = 0b1100011000;
1114        __gshared ba = BitArray(10, &x);
1115        ba.sort;
1116        for (size_t i = 0; i < 6; i++)
1117            assert(ba[i] == false);
1118        for (size_t i = 6; i < 10; i++)
1119            assert(ba[i] == true);
1120    }
1121
1122
1123    /***************************************
1124     * Support for operators == and != for $(D BitArray).
1125     */
1126    bool opEquals(const ref BitArray a2) const @nogc pure nothrow
1127    {
1128        if (this.length != a2.length)
1129            return false;
1130        auto p1 = this._ptr;
1131        auto p2 = a2._ptr;
1132
1133        if (p1[0 .. fullWords] != p2[0 .. fullWords])
1134            return false;
1135
1136        if (!endBits)
1137            return true;
1138
1139        auto i = fullWords;
1140        return (p1[i] & endMask) == (p2[i] & endMask);
1141    }
1142
1143    @system unittest
1144    {
1145        debug(bitarray) printf("BitArray.opEquals unittest\n");
1146
1147        static bool[] ba = [1,0,1,0,1];
1148        static bool[] bb = [1,0,1];
1149        static bool[] bc = [1,0,1,0,1,0,1];
1150        static bool[] bd = [1,0,1,1,1];
1151        static bool[] be = [1,0,1,0,1];
1152        static 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];
1153        static 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];
1154
1155        auto a = BitArray(ba);
1156        auto b = BitArray(bb);
1157        auto c = BitArray(bc);
1158        auto d = BitArray(bd);
1159        auto e = BitArray(be);
1160        auto f = BitArray(bf);
1161        auto g = BitArray(bg);
1162
1163        assert(a != b);
1164        assert(a != c);
1165        assert(a != d);
1166        assert(a == e);
1167        assert(f != g);
1168    }
1169
1170    /***************************************
1171     * Supports comparison operators for $(D BitArray).
1172     */
1173    int opCmp(BitArray a2) const @nogc pure nothrow
1174    {
1175        const lesser = this.length < a2.length ? &this : &a2;
1176        immutable fullWords = lesser.fullWords;
1177        immutable endBits = lesser.endBits;
1178        auto p1 = this._ptr;
1179        auto p2 = a2._ptr;
1180
1181        foreach (i; 0 .. fullWords)
1182        {
1183            if (p1[i] != p2[i])
1184            {
1185                return p1[i] & (size_t(1) << bsf(p1[i] ^ p2[i])) ? 1 : -1;
1186            }
1187        }
1188
1189        if (endBits)
1190        {
1191            immutable i = fullWords;
1192            immutable diff = p1[i] ^ p2[i];
1193            if (diff)
1194            {
1195                immutable index = bsf(diff);
1196                if (index < endBits)
1197                {
1198                    return p1[i] & (size_t(1) << index) ? 1 : -1;
1199                }
1200            }
1201        }
1202
1203        // Standard:
1204        // A bool value can be implicitly converted to any integral type,
1205        // with false becoming 0 and true becoming 1
1206        return (this.length > a2.length) - (this.length < a2.length);
1207    }
1208
1209    @system unittest
1210    {
1211        debug(bitarray) printf("BitArray.opCmp unittest\n");
1212
1213        static bool[] ba = [1,0,1,0,1];
1214        static bool[] bb = [1,0,1];
1215        static bool[] bc = [1,0,1,0,1,0,1];
1216        static bool[] bd = [1,0,1,1,1];
1217        static bool[] be = [1,0,1,0,1];
1218        static 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];
1219        static 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];
1220
1221        auto a = BitArray(ba);
1222        auto b = BitArray(bb);
1223        auto c = BitArray(bc);
1224        auto d = BitArray(bd);
1225        auto e = BitArray(be);
1226        auto f = BitArray(bf);
1227        auto g = BitArray(bg);
1228
1229        assert(a >  b);
1230        assert(a >= b);
1231        assert(a <  c);
1232        assert(a <= c);
1233        assert(a <  d);
1234        assert(a <= d);
1235        assert(a == e);
1236        assert(a <= e);
1237        assert(a >= e);
1238        assert(f <  g);
1239        assert(g <= g);
1240
1241        bool[] v;
1242        foreach  (i; 1 .. 256)
1243        {
1244            v.length = i;
1245            v[] = false;
1246            auto x = BitArray(v);
1247            v[i-1] = true;
1248            auto y = BitArray(v);
1249            assert(x < y);
1250            assert(x <= y);
1251        }
1252
1253        BitArray a1, a2;
1254
1255        for (size_t len = 4; len <= 256; len <<= 1)
1256        {
1257            a1.length = a2.length = len;
1258            a1[len-2] = a2[len-1] = true;
1259            assert(a1 > a2);
1260            a1[len-2] = a2[len-1] = false;
1261        }
1262
1263        foreach (j; 1 .. a1.length)
1264        {
1265            a1[j-1] = a2[j] = true;
1266            assert(a1 > a2);
1267            a1[j-1] = a2[j] = false;
1268        }
1269    }
1270
1271    /***************************************
1272     * Support for hashing for $(D BitArray).
1273     */
1274    size_t toHash() const @nogc pure nothrow
1275    {
1276        size_t hash = 3557;
1277        auto fullBytes = _len / 8;
1278        foreach (i; 0 .. fullBytes)
1279        {
1280            hash *= 3559;
1281            hash += (cast(byte*) this._ptr)[i];
1282        }
1283        foreach (i; 8*fullBytes .. _len)
1284        {
1285            hash *= 3571;
1286            hash += this[i];
1287        }
1288        return hash;
1289    }
1290
1291    /***************************************
1292     * Set this $(D BitArray) to the contents of $(D ba).
1293     */
1294    this(bool[] ba) pure nothrow @system
1295    {
1296        length = ba.length;
1297        foreach (i, b; ba)
1298        {
1299            this[i] = b;
1300        }
1301    }
1302
1303    // Deliberately undocumented: raw initialization of bit array.
1304    this(size_t len, size_t* ptr)
1305    {
1306        _len = len;
1307        _ptr = ptr;
1308    }
1309
1310    /***************************************
1311     * Map the $(D BitArray) onto $(D v), with $(D numbits) being the number of bits
1312     * in the array. Does not copy the data. $(D v.length) must be a multiple of
1313     * $(D size_t.sizeof). If there are unmapped bits in the final mapped word then
1314     * these will be set to 0.
1315     *
1316     * This is the inverse of $(D opCast).
1317     */
1318    this(void[] v, size_t numbits) pure nothrow
1319    in
1320    {
1321        assert(numbits <= v.length * 8);
1322        assert(v.length % size_t.sizeof == 0);
1323    }
1324    body
1325    {
1326        _ptr = cast(size_t*) v.ptr;
1327        _len = numbits;
1328        if (endBits)
1329        {
1330            // Need to mask away extraneous bits from v.
1331            _ptr[dim - 1] &= endMask;
1332        }
1333    }
1334
1335    @system unittest
1336    {
1337        debug(bitarray) printf("BitArray.init unittest\n");
1338
1339        static bool[] ba = [1,0,1,0,1];
1340
1341        auto a = BitArray(ba);
1342        void[] v;
1343
1344        v = cast(void[]) a;
1345        auto b = BitArray(v, a.length);
1346
1347        assert(b[0] == 1);
1348        assert(b[1] == 0);
1349        assert(b[2] == 1);
1350        assert(b[3] == 0);
1351        assert(b[4] == 1);
1352
1353        a[0] = 0;
1354        assert(b[0] == 0);
1355
1356        assert(a == b);
1357    }
1358
1359    /***************************************
1360     * Convert to $(D void[]).
1361     */
1362    void[] opCast(T : void[])() @nogc pure nothrow
1363    {
1364        return cast(void[])_ptr[0 .. dim];
1365    }
1366
1367    /***************************************
1368     * Convert to $(D size_t[]).
1369     */
1370    size_t[] opCast(T : size_t[])() @nogc pure nothrow
1371    {
1372        return _ptr[0 .. dim];
1373    }
1374
1375    @system unittest
1376    {
1377        debug(bitarray) printf("BitArray.opCast unittest\n");
1378
1379        static bool[] ba = [1,0,1,0,1];
1380
1381        auto a = BitArray(ba);
1382        void[] v = cast(void[]) a;
1383
1384        assert(v.length == a.dim * size_t.sizeof);
1385    }
1386
1387    /***************************************
1388     * Support for unary operator ~ for $(D BitArray).
1389     */
1390    BitArray opCom() const pure nothrow
1391    {
1392        auto dim = this.dim;
1393
1394        BitArray result;
1395        result.length = _len;
1396
1397        result._ptr[0 .. dim] = ~this._ptr[0 .. dim];
1398
1399        // Avoid putting garbage in extra bits
1400        // Remove once we zero on length extension
1401        if (endBits)
1402            result._ptr[dim - 1] &= endMask;
1403
1404        return result;
1405    }
1406
1407    @system unittest
1408    {
1409        debug(bitarray) printf("BitArray.opCom unittest\n");
1410
1411        static bool[] ba = [1,0,1,0,1];
1412
1413        auto a = BitArray(ba);
1414        BitArray b = ~a;
1415
1416        assert(b[0] == 0);
1417        assert(b[1] == 1);
1418        assert(b[2] == 0);
1419        assert(b[3] == 1);
1420        assert(b[4] == 0);
1421    }
1422
1423
1424    /***************************************
1425     * Support for binary bitwise operators for $(D BitArray).
1426     */
1427    BitArray opBinary(string op)(const BitArray e2) const pure nothrow
1428        if (op == "-" || op == "&" || op == "|" || op == "^")
1429    in
1430    {
1431        assert(_len == e2.length);
1432    }
1433    body
1434    {
1435        auto dim = this.dim;
1436
1437        BitArray result;
1438        result.length = _len;
1439
1440        static if (op == "-")
1441            result._ptr[0 .. dim] = this._ptr[0 .. dim] & ~e2._ptr[0 .. dim];
1442        else
1443            mixin("result._ptr[0 .. dim] = this._ptr[0 .. dim]"~op~" e2._ptr[0 .. dim];");
1444
1445        // Avoid putting garbage in extra bits
1446        // Remove once we zero on length extension
1447        if (endBits)
1448            result._ptr[dim - 1] &= endMask;
1449
1450        return result;
1451    }
1452
1453    @system unittest
1454    {
1455        debug(bitarray) printf("BitArray.opAnd unittest\n");
1456
1457        static bool[] ba = [1,0,1,0,1];
1458        static bool[] bb = [1,0,1,1,0];
1459
1460        auto a = BitArray(ba);
1461        auto b = BitArray(bb);
1462
1463        BitArray c = a & b;
1464
1465        assert(c[0] == 1);
1466        assert(c[1] == 0);
1467        assert(c[2] == 1);
1468        assert(c[3] == 0);
1469        assert(c[4] == 0);
1470    }
1471
1472    @system unittest
1473    {
1474        debug(bitarray) printf("BitArray.opOr unittest\n");
1475
1476        static bool[] ba = [1,0,1,0,1];
1477        static bool[] bb = [1,0,1,1,0];
1478
1479        auto a = BitArray(ba);
1480        auto b = BitArray(bb);
1481
1482        BitArray c = a | b;
1483
1484        assert(c[0] == 1);
1485        assert(c[1] == 0);
1486        assert(c[2] == 1);
1487        assert(c[3] == 1);
1488        assert(c[4] == 1);
1489    }
1490
1491    @system unittest
1492    {
1493        debug(bitarray) printf("BitArray.opXor unittest\n");
1494
1495        static bool[] ba = [1,0,1,0,1];
1496        static bool[] bb = [1,0,1,1,0];
1497
1498        auto a = BitArray(ba);
1499        auto b = BitArray(bb);
1500
1501        BitArray c = a ^ b;
1502
1503        assert(c[0] == 0);
1504        assert(c[1] == 0);
1505        assert(c[2] == 0);
1506        assert(c[3] == 1);
1507        assert(c[4] == 1);
1508    }
1509
1510    @system unittest
1511    {
1512        debug(bitarray) printf("BitArray.opSub unittest\n");
1513
1514        static bool[] ba = [1,0,1,0,1];
1515        static bool[] bb = [1,0,1,1,0];
1516
1517        auto a = BitArray(ba);
1518        auto b = BitArray(bb);
1519
1520        BitArray c = a - b;
1521
1522        assert(c[0] == 0);
1523        assert(c[1] == 0);
1524        assert(c[2] == 0);
1525        assert(c[3] == 0);
1526        assert(c[4] == 1);
1527    }
1528
1529
1530    /***************************************
1531     * Support for operator op= for $(D BitArray).
1532     */
1533    BitArray opOpAssign(string op)(const BitArray e2) @nogc pure nothrow
1534        if (op == "-" || op == "&" || op == "|" || op == "^")
1535    in
1536    {
1537        assert(_len == e2.length);
1538    }
1539    body
1540    {
1541        foreach (i; 0 .. fullWords)
1542        {
1543            static if (op == "-")
1544                _ptr[i] &= ~e2._ptr[i];
1545            else
1546                mixin("_ptr[i] "~op~"= e2._ptr[i];");
1547        }
1548        if (!endBits)
1549            return this;
1550
1551        size_t i = fullWords;
1552        size_t endWord = _ptr[i];
1553        static if (op == "-")
1554            endWord &= ~e2._ptr[i];
1555        else
1556            mixin("endWord "~op~"= e2._ptr[i];");
1557        _ptr[i] = (_ptr[i] & ~endMask) | (endWord & endMask);
1558
1559        return this;
1560    }
1561
1562    @system unittest
1563    {
1564        static bool[] ba = [1,0,1,0,1,1,0,1,0,1];
1565        static bool[] bb = [1,0,1,1,0];
1566        auto a = BitArray(ba);
1567        auto b = BitArray(bb);
1568        BitArray c = a;
1569        c.length = 5;
1570        c &= b;
1571        assert(a[5] == 1);
1572        assert(a[6] == 0);
1573        assert(a[7] == 1);
1574        assert(a[8] == 0);
1575        assert(a[9] == 1);
1576    }
1577
1578    @system unittest
1579    {
1580        debug(bitarray) printf("BitArray.opAndAssign unittest\n");
1581
1582        static bool[] ba = [1,0,1,0,1];
1583        static bool[] bb = [1,0,1,1,0];
1584
1585        auto a = BitArray(ba);
1586        auto b = BitArray(bb);
1587
1588        a &= b;
1589        assert(a[0] == 1);
1590        assert(a[1] == 0);
1591        assert(a[2] == 1);
1592        assert(a[3] == 0);
1593        assert(a[4] == 0);
1594    }
1595
1596    @system unittest
1597    {
1598        debug(bitarray) printf("BitArray.opOrAssign unittest\n");
1599
1600        static bool[] ba = [1,0,1,0,1];
1601        static bool[] bb = [1,0,1,1,0];
1602
1603        auto a = BitArray(ba);
1604        auto b = BitArray(bb);
1605
1606        a |= b;
1607        assert(a[0] == 1);
1608        assert(a[1] == 0);
1609        assert(a[2] == 1);
1610        assert(a[3] == 1);
1611        assert(a[4] == 1);
1612    }
1613
1614    @system unittest
1615    {
1616        debug(bitarray) printf("BitArray.opXorAssign unittest\n");
1617
1618        static bool[] ba = [1,0,1,0,1];
1619        static bool[] bb = [1,0,1,1,0];
1620
1621        auto a = BitArray(ba);
1622        auto b = BitArray(bb);
1623
1624        a ^= b;
1625        assert(a[0] == 0);
1626        assert(a[1] == 0);
1627        assert(a[2] == 0);
1628        assert(a[3] == 1);
1629        assert(a[4] == 1);
1630    }
1631
1632    @system unittest
1633    {
1634        debug(bitarray) printf("BitArray.opSubAssign unittest\n");
1635
1636        static bool[] ba = [1,0,1,0,1];
1637        static bool[] bb = [1,0,1,1,0];
1638
1639        auto a = BitArray(ba);
1640        auto b = BitArray(bb);
1641
1642        a -= b;
1643        assert(a[0] == 0);
1644        assert(a[1] == 0);
1645        assert(a[2] == 0);
1646        assert(a[3] == 0);
1647        assert(a[4] == 1);
1648    }
1649
1650    /***************************************
1651     * Support for operator ~= for $(D BitArray).
1652     * $(RED Warning: This will overwrite a bit in the final word
1653     * of the current underlying data regardless of whether it is
1654     * shared between BitArray objects. i.e. D dynamic array
1655     * concatenation semantics are not followed)
1656     */
1657
1658    BitArray opCatAssign(bool b) pure nothrow
1659    {
1660        length = _len + 1;
1661        this[_len - 1] = b;
1662        return this;
1663    }
1664
1665    @system unittest
1666    {
1667        debug(bitarray) printf("BitArray.opCatAssign unittest\n");
1668
1669        static bool[] ba = [1,0,1,0,1];
1670
1671        auto a = BitArray(ba);
1672        BitArray b;
1673
1674        b = (a ~= true);
1675        assert(a[0] == 1);
1676        assert(a[1] == 0);
1677        assert(a[2] == 1);
1678        assert(a[3] == 0);
1679        assert(a[4] == 1);
1680        assert(a[5] == 1);
1681
1682        assert(b == a);
1683    }
1684
1685    /***************************************
1686     * ditto
1687     */
1688
1689    BitArray opCatAssign(BitArray b) pure nothrow
1690    {
1691        auto istart = _len;
1692        length = _len + b.length;
1693        for (auto i = istart; i < _len; i++)
1694            this[i] = b[i - istart];
1695        return this;
1696    }
1697
1698    @system unittest
1699    {
1700        debug(bitarray) printf("BitArray.opCatAssign unittest\n");
1701
1702        static bool[] ba = [1,0];
1703        static bool[] bb = [0,1,0];
1704
1705        auto a = BitArray(ba);
1706        auto b = BitArray(bb);
1707        BitArray c;
1708
1709        c = (a ~= b);
1710        assert(a.length == 5);
1711        assert(a[0] == 1);
1712        assert(a[1] == 0);
1713        assert(a[2] == 0);
1714        assert(a[3] == 1);
1715        assert(a[4] == 0);
1716
1717        assert(c == a);
1718    }
1719
1720    /***************************************
1721     * Support for binary operator ~ for $(D BitArray).
1722     */
1723    BitArray opCat(bool b) const pure nothrow
1724    {
1725        BitArray r;
1726
1727        r = this.dup;
1728        r.length = _len + 1;
1729        r[_len] = b;
1730        return r;
1731    }
1732
1733    /** ditto */
1734    BitArray opCat_r(bool b) const pure nothrow
1735    {
1736        BitArray r;
1737
1738        r.length = _len + 1;
1739        r[0] = b;
1740        foreach (i; 0 .. _len)
1741            r[1 + i] = this[i];
1742        return r;
1743    }
1744
1745    /** ditto */
1746    BitArray opCat(BitArray b) const pure nothrow
1747    {
1748        BitArray r;
1749
1750        r = this.dup;
1751        r ~= b;
1752        return r;
1753    }
1754
1755    @system unittest
1756    {
1757        debug(bitarray) printf("BitArray.opCat unittest\n");
1758
1759        static bool[] ba = [1,0];
1760        static bool[] bb = [0,1,0];
1761
1762        auto a = BitArray(ba);
1763        auto b = BitArray(bb);
1764        BitArray c;
1765
1766        c = (a ~ b);
1767        assert(c.length == 5);
1768        assert(c[0] == 1);
1769        assert(c[1] == 0);
1770        assert(c[2] == 0);
1771        assert(c[3] == 1);
1772        assert(c[4] == 0);
1773
1774        c = (a ~ true);
1775        assert(c.length == 3);
1776        assert(c[0] == 1);
1777        assert(c[1] == 0);
1778        assert(c[2] == 1);
1779
1780        c = (false ~ a);
1781        assert(c.length == 3);
1782        assert(c[0] == 0);
1783        assert(c[1] == 1);
1784        assert(c[2] == 0);
1785    }
1786
1787    // Rolls double word (upper, lower) to the right by n bits and returns the
1788    // lower word of the result.
1789    private static size_t rollRight()(size_t upper, size_t lower, size_t nbits)
1790        pure @safe nothrow @nogc
1791    in
1792    {
1793        assert(nbits < bitsPerSizeT);
1794    }
1795    body
1796    {
1797        return (upper << (bitsPerSizeT - nbits)) | (lower >> nbits);
1798    }
1799
1800    @safe unittest
1801    {
1802        static if (size_t.sizeof == 8)
1803        {
1804            size_t x = 0x12345678_90ABCDEF;
1805            size_t y = 0xFEDBCA09_87654321;
1806
1807            assert(rollRight(x, y, 32) == 0x90ABCDEF_FEDBCA09);
1808            assert(rollRight(y, x, 4) == 0x11234567_890ABCDE);
1809        }
1810        else static if (size_t.sizeof == 4)
1811        {
1812            size_t x = 0x12345678;
1813            size_t y = 0x90ABCDEF;
1814
1815            assert(rollRight(x, y, 16) == 0x567890AB);
1816            assert(rollRight(y, x, 4) == 0xF1234567);
1817        }
1818        else
1819            static assert(0, "Unsupported size_t width");
1820    }
1821
1822    // Rolls double word (upper, lower) to the left by n bits and returns the
1823    // upper word of the result.
1824    private static size_t rollLeft()(size_t upper, size_t lower, size_t nbits)
1825        pure @safe nothrow @nogc
1826    in
1827    {
1828        assert(nbits < bitsPerSizeT);
1829    }
1830    body
1831    {
1832        return (upper << nbits) | (lower >> (bitsPerSizeT - nbits));
1833    }
1834
1835    @safe unittest
1836    {
1837        static if (size_t.sizeof == 8)
1838        {
1839            size_t x = 0x12345678_90ABCDEF;
1840            size_t y = 0xFEDBCA09_87654321;
1841
1842            assert(rollLeft(x, y, 32) == 0x90ABCDEF_FEDBCA09);
1843            assert(rollLeft(y, x, 4) == 0xEDBCA098_76543211);
1844        }
1845        else static if (size_t.sizeof == 4)
1846        {
1847            size_t x = 0x12345678;
1848            size_t y = 0x90ABCDEF;
1849
1850            assert(rollLeft(x, y, 16) == 0x567890AB);
1851            assert(rollLeft(y, x, 4) == 0x0ABCDEF1);
1852        }
1853    }
1854
1855    /**
1856     * Operator $(D <<=) support.
1857     *
1858     * Shifts all the bits in the array to the left by the given number of
1859     * bits.  The leftmost bits are dropped, and 0's are appended to the end
1860     * to fill up the vacant bits.
1861     *
1862     * $(RED Warning: unused bits in the final word up to the next word
1863     * boundary may be overwritten by this operation. It does not attempt to
1864     * preserve bits past the end of the array.)
1865     */
1866    void opOpAssign(string op)(size_t nbits) @nogc pure nothrow
1867        if (op == "<<")
1868    {
1869        size_t wordsToShift = nbits / bitsPerSizeT;
1870        size_t bitsToShift = nbits % bitsPerSizeT;
1871
1872        if (wordsToShift < dim)
1873        {
1874            foreach_reverse (i; 1 .. dim - wordsToShift)
1875            {
1876                _ptr[i + wordsToShift] = rollLeft(_ptr[i], _ptr[i-1],
1877                                                 bitsToShift);
1878            }
1879            _ptr[wordsToShift] = rollLeft(_ptr[0], 0, bitsToShift);
1880        }
1881
1882        import std.algorithm.comparison : min;
1883        foreach (i; 0 .. min(wordsToShift, dim))
1884        {
1885            _ptr[i] = 0;
1886        }
1887    }
1888
1889    /**
1890     * Operator $(D >>=) support.
1891     *
1892     * Shifts all the bits in the array to the right by the given number of
1893     * bits.  The rightmost bits are dropped, and 0's are inserted at the back
1894     * to fill up the vacant bits.
1895     *
1896     * $(RED Warning: unused bits in the final word up to the next word
1897     * boundary may be overwritten by this operation. It does not attempt to
1898     * preserve bits past the end of the array.)
1899     */
1900    void opOpAssign(string op)(size_t nbits) @nogc pure nothrow
1901        if (op == ">>")
1902    {
1903        size_t wordsToShift = nbits / bitsPerSizeT;
1904        size_t bitsToShift = nbits % bitsPerSizeT;
1905
1906        if (wordsToShift + 1 < dim)
1907        {
1908            foreach (i; 0 .. dim - wordsToShift - 1)
1909            {
1910                _ptr[i] = rollRight(_ptr[i + wordsToShift + 1],
1911                                   _ptr[i + wordsToShift], bitsToShift);
1912            }
1913        }
1914
1915        // The last word needs some care, as it must shift in 0's from past the
1916        // end of the array.
1917        if (wordsToShift < dim)
1918        {
1919            _ptr[dim - wordsToShift - 1] = rollRight(0, _ptr[dim - 1] & endMask,
1920                                                    bitsToShift);
1921        }
1922
1923        import std.algorithm.comparison : min;
1924        foreach (i; 0 .. min(wordsToShift, dim))
1925        {
1926            _ptr[dim - i - 1] = 0;
1927        }
1928    }
1929
1930    @system unittest
1931    {
1932        import std.format : format;
1933
1934        auto b = BitArray([1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1]);
1935
1936        b <<= 1;
1937        assert(format("%b", b) == "01100_10101101");
1938
1939        b >>= 1;
1940        assert(format("%b", b) == "11001_01011010");
1941
1942        b <<= 4;
1943        assert(format("%b", b) == "00001_10010101");
1944
1945        b >>= 5;
1946        assert(format("%b", b) == "10010_10100000");
1947
1948        b <<= 13;
1949        assert(format("%b", b) == "00000_00000000");
1950
1951        b = BitArray([1, 0, 1, 1, 0, 1, 1, 1]);
1952        b >>= 8;
1953        assert(format("%b", b) == "00000000");
1954
1955    }
1956
1957    // Test multi-word case
1958    @system unittest
1959    {
1960        import std.format : format;
1961
1962        // This has to be long enough to occupy more than one size_t. On 64-bit
1963        // machines, this would be at least 64 bits.
1964        auto b = BitArray([
1965            1, 0, 0, 0, 0, 0, 0, 0,  1, 1, 0, 0, 0, 0, 0, 0,
1966            1, 1, 1, 0, 0, 0, 0, 0,  1, 1, 1, 1, 0, 0, 0, 0,
1967            1, 1, 1, 1, 1, 0, 0, 0,  1, 1, 1, 1, 1, 1, 0, 0,
1968            1, 1, 1, 1, 1, 1, 1, 0,  1, 1, 1, 1, 1, 1, 1, 1,
1969            1, 0, 1, 0, 1, 0, 1, 0,  0, 1, 0, 1, 0, 1, 0, 1,
1970        ]);
1971        b <<= 8;
1972        assert(format("%b", b) ==
1973               "00000000_10000000_"~
1974               "11000000_11100000_"~
1975               "11110000_11111000_"~
1976               "11111100_11111110_"~
1977               "11111111_10101010");
1978
1979        // Test right shift of more than one size_t's worth of bits
1980        b <<= 68;
1981        assert(format("%b", b) ==
1982               "00000000_00000000_"~
1983               "00000000_00000000_"~
1984               "00000000_00000000_"~
1985               "00000000_00000000_"~
1986               "00000000_00001000");
1987
1988        b = BitArray([
1989            1, 0, 0, 0, 0, 0, 0, 0,  1, 1, 0, 0, 0, 0, 0, 0,
1990            1, 1, 1, 0, 0, 0, 0, 0,  1, 1, 1, 1, 0, 0, 0, 0,
1991            1, 1, 1, 1, 1, 0, 0, 0,  1, 1, 1, 1, 1, 1, 0, 0,
1992            1, 1, 1, 1, 1, 1, 1, 0,  1, 1, 1, 1, 1, 1, 1, 1,
1993            1, 0, 1, 0, 1, 0, 1, 0,  0, 1, 0, 1, 0, 1, 0, 1,
1994        ]);
1995        b >>= 8;
1996        assert(format("%b", b) ==
1997               "11000000_11100000_"~
1998               "11110000_11111000_"~
1999               "11111100_11111110_"~
2000               "11111111_10101010_"~
2001               "01010101_00000000");
2002
2003        // Test left shift of more than 1 size_t's worth of bits
2004        b >>= 68;
2005        assert(format("%b", b) ==
2006               "01010000_00000000_"~
2007               "00000000_00000000_"~
2008               "00000000_00000000_"~
2009               "00000000_00000000_"~
2010               "00000000_00000000");
2011    }
2012
2013    /***************************************
2014     * Return a string representation of this BitArray.
2015     *
2016     * Two format specifiers are supported:
2017     * $(LI $(B %s) which prints the bits as an array, and)
2018     * $(LI $(B %b) which prints the bits as 8-bit byte packets)
2019     * separated with an underscore.
2020     */
2021    void toString(scope void delegate(const(char)[]) sink,
2022                  FormatSpec!char fmt) const
2023    {
2024        switch (fmt.spec)
2025        {
2026            case 'b':
2027                return formatBitString(sink);
2028            case 's':
2029                return formatBitArray(sink);
2030            default:
2031                throw new Exception("Unknown format specifier: %" ~ fmt.spec);
2032        }
2033    }
2034
2035    ///
2036    @system unittest
2037    {
2038        import std.format : format;
2039
2040        debug(bitarray) printf("BitArray.toString unittest\n");
2041        auto b = BitArray([0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1]);
2042
2043        auto s1 = format("%s", b);
2044        assert(s1 == "[0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1]");
2045
2046        auto s2 = format("%b", b);
2047        assert(s2 == "00001111_00001111");
2048    }
2049
2050    /***************************************
2051     * Return a lazy range of the indices of set bits.
2052     */
2053    @property auto bitsSet() const nothrow
2054    {
2055        import std.algorithm.iteration : filter, map, joiner;
2056        import std.range : iota;
2057
2058        return iota(dim).
2059               filter!(i => _ptr[i])().
2060               map!(i => BitsSet!size_t(_ptr[i], i * bitsPerSizeT))().
2061               joiner();
2062    }
2063
2064    ///
2065    @system unittest
2066    {
2067        import std.algorithm.comparison : equal;
2068
2069        auto b1 = BitArray([0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1]);
2070        assert(b1.bitsSet.equal([4, 5, 6, 7, 12, 13, 14, 15]));
2071
2072        BitArray b2;
2073        b2.length = 1000;
2074        b2[333] = true;
2075        b2[666] = true;
2076        b2[999] = true;
2077        assert(b2.bitsSet.equal([333, 666, 999]));
2078    }
2079
2080    @system unittest
2081    {
2082        import std.algorithm.comparison : equal;
2083        import std.range : iota;
2084
2085        debug(bitarray) printf("BitArray.bitsSet unittest\n");
2086        BitArray b;
2087        enum wordBits = size_t.sizeof * 8;
2088        b = BitArray([size_t.max], 0);
2089        assert(b.bitsSet.empty);
2090        b = BitArray([size_t.max], 1);
2091        assert(b.bitsSet.equal([0]));
2092        b = BitArray([size_t.max], wordBits);
2093        assert(b.bitsSet.equal(iota(wordBits)));
2094        b = BitArray([size_t.max, size_t.max], wordBits);
2095        assert(b.bitsSet.equal(iota(wordBits)));
2096        b = BitArray([size_t.max, size_t.max], wordBits + 1);
2097        assert(b.bitsSet.equal(iota(wordBits + 1)));
2098        b = BitArray([size_t.max, size_t.max], wordBits * 2);
2099        assert(b.bitsSet.equal(iota(wordBits * 2)));
2100    }
2101
2102    private void formatBitString(scope void delegate(const(char)[]) sink) const
2103    {
2104        if (!length)
2105            return;
2106
2107        auto leftover = _len % 8;
2108        foreach (idx; 0 .. leftover)
2109        {
2110            char[1] res = cast(char)(this[idx] + '0');
2111            sink.put(res[]);
2112        }
2113
2114        if (leftover && _len > 8)
2115            sink.put("_");
2116
2117        size_t count;
2118        foreach (idx; leftover .. _len)
2119        {
2120            char[1] res = cast(char)(this[idx] + '0');
2121            sink.put(res[]);
2122            if (++count == 8 && idx != _len - 1)
2123            {
2124                sink.put("_");
2125                count = 0;
2126            }
2127        }
2128    }
2129
2130    private void formatBitArray(scope void delegate(const(char)[]) sink) const
2131    {
2132        sink("[");
2133        foreach (idx; 0 .. _len)
2134        {
2135            char[1] res = cast(char)(this[idx] + '0');
2136            sink(res[]);
2137            if (idx+1 < _len)
2138                sink(", ");
2139        }
2140        sink("]");
2141    }
2142}
2143
2144@system unittest
2145{
2146    import std.format : format;
2147
2148    BitArray b;
2149
2150    b = BitArray([]);
2151    assert(format("%s", b) == "[]");
2152    assert(format("%b", b) is null);
2153
2154    b = BitArray([1]);
2155    assert(format("%s", b) == "[1]");
2156    assert(format("%b", b) == "1");
2157
2158    b = BitArray([0, 0, 0, 0]);
2159    assert(format("%b", b) == "0000");
2160
2161    b = BitArray([0, 0, 0, 0, 1, 1, 1, 1]);
2162    assert(format("%s", b) == "[0, 0, 0, 0, 1, 1, 1, 1]");
2163    assert(format("%b", b) == "00001111");
2164
2165    b = BitArray([0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1]);
2166    assert(format("%s", b) == "[0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1]");
2167    assert(format("%b", b) == "00001111_00001111");
2168
2169    b = BitArray([1, 0, 0, 0, 0, 1, 1, 1, 1]);
2170    assert(format("%b", b) == "1_00001111");
2171
2172    b = BitArray([1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1]);
2173    assert(format("%b", b) == "1_00001111_00001111");
2174}
2175
2176/++
2177    Swaps the endianness of the given integral value or character.
2178  +/
2179T swapEndian(T)(T val) @safe pure nothrow @nogc
2180if (isIntegral!T || isSomeChar!T || isBoolean!T)
2181{
2182    static if (val.sizeof == 1)
2183        return val;
2184    else static if (isUnsigned!T)
2185        return swapEndianImpl(val);
2186    else static if (isIntegral!T)
2187        return cast(T) swapEndianImpl(cast(Unsigned!T) val);
2188    else static if (is(Unqual!T == wchar))
2189        return cast(T) swapEndian(cast(ushort) val);
2190    else static if (is(Unqual!T == dchar))
2191        return cast(T) swapEndian(cast(uint) val);
2192    else
2193        static assert(0, T.stringof ~ " unsupported by swapEndian.");
2194}
2195
2196private ushort swapEndianImpl(ushort val) @safe pure nothrow @nogc
2197{
2198    return ((val & 0xff00U) >> 8) |
2199           ((val & 0x00ffU) << 8);
2200}
2201
2202private uint swapEndianImpl(uint val) @trusted pure nothrow @nogc
2203{
2204    import core.bitop : bswap;
2205    return bswap(val);
2206}
2207
2208private ulong swapEndianImpl(ulong val) @trusted pure nothrow @nogc
2209{
2210    import core.bitop : bswap;
2211    immutable ulong res = bswap(cast(uint) val);
2212    return res << 32 | bswap(cast(uint)(val >> 32));
2213}
2214
2215@safe unittest
2216{
2217    import std.meta;
2218    foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, int, uint, long, ulong, char, wchar, dchar))
2219    {
2220        scope(failure) writefln("Failed type: %s", T.stringof);
2221        T val;
2222        const T cval;
2223        immutable T ival;
2224
2225        assert(swapEndian(swapEndian(val)) == val);
2226        assert(swapEndian(swapEndian(cval)) == cval);
2227        assert(swapEndian(swapEndian(ival)) == ival);
2228        assert(swapEndian(swapEndian(T.min)) == T.min);
2229        assert(swapEndian(swapEndian(T.max)) == T.max);
2230
2231        foreach (i; 2 .. 10)
2232        {
2233            immutable T maxI = cast(T)(T.max / i);
2234            immutable T minI = cast(T)(T.min / i);
2235
2236            assert(swapEndian(swapEndian(maxI)) == maxI);
2237
2238            static if (isSigned!T)
2239                assert(swapEndian(swapEndian(minI)) == minI);
2240        }
2241
2242        static if (isSigned!T)
2243            assert(swapEndian(swapEndian(cast(T) 0)) == 0);
2244
2245        // used to trigger BUG6354
2246        static if (T.sizeof > 1 && isUnsigned!T)
2247        {
2248            T left = 0xffU;
2249            left <<= (T.sizeof - 1) * 8;
2250            T right = 0xffU;
2251
2252            for (size_t i = 1; i < T.sizeof; ++i)
2253            {
2254                assert(swapEndian(left) == right);
2255                assert(swapEndian(right) == left);
2256                left >>= 8;
2257                right <<= 8;
2258            }
2259        }
2260    }
2261}
2262
2263
2264private union EndianSwapper(T)
2265if (canSwapEndianness!T)
2266{
2267    Unqual!T value;
2268    ubyte[T.sizeof] array;
2269
2270    static if (is(FloatingPointTypeOf!T == float))
2271        uint  intValue;
2272    else static if (is(FloatingPointTypeOf!T == double))
2273        ulong intValue;
2274
2275}
2276
2277
2278/++
2279    Converts the given value from the native endianness to big endian and
2280    returns it as a $(D ubyte[n]) where $(D n) is the size of the given type.
2281
2282    Returning a $(D ubyte[n]) helps prevent accidentally using a swapped value
2283    as a regular one (and in the case of floating point values, it's necessary,
2284    because the FPU will mess up any swapped floating point values. So, you
2285    can't actually have swapped floating point values as floating point values).
2286
2287    $(D real) is not supported, because its size is implementation-dependent
2288    and therefore could vary from machine to machine (which could make it
2289    unusable if you tried to transfer it to another machine).
2290  +/
2291auto nativeToBigEndian(T)(T val) @safe pure nothrow @nogc
2292if (canSwapEndianness!T)
2293{
2294    return nativeToBigEndianImpl(val);
2295}
2296
2297///
2298@safe unittest
2299{
2300    int i = 12345;
2301    ubyte[4] swappedI = nativeToBigEndian(i);
2302    assert(i == bigEndianToNative!int(swappedI));
2303
2304    double d = 123.45;
2305    ubyte[8] swappedD = nativeToBigEndian(d);
2306    assert(d == bigEndianToNative!double(swappedD));
2307}
2308
2309private auto nativeToBigEndianImpl(T)(T val) @safe pure nothrow @nogc
2310if (isIntegral!T || isSomeChar!T || isBoolean!T)
2311{
2312    EndianSwapper!T es = void;
2313
2314    version (LittleEndian)
2315        es.value = swapEndian(val);
2316    else
2317        es.value = val;
2318
2319    return es.array;
2320}
2321
2322private auto nativeToBigEndianImpl(T)(T val) @safe pure nothrow @nogc
2323if (isFloatOrDouble!T)
2324{
2325    version (LittleEndian)
2326        return floatEndianImpl!(T, true)(val);
2327    else
2328        return floatEndianImpl!(T, false)(val);
2329}
2330
2331@safe unittest
2332{
2333    import std.meta;
2334    foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, int, uint, long, ulong,
2335                         char, wchar, dchar
2336        /* The trouble here is with floats and doubles being compared against nan
2337         * using a bit compare. There are two kinds of nans, quiet and signaling.
2338         * When a nan passes through the x87, it converts signaling to quiet.
2339         * When a nan passes through the XMM, it does not convert signaling to quiet.
2340         * float.init is a signaling nan.
2341         * The binary API sometimes passes the data through the XMM, sometimes through
2342         * the x87, meaning these will fail the 'is' bit compare under some circumstances.
2343         * I cannot think of a fix for this that makes consistent sense.
2344         */
2345                          /*,float, double*/))
2346    {
2347        scope(failure) writefln("Failed type: %s", T.stringof);
2348        T val;
2349        const T cval;
2350        immutable T ival;
2351
2352        //is instead of == because of NaN for floating point values.
2353        assert(bigEndianToNative!T(nativeToBigEndian(val)) is val);
2354        assert(bigEndianToNative!T(nativeToBigEndian(cval)) is cval);
2355        assert(bigEndianToNative!T(nativeToBigEndian(ival)) is ival);
2356        assert(bigEndianToNative!T(nativeToBigEndian(T.min)) == T.min);
2357        assert(bigEndianToNative!T(nativeToBigEndian(T.max)) == T.max);
2358
2359        static if (isSigned!T)
2360            assert(bigEndianToNative!T(nativeToBigEndian(cast(T) 0)) == 0);
2361
2362        static if (!is(T == bool))
2363        {
2364            foreach (i; [2, 4, 6, 7, 9, 11])
2365            {
2366                immutable T maxI = cast(T)(T.max / i);
2367                immutable T minI = cast(T)(T.min / i);
2368
2369                assert(bigEndianToNative!T(nativeToBigEndian(maxI)) == maxI);
2370
2371                static if (T.sizeof > 1)
2372                    assert(nativeToBigEndian(maxI) != nativeToLittleEndian(maxI));
2373                else
2374                    assert(nativeToBigEndian(maxI) == nativeToLittleEndian(maxI));
2375
2376                static if (isSigned!T)
2377                {
2378                    assert(bigEndianToNative!T(nativeToBigEndian(minI)) == minI);
2379
2380                    static if (T.sizeof > 1)
2381                        assert(nativeToBigEndian(minI) != nativeToLittleEndian(minI));
2382                    else
2383                        assert(nativeToBigEndian(minI) == nativeToLittleEndian(minI));
2384                }
2385            }
2386        }
2387
2388        static if (isUnsigned!T || T.sizeof == 1 || is(T == wchar))
2389            assert(nativeToBigEndian(T.max) == nativeToLittleEndian(T.max));
2390        else
2391            assert(nativeToBigEndian(T.max) != nativeToLittleEndian(T.max));
2392
2393        static if (isUnsigned!T || T.sizeof == 1 || isSomeChar!T)
2394            assert(nativeToBigEndian(T.min) == nativeToLittleEndian(T.min));
2395        else
2396            assert(nativeToBigEndian(T.min) != nativeToLittleEndian(T.min));
2397    }
2398}
2399
2400
2401/++
2402    Converts the given value from big endian to the native endianness and
2403    returns it. The value is given as a $(D ubyte[n]) where $(D n) is the size
2404    of the target type. You must give the target type as a template argument,
2405    because there are multiple types with the same size and so the type of the
2406    argument is not enough to determine the return type.
2407
2408    Taking a $(D ubyte[n]) helps prevent accidentally using a swapped value
2409    as a regular one (and in the case of floating point values, it's necessary,
2410    because the FPU will mess up any swapped floating point values. So, you
2411    can't actually have swapped floating point values as floating point values).
2412  +/
2413T bigEndianToNative(T, size_t n)(ubyte[n] val) @safe pure nothrow @nogc
2414if (canSwapEndianness!T && n == T.sizeof)
2415{
2416    return bigEndianToNativeImpl!(T, n)(val);
2417}
2418
2419///
2420@safe unittest
2421{
2422    ushort i = 12345;
2423    ubyte[2] swappedI = nativeToBigEndian(i);
2424    assert(i == bigEndianToNative!ushort(swappedI));
2425
2426    dchar c = 'D';
2427    ubyte[4] swappedC = nativeToBigEndian(c);
2428    assert(c == bigEndianToNative!dchar(swappedC));
2429}
2430
2431private T bigEndianToNativeImpl(T, size_t n)(ubyte[n] val) @safe pure nothrow @nogc
2432if ((isIntegral!T || isSomeChar!T || isBoolean!T) &&
2433    n == T.sizeof)
2434{
2435    EndianSwapper!T es = void;
2436    es.array = val;
2437
2438    version (LittleEndian)
2439        immutable retval = swapEndian(es.value);
2440    else
2441        immutable retval = es.value;
2442
2443    return retval;
2444}
2445
2446private T bigEndianToNativeImpl(T, size_t n)(ubyte[n] val) @safe pure nothrow @nogc
2447if (isFloatOrDouble!T && n == T.sizeof)
2448{
2449    version (LittleEndian)
2450        return cast(T) floatEndianImpl!(n, true)(val);
2451    else
2452        return cast(T) floatEndianImpl!(n, false)(val);
2453}
2454
2455
2456/++
2457    Converts the given value from the native endianness to little endian and
2458    returns it as a $(D ubyte[n]) where $(D n) is the size of the given type.
2459
2460    Returning a $(D ubyte[n]) helps prevent accidentally using a swapped value
2461    as a regular one (and in the case of floating point values, it's necessary,
2462    because the FPU will mess up any swapped floating point values. So, you
2463    can't actually have swapped floating point values as floating point values).
2464  +/
2465auto nativeToLittleEndian(T)(T val) @safe pure nothrow @nogc
2466if (canSwapEndianness!T)
2467{
2468    return nativeToLittleEndianImpl(val);
2469}
2470
2471///
2472@safe unittest
2473{
2474    int i = 12345;
2475    ubyte[4] swappedI = nativeToLittleEndian(i);
2476    assert(i == littleEndianToNative!int(swappedI));
2477
2478    double d = 123.45;
2479    ubyte[8] swappedD = nativeToLittleEndian(d);
2480    assert(d == littleEndianToNative!double(swappedD));
2481}
2482
2483private auto nativeToLittleEndianImpl(T)(T val) @safe pure nothrow @nogc
2484if (isIntegral!T || isSomeChar!T || isBoolean!T)
2485{
2486    EndianSwapper!T es = void;
2487
2488    version (BigEndian)
2489        es.value = swapEndian(val);
2490    else
2491        es.value = val;
2492
2493    return es.array;
2494}
2495
2496private auto nativeToLittleEndianImpl(T)(T val) @safe pure nothrow @nogc
2497if (isFloatOrDouble!T)
2498{
2499    version (BigEndian)
2500        return floatEndianImpl!(T, true)(val);
2501    else
2502        return floatEndianImpl!(T, false)(val);
2503}
2504
2505@safe unittest
2506{
2507    import std.meta;
2508    foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, int, uint, long, ulong,
2509                         char, wchar, dchar/*,
2510                         float, double*/))
2511    {
2512        scope(failure) writefln("Failed type: %s", T.stringof);
2513        T val;
2514        const T cval;
2515        immutable T ival;
2516
2517        //is instead of == because of NaN for floating point values.
2518        assert(littleEndianToNative!T(nativeToLittleEndian(val)) is val);
2519        assert(littleEndianToNative!T(nativeToLittleEndian(cval)) is cval);
2520        assert(littleEndianToNative!T(nativeToLittleEndian(ival)) is ival);
2521        assert(littleEndianToNative!T(nativeToLittleEndian(T.min)) == T.min);
2522        assert(littleEndianToNative!T(nativeToLittleEndian(T.max)) == T.max);
2523
2524        static if (isSigned!T)
2525            assert(littleEndianToNative!T(nativeToLittleEndian(cast(T) 0)) == 0);
2526
2527        static if (!is(T == bool))
2528        {
2529            foreach (i; 2 .. 10)
2530            {
2531                immutable T maxI = cast(T)(T.max / i);
2532                immutable T minI = cast(T)(T.min / i);
2533
2534                assert(littleEndianToNative!T(nativeToLittleEndian(maxI)) == maxI);
2535
2536                static if (isSigned!T)
2537                    assert(littleEndianToNative!T(nativeToLittleEndian(minI)) == minI);
2538            }
2539        }
2540    }
2541}
2542
2543
2544/++
2545    Converts the given value from little endian to the native endianness and
2546    returns it. The value is given as a $(D ubyte[n]) where $(D n) is the size
2547    of the target type. You must give the target type as a template argument,
2548    because there are multiple types with the same size and so the type of the
2549    argument is not enough to determine the return type.
2550
2551    Taking a $(D ubyte[n]) helps prevent accidentally using a swapped value
2552    as a regular one (and in the case of floating point values, it's necessary,
2553    because the FPU will mess up any swapped floating point values. So, you
2554    can't actually have swapped floating point values as floating point values).
2555
2556    $(D real) is not supported, because its size is implementation-dependent
2557    and therefore could vary from machine to machine (which could make it
2558    unusable if you tried to transfer it to another machine).
2559  +/
2560T littleEndianToNative(T, size_t n)(ubyte[n] val) @safe pure nothrow @nogc
2561if (canSwapEndianness!T && n == T.sizeof)
2562{
2563    return littleEndianToNativeImpl!T(val);
2564}
2565
2566///
2567@safe unittest
2568{
2569    ushort i = 12345;
2570    ubyte[2] swappedI = nativeToLittleEndian(i);
2571    assert(i == littleEndianToNative!ushort(swappedI));
2572
2573    dchar c = 'D';
2574    ubyte[4] swappedC = nativeToLittleEndian(c);
2575    assert(c == littleEndianToNative!dchar(swappedC));
2576}
2577
2578private T littleEndianToNativeImpl(T, size_t n)(ubyte[n] val) @safe pure nothrow @nogc
2579if ((isIntegral!T || isSomeChar!T || isBoolean!T) &&
2580    n == T.sizeof)
2581{
2582    EndianSwapper!T es = void;
2583    es.array = val;
2584
2585    version (BigEndian)
2586        immutable retval = swapEndian(es.value);
2587    else
2588        immutable retval = es.value;
2589
2590    return retval;
2591}
2592
2593private T littleEndianToNativeImpl(T, size_t n)(ubyte[n] val) @safe pure nothrow @nogc
2594if (((isFloatOrDouble!T) &&
2595    n == T.sizeof))
2596{
2597    version (BigEndian)
2598        return floatEndianImpl!(n, true)(val);
2599    else
2600        return floatEndianImpl!(n, false)(val);
2601}
2602
2603private auto floatEndianImpl(T, bool swap)(T val) @safe pure nothrow @nogc
2604if (isFloatOrDouble!T)
2605{
2606    EndianSwapper!T es = void;
2607    es.value = val;
2608
2609    static if (swap)
2610        es.intValue = swapEndian(es.intValue);
2611
2612    return es.array;
2613}
2614
2615private auto floatEndianImpl(size_t n, bool swap)(ubyte[n] val) @safe pure nothrow @nogc
2616if (n == 4 || n == 8)
2617{
2618    static if (n == 4)       EndianSwapper!float es = void;
2619    else static if (n == 8)  EndianSwapper!double es = void;
2620
2621    es.array = val;
2622
2623    static if (swap)
2624        es.intValue = swapEndian(es.intValue);
2625
2626    return es.value;
2627}
2628
2629private template isFloatOrDouble(T)
2630{
2631    enum isFloatOrDouble = isFloatingPoint!T &&
2632                           !is(Unqual!(FloatingPointTypeOf!T) == real);
2633}
2634
2635@safe unittest
2636{
2637    import std.meta;
2638    foreach (T; AliasSeq!(float, double))
2639    {
2640        static assert(isFloatOrDouble!(T));
2641        static assert(isFloatOrDouble!(const T));
2642        static assert(isFloatOrDouble!(immutable T));
2643        static assert(isFloatOrDouble!(shared T));
2644        static assert(isFloatOrDouble!(shared(const T)));
2645        static assert(isFloatOrDouble!(shared(immutable T)));
2646    }
2647
2648    static assert(!isFloatOrDouble!(real));
2649    static assert(!isFloatOrDouble!(const real));
2650    static assert(!isFloatOrDouble!(immutable real));
2651    static assert(!isFloatOrDouble!(shared real));
2652    static assert(!isFloatOrDouble!(shared(const real)));
2653    static assert(!isFloatOrDouble!(shared(immutable real)));
2654}
2655
2656private template canSwapEndianness(T)
2657{
2658    enum canSwapEndianness = isIntegral!T ||
2659                             isSomeChar!T ||
2660                             isBoolean!T ||
2661                             isFloatOrDouble!T;
2662}
2663
2664@safe unittest
2665{
2666    import std.meta;
2667    foreach (T; AliasSeq!(bool, ubyte, byte, ushort, short, uint, int, ulong,
2668                         long, char, wchar, dchar, float, double))
2669    {
2670        static assert(canSwapEndianness!(T));
2671        static assert(canSwapEndianness!(const T));
2672        static assert(canSwapEndianness!(immutable T));
2673        static assert(canSwapEndianness!(shared(T)));
2674        static assert(canSwapEndianness!(shared(const T)));
2675        static assert(canSwapEndianness!(shared(immutable T)));
2676    }
2677
2678    //!
2679    foreach (T; AliasSeq!(real, string, wstring, dstring))
2680    {
2681        static assert(!canSwapEndianness!(T));
2682        static assert(!canSwapEndianness!(const T));
2683        static assert(!canSwapEndianness!(immutable T));
2684        static assert(!canSwapEndianness!(shared(T)));
2685        static assert(!canSwapEndianness!(shared(const T)));
2686        static assert(!canSwapEndianness!(shared(immutable T)));
2687    }
2688}
2689
2690/++
2691    Takes a range of $(D ubyte)s and converts the first $(D T.sizeof) bytes to
2692    $(D T). The value returned is converted from the given endianness to the
2693    native endianness. The range is not consumed.
2694
2695    Params:
2696        T     = The integral type to convert the first $(D T.sizeof) bytes to.
2697        endianness = The endianness that the bytes are assumed to be in.
2698        range = The range to read from.
2699        index = The index to start reading from (instead of starting at the
2700                front). If index is a pointer, then it is updated to the index
2701                after the bytes read. The overloads with index are only
2702                available if $(D hasSlicing!R) is $(D true).
2703  +/
2704
2705T peek(T, Endian endianness = Endian.bigEndian, R)(R range)
2706if (canSwapEndianness!T &&
2707    isForwardRange!R &&
2708    is(ElementType!R : const ubyte))
2709{
2710    static if (hasSlicing!R)
2711        const ubyte[T.sizeof] bytes = range[0 .. T.sizeof];
2712    else
2713    {
2714        ubyte[T.sizeof] bytes;
2715        //Make sure that range is not consumed, even if it's a class.
2716        range = range.save;
2717
2718        foreach (ref e; bytes)
2719        {
2720            e = range.front;
2721            range.popFront();
2722        }
2723    }
2724
2725    static if (endianness == Endian.bigEndian)
2726        return bigEndianToNative!T(bytes);
2727    else
2728        return littleEndianToNative!T(bytes);
2729}
2730
2731/++ Ditto +/
2732T peek(T, Endian endianness = Endian.bigEndian, R)(R range, size_t index)
2733if (canSwapEndianness!T &&
2734    isForwardRange!R &&
2735    hasSlicing!R &&
2736    is(ElementType!R : const ubyte))
2737{
2738    return peek!(T, endianness)(range, &index);
2739}
2740
2741/++ Ditto +/
2742T peek(T, Endian endianness = Endian.bigEndian, R)(R range, size_t* index)
2743if (canSwapEndianness!T &&
2744    isForwardRange!R &&
2745    hasSlicing!R &&
2746    is(ElementType!R : const ubyte))
2747{
2748    assert(index);
2749
2750    immutable begin = *index;
2751    immutable end = begin + T.sizeof;
2752    const ubyte[T.sizeof] bytes = range[begin .. end];
2753    *index = end;
2754
2755    static if (endianness == Endian.bigEndian)
2756        return bigEndianToNative!T(bytes);
2757    else
2758        return littleEndianToNative!T(bytes);
2759}
2760
2761///
2762@system unittest
2763{
2764    ubyte[] buffer = [1, 5, 22, 9, 44, 255, 8];
2765    assert(buffer.peek!uint() == 17110537);
2766    assert(buffer.peek!ushort() == 261);
2767    assert(buffer.peek!ubyte() == 1);
2768
2769    assert(buffer.peek!uint(2) == 369700095);
2770    assert(buffer.peek!ushort(2) == 5641);
2771    assert(buffer.peek!ubyte(2) == 22);
2772
2773    size_t index = 0;
2774    assert(buffer.peek!ushort(&index) == 261);
2775    assert(index == 2);
2776
2777    assert(buffer.peek!uint(&index) == 369700095);
2778    assert(index == 6);
2779
2780    assert(buffer.peek!ubyte(&index) == 8);
2781    assert(index == 7);
2782}
2783
2784@system unittest
2785{
2786    {
2787        //bool
2788        ubyte[] buffer = [0, 1];
2789        assert(buffer.peek!bool() == false);
2790        assert(buffer.peek!bool(1) == true);
2791
2792        size_t index = 0;
2793        assert(buffer.peek!bool(&index) == false);
2794        assert(index == 1);
2795
2796        assert(buffer.peek!bool(&index) == true);
2797        assert(index == 2);
2798    }
2799
2800    {
2801        //char (8bit)
2802        ubyte[] buffer = [97, 98, 99, 100];
2803        assert(buffer.peek!char() == 'a');
2804        assert(buffer.peek!char(1) == 'b');
2805
2806        size_t index = 0;
2807        assert(buffer.peek!char(&index) == 'a');
2808        assert(index == 1);
2809
2810        assert(buffer.peek!char(&index) == 'b');
2811        assert(index == 2);
2812    }
2813
2814    {
2815        //wchar (16bit - 2x ubyte)
2816        ubyte[] buffer = [1, 5, 32, 29, 1, 7];
2817        assert(buffer.peek!wchar() == '��');
2818        assert(buffer.peek!wchar(2) == '���');
2819        assert(buffer.peek!wchar(4) == '��');
2820
2821        size_t index = 0;
2822        assert(buffer.peek!wchar(&index) == '��');
2823        assert(index == 2);
2824
2825        assert(buffer.peek!wchar(&index) == '���');
2826        assert(index == 4);
2827
2828        assert(buffer.peek!wchar(&index) == '��');
2829        assert(index == 6);
2830    }
2831
2832    {
2833        //dchar (32bit - 4x ubyte)
2834        ubyte[] buffer = [0, 0, 1, 5, 0, 0, 32, 29, 0, 0, 1, 7];
2835        assert(buffer.peek!dchar() == '��');
2836        assert(buffer.peek!dchar(4) == '���');
2837        assert(buffer.peek!dchar(8) == '��');
2838
2839        size_t index = 0;
2840        assert(buffer.peek!dchar(&index) == '��');
2841        assert(index == 4);
2842
2843        assert(buffer.peek!dchar(&index) == '���');
2844        assert(index == 8);
2845
2846        assert(buffer.peek!dchar(&index) == '��');
2847        assert(index == 12);
2848    }
2849
2850    {
2851        //float (32bit - 4x ubyte)
2852        ubyte[] buffer = [66, 0, 0, 0, 65, 200, 0, 0];
2853        assert(buffer.peek!float()== 32.0);
2854        assert(buffer.peek!float(4) == 25.0f);
2855
2856        size_t index = 0;
2857        assert(buffer.peek!float(&index) == 32.0f);
2858        assert(index == 4);
2859
2860        assert(buffer.peek!float(&index) == 25.0f);
2861        assert(index == 8);
2862    }
2863
2864    {
2865        //double (64bit - 8x ubyte)
2866        ubyte[] buffer = [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0];
2867        assert(buffer.peek!double() == 32.0);
2868        assert(buffer.peek!double(8) == 25.0);
2869
2870        size_t index = 0;
2871        assert(buffer.peek!double(&index) == 32.0);
2872        assert(index == 8);
2873
2874        assert(buffer.peek!double(&index) == 25.0);
2875        assert(index == 16);
2876    }
2877
2878    {
2879        //enum
2880        ubyte[] buffer = [0, 0, 0, 10, 0, 0, 0, 20, 0, 0, 0, 30];
2881
2882        enum Foo
2883        {
2884            one = 10,
2885            two = 20,
2886            three = 30
2887        }
2888
2889        assert(buffer.peek!Foo() == Foo.one);
2890        assert(buffer.peek!Foo(0) == Foo.one);
2891        assert(buffer.peek!Foo(4) == Foo.two);
2892        assert(buffer.peek!Foo(8) == Foo.three);
2893
2894        size_t index = 0;
2895        assert(buffer.peek!Foo(&index) == Foo.one);
2896        assert(index == 4);
2897
2898        assert(buffer.peek!Foo(&index) == Foo.two);
2899        assert(index == 8);
2900
2901        assert(buffer.peek!Foo(&index) == Foo.three);
2902        assert(index == 12);
2903    }
2904
2905    {
2906        //enum - bool
2907        ubyte[] buffer = [0, 1];
2908
2909        enum Bool: bool
2910        {
2911            bfalse = false,
2912            btrue = true,
2913        }
2914
2915        assert(buffer.peek!Bool() == Bool.bfalse);
2916        assert(buffer.peek!Bool(0) == Bool.bfalse);
2917        assert(buffer.peek!Bool(1) == Bool.btrue);
2918
2919        size_t index = 0;
2920        assert(buffer.peek!Bool(&index) == Bool.bfalse);
2921        assert(index == 1);
2922
2923        assert(buffer.peek!Bool(&index) == Bool.btrue);
2924        assert(index == 2);
2925    }
2926
2927    {
2928        //enum - float
2929        ubyte[] buffer = [66, 0, 0, 0, 65, 200, 0, 0];
2930
2931        enum Float: float
2932        {
2933            one = 32.0f,
2934            two = 25.0f
2935        }
2936
2937        assert(buffer.peek!Float() == Float.one);
2938        assert(buffer.peek!Float(0) == Float.one);
2939        assert(buffer.peek!Float(4) == Float.two);
2940
2941        size_t index = 0;
2942        assert(buffer.peek!Float(&index) == Float.one);
2943        assert(index == 4);
2944
2945        assert(buffer.peek!Float(&index) == Float.two);
2946        assert(index == 8);
2947    }
2948
2949    {
2950        //enum - double
2951        ubyte[] buffer = [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0];
2952
2953        enum Double: double
2954        {
2955            one = 32.0,
2956            two = 25.0
2957        }
2958
2959        assert(buffer.peek!Double() == Double.one);
2960        assert(buffer.peek!Double(0) == Double.one);
2961        assert(buffer.peek!Double(8) == Double.two);
2962
2963        size_t index = 0;
2964        assert(buffer.peek!Double(&index) == Double.one);
2965        assert(index == 8);
2966
2967        assert(buffer.peek!Double(&index) == Double.two);
2968        assert(index == 16);
2969    }
2970
2971    {
2972        //enum - real
2973        ubyte[] buffer = [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0];
2974
2975        enum Real: real
2976        {
2977            one = 32.0,
2978            two = 25.0
2979        }
2980
2981        static assert(!__traits(compiles, buffer.peek!Real()));
2982    }
2983}
2984
2985@safe unittest
2986{
2987    import std.algorithm.iteration : filter;
2988    ubyte[] buffer = [1, 5, 22, 9, 44, 255, 7];
2989    auto range = filter!"true"(buffer);
2990    assert(range.peek!uint() == 17110537);
2991    assert(range.peek!ushort() == 261);
2992    assert(range.peek!ubyte() == 1);
2993}
2994
2995
2996/++
2997    Takes a range of $(D ubyte)s and converts the first $(D T.sizeof) bytes to
2998    $(D T). The value returned is converted from the given endianness to the
2999    native endianness. The $(D T.sizeof) bytes which are read are consumed from
3000    the range.
3001
3002    Params:
3003        T     = The integral type to convert the first $(D T.sizeof) bytes to.
3004        endianness = The endianness that the bytes are assumed to be in.
3005        range = The range to read from.
3006  +/
3007T read(T, Endian endianness = Endian.bigEndian, R)(ref R range)
3008if (canSwapEndianness!T && isInputRange!R && is(ElementType!R : const ubyte))
3009{
3010    static if (hasSlicing!R && is(typeof(R.init[0 .. 0]) : const(ubyte)[]))
3011    {
3012        const ubyte[T.sizeof] bytes = range[0 .. T.sizeof];
3013        range.popFrontN(T.sizeof);
3014    }
3015    else
3016    {
3017        ubyte[T.sizeof] bytes;
3018
3019        foreach (ref e; bytes)
3020        {
3021            e = range.front;
3022            range.popFront();
3023        }
3024    }
3025
3026    static if (endianness == Endian.bigEndian)
3027        return bigEndianToNative!T(bytes);
3028    else
3029        return littleEndianToNative!T(bytes);
3030}
3031
3032///
3033@safe unittest
3034{
3035    import std.range.primitives : empty;
3036    ubyte[] buffer = [1, 5, 22, 9, 44, 255, 8];
3037    assert(buffer.length == 7);
3038
3039    assert(buffer.read!ushort() == 261);
3040    assert(buffer.length == 5);
3041
3042    assert(buffer.read!uint() == 369700095);
3043    assert(buffer.length == 1);
3044
3045    assert(buffer.read!ubyte() == 8);
3046    assert(buffer.empty);
3047}
3048
3049@safe unittest
3050{
3051    {
3052        //bool
3053        ubyte[] buffer = [0, 1];
3054        assert(buffer.length == 2);
3055
3056        assert(buffer.read!bool() == false);
3057        assert(buffer.length == 1);
3058
3059        assert(buffer.read!bool() == true);
3060        assert(buffer.empty);
3061    }
3062
3063    {
3064        //char (8bit)
3065        ubyte[] buffer = [97, 98, 99];
3066        assert(buffer.length == 3);
3067
3068        assert(buffer.read!char() == 'a');
3069        assert(buffer.length == 2);
3070
3071        assert(buffer.read!char() == 'b');
3072        assert(buffer.length == 1);
3073
3074        assert(buffer.read!char() == 'c');
3075        assert(buffer.empty);
3076    }
3077
3078    {
3079        //wchar (16bit - 2x ubyte)
3080        ubyte[] buffer = [1, 5, 32, 29, 1, 7];
3081        assert(buffer.length == 6);
3082
3083        assert(buffer.read!wchar() == '��');
3084        assert(buffer.length == 4);
3085
3086        assert(buffer.read!wchar() == '���');
3087        assert(buffer.length == 2);
3088
3089        assert(buffer.read!wchar() == '��');
3090        assert(buffer.empty);
3091    }
3092
3093    {
3094        //dchar (32bit - 4x ubyte)
3095        ubyte[] buffer = [0, 0, 1, 5, 0, 0, 32, 29, 0, 0, 1, 7];
3096        assert(buffer.length == 12);
3097
3098        assert(buffer.read!dchar() == '��');
3099        assert(buffer.length == 8);
3100
3101        assert(buffer.read!dchar() == '���');
3102        assert(buffer.length == 4);
3103
3104        assert(buffer.read!dchar() == '��');
3105        assert(buffer.empty);
3106    }
3107
3108    {
3109        //float (32bit - 4x ubyte)
3110        ubyte[] buffer = [66, 0, 0, 0, 65, 200, 0, 0];
3111        assert(buffer.length == 8);
3112
3113        assert(buffer.read!float()== 32.0);
3114        assert(buffer.length == 4);
3115
3116        assert(buffer.read!float() == 25.0f);
3117        assert(buffer.empty);
3118    }
3119
3120    {
3121        //double (64bit - 8x ubyte)
3122        ubyte[] buffer = [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0];
3123        assert(buffer.length == 16);
3124
3125        assert(buffer.read!double() == 32.0);
3126        assert(buffer.length == 8);
3127
3128        assert(buffer.read!double() == 25.0);
3129        assert(buffer.empty);
3130    }
3131
3132    {
3133        //enum - uint
3134        ubyte[] buffer = [0, 0, 0, 10, 0, 0, 0, 20, 0, 0, 0, 30];
3135        assert(buffer.length == 12);
3136
3137        enum Foo
3138        {
3139            one = 10,
3140            two = 20,
3141            three = 30
3142        }
3143
3144        assert(buffer.read!Foo() == Foo.one);
3145        assert(buffer.length == 8);
3146
3147        assert(buffer.read!Foo() == Foo.two);
3148        assert(buffer.length == 4);
3149
3150        assert(buffer.read!Foo() == Foo.three);
3151        assert(buffer.empty);
3152    }
3153
3154    {
3155        //enum - bool
3156        ubyte[] buffer = [0, 1];
3157        assert(buffer.length == 2);
3158
3159        enum Bool: bool
3160        {
3161            bfalse = false,
3162            btrue = true,
3163        }
3164
3165        assert(buffer.read!Bool() == Bool.bfalse);
3166        assert(buffer.length == 1);
3167
3168        assert(buffer.read!Bool() == Bool.btrue);
3169        assert(buffer.empty);
3170    }
3171
3172    {
3173        //enum - float
3174        ubyte[] buffer = [66, 0, 0, 0, 65, 200, 0, 0];
3175        assert(buffer.length == 8);
3176
3177        enum Float: float
3178        {
3179            one = 32.0f,
3180            two = 25.0f
3181        }
3182
3183        assert(buffer.read!Float() == Float.one);
3184        assert(buffer.length == 4);
3185
3186        assert(buffer.read!Float() == Float.two);
3187        assert(buffer.empty);
3188    }
3189
3190    {
3191        //enum - double
3192        ubyte[] buffer = [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0];
3193        assert(buffer.length == 16);
3194
3195        enum Double: double
3196        {
3197            one = 32.0,
3198            two = 25.0
3199        }
3200
3201        assert(buffer.read!Double() == Double.one);
3202        assert(buffer.length == 8);
3203
3204        assert(buffer.read!Double() == Double.two);
3205        assert(buffer.empty);
3206    }
3207
3208    {
3209        //enum - real
3210        ubyte[] buffer = [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0];
3211
3212        enum Real: real
3213        {
3214            one = 32.0,
3215            two = 25.0
3216        }
3217
3218        static assert(!__traits(compiles, buffer.read!Real()));
3219    }
3220}
3221
3222@safe unittest
3223{
3224    import std.algorithm.iteration : filter;
3225    ubyte[] buffer = [1, 5, 22, 9, 44, 255, 8];
3226    auto range = filter!"true"(buffer);
3227    assert(walkLength(range) == 7);
3228
3229    assert(range.read!ushort() == 261);
3230    assert(walkLength(range) == 5);
3231
3232    assert(range.read!uint() == 369700095);
3233    assert(walkLength(range) == 1);
3234
3235    assert(range.read!ubyte() == 8);
3236    assert(range.empty);
3237}
3238
3239// issue 17247
3240@safe unittest
3241{
3242    struct UbyteRange
3243    {
3244        ubyte[] impl;
3245        @property bool empty() { return impl.empty; }
3246        @property ubyte front() { return impl.front; }
3247        void popFront() { impl.popFront(); }
3248        @property UbyteRange save() { return this; }
3249
3250        // N.B. support slicing but do not return ubyte[] slices.
3251        UbyteRange opSlice(size_t start, size_t end)
3252        {
3253            return UbyteRange(impl[start .. end]);
3254        }
3255        @property size_t length() { return impl.length; }
3256        size_t opDollar() { return impl.length; }
3257    }
3258    static assert(hasSlicing!UbyteRange);
3259
3260    auto r = UbyteRange([0x01, 0x00, 0x00, 0x00]);
3261    int x = r.read!(int, Endian.littleEndian)();
3262    assert(x == 1);
3263}
3264
3265
3266/++
3267    Takes an integral value, converts it to the given endianness, and writes it
3268    to the given range of $(D ubyte)s as a sequence of $(D T.sizeof) $(D ubyte)s
3269    starting at index. $(D hasSlicing!R) must be $(D true).
3270
3271    Params:
3272        T     = The integral type to convert the first $(D T.sizeof) bytes to.
3273        endianness = The endianness to _write the bytes in.
3274        range = The range to _write to.
3275        value = The value to _write.
3276        index = The index to start writing to. If index is a pointer, then it
3277                is updated to the index after the bytes read.
3278  +/
3279void write(T, Endian endianness = Endian.bigEndian, R)(R range, T value, size_t index)
3280if (canSwapEndianness!T &&
3281    isForwardRange!R &&
3282    hasSlicing!R &&
3283    is(ElementType!R : ubyte))
3284{
3285    write!(T, endianness)(range, value, &index);
3286}
3287
3288/++ Ditto +/
3289void write(T, Endian endianness = Endian.bigEndian, R)(R range, T value, size_t* index)
3290if (canSwapEndianness!T &&
3291    isForwardRange!R &&
3292    hasSlicing!R &&
3293    is(ElementType!R : ubyte))
3294{
3295    assert(index);
3296
3297    static if (endianness == Endian.bigEndian)
3298        immutable bytes = nativeToBigEndian!T(value);
3299    else
3300        immutable bytes = nativeToLittleEndian!T(value);
3301
3302    immutable begin = *index;
3303    immutable end = begin + T.sizeof;
3304    *index = end;
3305    range[begin .. end] = bytes[0 .. T.sizeof];
3306}
3307
3308///
3309@system unittest
3310{
3311    {
3312        ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0];
3313        buffer.write!uint(29110231u, 0);
3314        assert(buffer == [1, 188, 47, 215, 0, 0, 0, 0]);
3315
3316        buffer.write!ushort(927, 0);
3317        assert(buffer == [3, 159, 47, 215, 0, 0, 0, 0]);
3318
3319        buffer.write!ubyte(42, 0);
3320        assert(buffer == [42, 159, 47, 215, 0, 0, 0, 0]);
3321    }
3322
3323    {
3324        ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0, 0];
3325        buffer.write!uint(142700095u, 2);
3326        assert(buffer == [0, 0, 8, 129, 110, 63, 0, 0, 0]);
3327
3328        buffer.write!ushort(19839, 2);
3329        assert(buffer == [0, 0, 77, 127, 110, 63, 0, 0, 0]);
3330
3331        buffer.write!ubyte(132, 2);
3332        assert(buffer == [0, 0, 132, 127, 110, 63, 0, 0, 0]);
3333    }
3334
3335    {
3336        ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0];
3337        size_t index = 0;
3338        buffer.write!ushort(261, &index);
3339        assert(buffer == [1, 5, 0, 0, 0, 0, 0, 0]);
3340        assert(index == 2);
3341
3342        buffer.write!uint(369700095u, &index);
3343        assert(buffer == [1, 5, 22, 9, 44, 255, 0, 0]);
3344        assert(index == 6);
3345
3346        buffer.write!ubyte(8, &index);
3347        assert(buffer == [1, 5, 22, 9, 44, 255, 8, 0]);
3348        assert(index == 7);
3349    }
3350}
3351
3352@system unittest
3353{
3354    {
3355        //bool
3356        ubyte[] buffer = [0, 0];
3357
3358        buffer.write!bool(false, 0);
3359        assert(buffer == [0, 0]);
3360
3361        buffer.write!bool(true, 0);
3362        assert(buffer == [1, 0]);
3363
3364        buffer.write!bool(true, 1);
3365        assert(buffer == [1, 1]);
3366
3367        buffer.write!bool(false, 1);
3368        assert(buffer == [1, 0]);
3369
3370        size_t index = 0;
3371        buffer.write!bool(false, &index);
3372        assert(buffer == [0, 0]);
3373        assert(index == 1);
3374
3375        buffer.write!bool(true, &index);
3376        assert(buffer == [0, 1]);
3377        assert(index == 2);
3378    }
3379
3380    {
3381        //char (8bit)
3382        ubyte[] buffer = [0, 0, 0];
3383
3384        buffer.write!char('a', 0);
3385        assert(buffer == [97, 0, 0]);
3386
3387        buffer.write!char('b', 1);
3388        assert(buffer == [97, 98, 0]);
3389
3390        size_t index = 0;
3391        buffer.write!char('a', &index);
3392        assert(buffer == [97, 98, 0]);
3393        assert(index == 1);
3394
3395        buffer.write!char('b', &index);
3396        assert(buffer == [97, 98, 0]);
3397        assert(index == 2);
3398
3399        buffer.write!char('c', &index);
3400        assert(buffer == [97, 98, 99]);
3401        assert(index == 3);
3402    }
3403
3404    {
3405        //wchar (16bit - 2x ubyte)
3406        ubyte[] buffer = [0, 0, 0, 0];
3407
3408        buffer.write!wchar('��', 0);
3409        assert(buffer == [1, 5, 0, 0]);
3410
3411        buffer.write!wchar('���', 2);
3412        assert(buffer == [1, 5, 32, 29]);
3413
3414        size_t index = 0;
3415        buffer.write!wchar('��', &index);
3416        assert(buffer == [1, 7, 32, 29]);
3417        assert(index == 2);
3418
3419        buffer.write!wchar('��', &index);
3420        assert(buffer == [1, 7, 1, 5]);
3421        assert(index == 4);
3422    }
3423
3424    {
3425        //dchar (32bit - 4x ubyte)
3426        ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0];
3427
3428        buffer.write!dchar('��', 0);
3429        assert(buffer == [0, 0, 1, 5, 0, 0, 0, 0]);
3430
3431        buffer.write!dchar('���', 4);
3432        assert(buffer == [0, 0, 1, 5, 0, 0, 32, 29]);
3433
3434        size_t index = 0;
3435        buffer.write!dchar('��', &index);
3436        assert(buffer == [0, 0, 1, 7, 0, 0, 32, 29]);
3437        assert(index == 4);
3438
3439        buffer.write!dchar('��', &index);
3440        assert(buffer == [0, 0, 1, 7, 0, 0, 1, 5]);
3441        assert(index == 8);
3442    }
3443
3444    {
3445        //float (32bit - 4x ubyte)
3446        ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0];
3447
3448        buffer.write!float(32.0f, 0);
3449        assert(buffer == [66, 0, 0, 0, 0, 0, 0, 0]);
3450
3451        buffer.write!float(25.0f, 4);
3452        assert(buffer == [66, 0, 0, 0, 65, 200, 0, 0]);
3453
3454        size_t index = 0;
3455        buffer.write!float(25.0f, &index);
3456        assert(buffer == [65, 200, 0, 0, 65, 200, 0, 0]);
3457        assert(index == 4);
3458
3459        buffer.write!float(32.0f, &index);
3460        assert(buffer == [65, 200, 0, 0, 66, 0, 0, 0]);
3461        assert(index == 8);
3462    }
3463
3464    {
3465        //double (64bit - 8x ubyte)
3466        ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
3467
3468        buffer.write!double(32.0, 0);
3469        assert(buffer == [64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
3470
3471        buffer.write!double(25.0, 8);
3472        assert(buffer == [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0]);
3473
3474        size_t index = 0;
3475        buffer.write!double(25.0, &index);
3476        assert(buffer == [64, 57, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0]);
3477        assert(index == 8);
3478
3479        buffer.write!double(32.0, &index);
3480        assert(buffer == [64, 57, 0, 0, 0, 0, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0]);
3481        assert(index == 16);
3482    }
3483
3484    {
3485        //enum
3486        ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
3487
3488        enum Foo
3489        {
3490            one = 10,
3491            two = 20,
3492            three = 30
3493        }
3494
3495        buffer.write!Foo(Foo.one, 0);
3496        assert(buffer == [0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0]);
3497
3498        buffer.write!Foo(Foo.two, 4);
3499        assert(buffer == [0, 0, 0, 10, 0, 0, 0, 20, 0, 0, 0, 0]);
3500
3501        buffer.write!Foo(Foo.three, 8);
3502        assert(buffer == [0, 0, 0, 10, 0, 0, 0, 20, 0, 0, 0, 30]);
3503
3504        size_t index = 0;
3505        buffer.write!Foo(Foo.three, &index);
3506        assert(buffer == [0, 0, 0, 30, 0, 0, 0, 20, 0, 0, 0, 30]);
3507        assert(index == 4);
3508
3509        buffer.write!Foo(Foo.one, &index);
3510        assert(buffer == [0, 0, 0, 30, 0, 0, 0, 10, 0, 0, 0, 30]);
3511        assert(index == 8);
3512
3513        buffer.write!Foo(Foo.two, &index);
3514        assert(buffer == [0, 0, 0, 30, 0, 0, 0, 10, 0, 0, 0, 20]);
3515        assert(index == 12);
3516    }
3517
3518    {
3519        //enum - bool
3520        ubyte[] buffer = [0, 0];
3521
3522        enum Bool: bool
3523        {
3524            bfalse = false,
3525            btrue = true,
3526        }
3527
3528        buffer.write!Bool(Bool.btrue, 0);
3529        assert(buffer == [1, 0]);
3530
3531        buffer.write!Bool(Bool.btrue, 1);
3532        assert(buffer == [1, 1]);
3533
3534        size_t index = 0;
3535        buffer.write!Bool(Bool.bfalse, &index);
3536        assert(buffer == [0, 1]);
3537        assert(index == 1);
3538
3539        buffer.write!Bool(Bool.bfalse, &index);
3540        assert(buffer == [0, 0]);
3541        assert(index == 2);
3542    }
3543
3544    {
3545        //enum - float
3546        ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0];
3547
3548        enum Float: float
3549        {
3550            one = 32.0f,
3551            two = 25.0f
3552        }
3553
3554        buffer.write!Float(Float.one, 0);
3555        assert(buffer == [66, 0, 0, 0, 0, 0, 0, 0]);
3556
3557        buffer.write!Float(Float.two, 4);
3558        assert(buffer == [66, 0, 0, 0, 65, 200, 0, 0]);
3559
3560        size_t index = 0;
3561        buffer.write!Float(Float.two, &index);
3562        assert(buffer == [65, 200, 0, 0, 65, 200, 0, 0]);
3563        assert(index == 4);
3564
3565        buffer.write!Float(Float.one, &index);
3566        assert(buffer == [65, 200, 0, 0, 66, 0, 0, 0]);
3567        assert(index == 8);
3568    }
3569
3570    {
3571        //enum - double
3572        ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
3573
3574        enum Double: double
3575        {
3576            one = 32.0,
3577            two = 25.0
3578        }
3579
3580        buffer.write!Double(Double.one, 0);
3581        assert(buffer == [64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
3582
3583        buffer.write!Double(Double.two, 8);
3584        assert(buffer == [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0]);
3585
3586        size_t index = 0;
3587        buffer.write!Double(Double.two, &index);
3588        assert(buffer == [64, 57, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0]);
3589        assert(index == 8);
3590
3591        buffer.write!Double(Double.one, &index);
3592        assert(buffer == [64, 57, 0, 0, 0, 0, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0]);
3593        assert(index == 16);
3594    }
3595
3596    {
3597        //enum - real
3598        ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
3599
3600        enum Real: real
3601        {
3602            one = 32.0,
3603            two = 25.0
3604        }
3605
3606        static assert(!__traits(compiles, buffer.write!Real(Real.one)));
3607    }
3608}
3609
3610
3611/++
3612    Takes an integral value, converts it to the given endianness, and appends
3613    it to the given range of $(D ubyte)s (using $(D put)) as a sequence of
3614    $(D T.sizeof) $(D ubyte)s starting at index. $(D hasSlicing!R) must be
3615    $(D true).
3616
3617    Params:
3618        T     = The integral type to convert the first $(D T.sizeof) bytes to.
3619        endianness = The endianness to write the bytes in.
3620        range = The range to _append to.
3621        value = The value to _append.
3622  +/
3623void append(T, Endian endianness = Endian.bigEndian, R)(R range, T value)
3624if (canSwapEndianness!T && isOutputRange!(R, ubyte))
3625{
3626    static if (endianness == Endian.bigEndian)
3627        immutable bytes = nativeToBigEndian!T(value);
3628    else
3629        immutable bytes = nativeToLittleEndian!T(value);
3630
3631    put(range, bytes[]);
3632}
3633
3634///
3635@safe unittest
3636{
3637    import std.array;
3638    auto buffer = appender!(const ubyte[])();
3639    buffer.append!ushort(261);
3640    assert(buffer.data == [1, 5]);
3641
3642    buffer.append!uint(369700095u);
3643    assert(buffer.data == [1, 5, 22, 9, 44, 255]);
3644
3645    buffer.append!ubyte(8);
3646    assert(buffer.data == [1, 5, 22, 9, 44, 255, 8]);
3647}
3648
3649@safe unittest
3650{
3651    import std.array;
3652    {
3653        //bool
3654        auto buffer = appender!(const ubyte[])();
3655
3656        buffer.append!bool(true);
3657        assert(buffer.data == [1]);
3658
3659        buffer.append!bool(false);
3660        assert(buffer.data == [1, 0]);
3661    }
3662
3663    {
3664        //char wchar dchar
3665        auto buffer = appender!(const ubyte[])();
3666
3667        buffer.append!char('a');
3668        assert(buffer.data == [97]);
3669
3670        buffer.append!char('b');
3671        assert(buffer.data == [97, 98]);
3672
3673        buffer.append!wchar('��');
3674        assert(buffer.data == [97, 98, 1, 5]);
3675
3676        buffer.append!dchar('��');
3677        assert(buffer.data == [97, 98, 1, 5, 0, 0, 1, 5]);
3678    }
3679
3680    {
3681        //float double
3682        auto buffer = appender!(const ubyte[])();
3683
3684        buffer.append!float(32.0f);
3685        assert(buffer.data == [66, 0, 0, 0]);
3686
3687        buffer.append!double(32.0);
3688        assert(buffer.data == [66, 0, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0]);
3689    }
3690
3691    {
3692        //enum
3693        auto buffer = appender!(const ubyte[])();
3694
3695        enum Foo
3696        {
3697            one = 10,
3698            two = 20,
3699            three = 30
3700        }
3701
3702        buffer.append!Foo(Foo.one);
3703        assert(buffer.data == [0, 0, 0, 10]);
3704
3705        buffer.append!Foo(Foo.two);
3706        assert(buffer.data == [0, 0, 0, 10, 0, 0, 0, 20]);
3707
3708        buffer.append!Foo(Foo.three);
3709        assert(buffer.data == [0, 0, 0, 10, 0, 0, 0, 20, 0, 0, 0, 30]);
3710    }
3711
3712    {
3713        //enum - bool
3714        auto buffer = appender!(const ubyte[])();
3715
3716        enum Bool: bool
3717        {
3718            bfalse = false,
3719            btrue = true,
3720        }
3721
3722        buffer.append!Bool(Bool.btrue);
3723        assert(buffer.data == [1]);
3724
3725        buffer.append!Bool(Bool.bfalse);
3726        assert(buffer.data == [1, 0]);
3727
3728        buffer.append!Bool(Bool.btrue);
3729        assert(buffer.data == [1, 0, 1]);
3730    }
3731
3732    {
3733        //enum - float
3734        auto buffer = appender!(const ubyte[])();
3735
3736        enum Float: float
3737        {
3738            one = 32.0f,
3739            two = 25.0f
3740        }
3741
3742        buffer.append!Float(Float.one);
3743        assert(buffer.data == [66, 0, 0, 0]);
3744
3745        buffer.append!Float(Float.two);
3746        assert(buffer.data == [66, 0, 0, 0, 65, 200, 0, 0]);
3747    }
3748
3749    {
3750        //enum - double
3751        auto buffer = appender!(const ubyte[])();
3752
3753        enum Double: double
3754        {
3755            one = 32.0,
3756            two = 25.0
3757        }
3758
3759        buffer.append!Double(Double.one);
3760        assert(buffer.data == [64, 64, 0, 0, 0, 0, 0, 0]);
3761
3762        buffer.append!Double(Double.two);
3763        assert(buffer.data == [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0]);
3764    }
3765
3766    {
3767        //enum - real
3768        auto buffer = appender!(const ubyte[])();
3769
3770        enum Real: real
3771        {
3772            one = 32.0,
3773            two = 25.0
3774        }
3775
3776        static assert(!__traits(compiles, buffer.append!Real(Real.one)));
3777    }
3778}
3779
3780@system unittest
3781{
3782    import std.array;
3783    import std.format : format;
3784    import std.meta;
3785    foreach (endianness; AliasSeq!(Endian.bigEndian, Endian.littleEndian))
3786    {
3787        auto toWrite = appender!(ubyte[])();
3788        alias Types = AliasSeq!(uint, int, long, ulong, short, ubyte, ushort, byte, uint);
3789        ulong[] values = [42, -11, long.max, 1098911981329L, 16, 255, 19012, 2, 17];
3790        assert(Types.length == values.length);
3791
3792        size_t index = 0;
3793        size_t length = 0;
3794        foreach (T; Types)
3795        {
3796            toWrite.append!(T, endianness)(cast(T) values[index++]);
3797            length += T.sizeof;
3798        }
3799
3800        auto toRead = toWrite.data;
3801        assert(toRead.length == length);
3802
3803        index = 0;
3804        foreach (T; Types)
3805        {
3806            assert(toRead.peek!(T, endianness)() == values[index], format("Failed Index: %s", index));
3807            assert(toRead.peek!(T, endianness)(0) == values[index], format("Failed Index: %s", index));
3808            assert(toRead.length == length,
3809                   format("Failed Index [%s], Actual Length: %s", index, toRead.length));
3810            assert(toRead.read!(T, endianness)() == values[index], format("Failed Index: %s", index));
3811            length -= T.sizeof;
3812            assert(toRead.length == length,
3813                   format("Failed Index [%s], Actual Length: %s", index, toRead.length));
3814            ++index;
3815        }
3816        assert(toRead.empty);
3817    }
3818}
3819
3820/**
3821Counts the number of set bits in the binary representation of $(D value).
3822For signed integers, the sign bit is included in the count.
3823*/
3824private uint countBitsSet(T)(T value) @nogc pure nothrow
3825if (isIntegral!T)
3826{
3827    // http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
3828    static if (T.sizeof == 8)
3829    {
3830        T c = value - ((value >> 1) & 0x55555555_55555555);
3831        c = ((c >> 2) & 0x33333333_33333333) + (c & 0x33333333_33333333);
3832        c = ((c >> 4) + c) & 0x0F0F0F0F_0F0F0F0F;
3833        c = ((c >> 8) + c) & 0x00FF00FF_00FF00FF;
3834        c = ((c >> 16) + c) & 0x0000FFFF_0000FFFF;
3835        c = ((c >> 32) + c) & 0x00000000_FFFFFFFF;
3836    }
3837    else static if (T.sizeof == 4)
3838    {
3839        T c = value - ((value >> 1) & 0x55555555);
3840        c = ((c >> 2) & 0x33333333) + (c & 0x33333333);
3841        c = ((c >> 4) + c) & 0x0F0F0F0F;
3842        c = ((c >> 8) + c) & 0x00FF00FF;
3843        c = ((c >> 16) + c) & 0x0000FFFF;
3844    }
3845    else static if (T.sizeof == 2)
3846    {
3847        uint c = value - ((value >> 1) & 0x5555);
3848        c = ((c >> 2) & 0x3333) + (c & 0X3333);
3849        c = ((c >> 4) + c) & 0x0F0F;
3850        c = ((c >> 8) + c) & 0x00FF;
3851    }
3852    else static if (T.sizeof == 1)
3853    {
3854        uint c = value - ((value >> 1) & 0x55);
3855        c = ((c >> 2) & 0x33) + (c & 0X33);
3856        c = ((c >> 4) + c) & 0x0F;
3857    }
3858    else
3859    {
3860        static assert(false, "countBitsSet only supports 1, 2, 4, or 8 byte sized integers.");
3861    }
3862    return cast(uint) c;
3863}
3864
3865@safe unittest
3866{
3867    assert(countBitsSet(1) == 1);
3868    assert(countBitsSet(0) == 0);
3869    assert(countBitsSet(int.min) == 1);
3870    assert(countBitsSet(uint.max) == 32);
3871}
3872
3873@safe unittest
3874{
3875    import std.meta;
3876    foreach (T; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong))
3877    {
3878        assert(countBitsSet(cast(T) 0) == 0);
3879        assert(countBitsSet(cast(T) 1) == 1);
3880        assert(countBitsSet(cast(T) 2) == 1);
3881        assert(countBitsSet(cast(T) 3) == 2);
3882        assert(countBitsSet(cast(T) 4) == 1);
3883        assert(countBitsSet(cast(T) 5) == 2);
3884        assert(countBitsSet(cast(T) 127) == 7);
3885        static if (isSigned!T)
3886        {
3887            assert(countBitsSet(cast(T)-1) == 8 * T.sizeof);
3888            assert(countBitsSet(T.min) == 1);
3889        }
3890        else
3891        {
3892            assert(countBitsSet(T.max) == 8 * T.sizeof);
3893        }
3894    }
3895    assert(countBitsSet(1_000_000) == 7);
3896    foreach (i; 0 .. 63)
3897        assert(countBitsSet(1UL << i) == 1);
3898}
3899
3900private struct BitsSet(T)
3901{
3902    static assert(T.sizeof <= 8, "bitsSet assumes T is no more than 64-bit.");
3903
3904@nogc pure nothrow:
3905
3906    this(T value, size_t startIndex = 0)
3907    {
3908        _value = value;
3909        // Further calculation is only valid and needed when the range is non-empty.
3910        if (!_value)
3911            return;
3912
3913        import core.bitop : bsf;
3914        immutable trailingZerosCount = bsf(value);
3915        _value >>>= trailingZerosCount;
3916        _index = startIndex + trailingZerosCount;
3917    }
3918
3919    @property size_t front()
3920    {
3921        return _index;
3922    }
3923
3924    @property bool empty() const
3925    {
3926        return !_value;
3927    }
3928
3929    void popFront()
3930    {
3931        assert(_value, "Cannot call popFront on empty range.");
3932
3933        _value >>>= 1;
3934        // Further calculation is only valid and needed when the range is non-empty.
3935        if (!_value)
3936            return;
3937
3938        import core.bitop : bsf;
3939        immutable trailingZerosCount = bsf(_value);
3940        _value >>>= trailingZerosCount;
3941        _index += trailingZerosCount + 1;
3942    }
3943
3944    @property auto save()
3945    {
3946        return this;
3947    }
3948
3949    @property size_t length()
3950    {
3951        return countBitsSet(_value);
3952    }
3953
3954    private T _value;
3955    private size_t _index;
3956}
3957
3958/**
3959Range that iterates the indices of the set bits in $(D value).
3960Index 0 corresponds to the least significant bit.
3961For signed integers, the highest index corresponds to the sign bit.
3962*/
3963auto bitsSet(T)(T value) @nogc pure nothrow
3964if (isIntegral!T)
3965{
3966    return BitsSet!T(value);
3967}
3968
3969///
3970@safe unittest
3971{
3972    import std.algorithm.comparison : equal;
3973    import std.range : iota;
3974
3975    assert(bitsSet(1).equal([0]));
3976    assert(bitsSet(5).equal([0, 2]));
3977    assert(bitsSet(-1).equal(iota(32)));
3978    assert(bitsSet(int.min).equal([31]));
3979}
3980
3981@safe unittest
3982{
3983    import std.algorithm.comparison : equal;
3984    import std.range : iota;
3985
3986    import std.meta;
3987    foreach (T; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong))
3988    {
3989        assert(bitsSet(cast(T) 0).empty);
3990        assert(bitsSet(cast(T) 1).equal([0]));
3991        assert(bitsSet(cast(T) 2).equal([1]));
3992        assert(bitsSet(cast(T) 3).equal([0, 1]));
3993        assert(bitsSet(cast(T) 4).equal([2]));
3994        assert(bitsSet(cast(T) 5).equal([0, 2]));
3995        assert(bitsSet(cast(T) 127).equal(iota(7)));
3996        static if (isSigned!T)
3997        {
3998            assert(bitsSet(cast(T)-1).equal(iota(8 * T.sizeof)));
3999            assert(bitsSet(T.min).equal([8 * T.sizeof - 1]));
4000        }
4001        else
4002        {
4003            assert(bitsSet(T.max).equal(iota(8 * T.sizeof)));
4004        }
4005    }
4006    assert(bitsSet(1_000_000).equal([6, 9, 14, 16, 17, 18, 19]));
4007    foreach (i; 0 .. 63)
4008        assert(bitsSet(1UL << i).equal([i]));
4009}
4010