1 module barcode.qr.util;
2 
3 // std.bitmanip.BitArray store bits in other order
4 
5 struct BitBuffer
6 {
7     ubyte[] data;
8     int length;
9 
10     alias getBytes = data;
11 
12 pure @safe:
13     void appendBits(long val, int len)
14     {
15         auto nlen = length + len;
16         reserve(nlen);
17         for (int i = len - 1; i >= 0; i--, length++)
18             data[length>>3] |= ((val >> i) & 1) << (7-(length&7));
19     }
20 
21     void reserve(int nlen)
22     {
23         if (nlen > data.length * 8)
24             data.length += (nlen - data.length * 8 + 7) / 8;
25     }
26 
27     void appendData(const(ubyte)[] arr, int len)
28     {
29         auto nlen = length + len;
30         reserve(nlen);
31         for (int i = 0; i < len; i++, length++)
32         {
33             int bit = (arr[i >> 3] >> (7-(i&7))) & 1;
34             data[length>>3] |= bit << (7-(length & 7));
35         }
36     }
37 
38     bool opIndex(size_t i) const
39     { return cast(bool)((data[i>>3] >> (7-(i&7))) & 1); }
40 
41     void opIndexAssign(int val, size_t i)
42     {
43         auto bit = cast(bool)val;
44         data[i>>3] |= bit << (7-(i&7));
45     }
46 }
47 
48 @safe
49 unittest
50 {
51     BitBuffer arr;
52     arr.appendBits(0b101101, 4);
53     assert (arr.length == 4);
54     assert (arr[0] == true);
55     assert (arr[1] == true);
56     assert (arr[2] == false);
57     assert (arr[3] == true);
58     arr.appendBits(0b101, 3);
59     assert (arr.length == 7);
60     assert (arr[4] == true);
61     assert (arr[5] == false);
62     assert (arr[6] == true);
63 
64     arr[5] = 1;
65     assert (arr[5] == true);
66 }