Committed C# port from Mohamad
[zxing.git] / csharp / qrcode / encoder / BitVector.cs
1 /*\r
2 * Copyright 2007 ZXing authors\r
3 *\r
4 * Licensed under the Apache License, Version 2.0 (the "License");\r
5 * you may not use this file except in compliance with the License.\r
6 * You may obtain a copy of the License at\r
7 *\r
8 *      http://www.apache.org/licenses/LICENSE-2.0\r
9 *\r
10 * Unless required by applicable law or agreed to in writing, software\r
11 * distributed under the License is distributed on an "AS IS" BASIS,\r
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
13 * See the License for the specific language governing permissions and\r
14 * limitations under the License.\r
15 */\r
16 using System;\r
17 using System.Text;\r
18 using com.google.zxing;\r
19 using com.google.zxing.common;\r
20 \r
21 namespace com.google.zxing.qrcode.encoder\r
22 {\r
23     public sealed class BitVector { \r
24     \r
25           private int sizeInBits;\r
26           private sbyte[] array;\r
27 \r
28           // For efficiency, start out with some room to work.\r
29           private static int DEFAULT_SIZE_IN_BYTES = 32;\r
30 \r
31           public BitVector() {\r
32             sizeInBits = 0;\r
33             array = new sbyte[DEFAULT_SIZE_IN_BYTES];\r
34           }\r
35 \r
36           // Return the bit value at "index".\r
37           public int at(int index) {\r
38             if (index < 0 || index >= sizeInBits) {\r
39               throw new ArgumentException("Bad index: " + index);\r
40             }\r
41             int value = array[index >> 3] & 0xff;\r
42             return (value >> (7 - (index & 0x7))) & 1;\r
43           }\r
44 \r
45           // Return the number of bits in the bit vector.\r
46           public int size() {\r
47             return sizeInBits;\r
48           }\r
49 \r
50           // Return the number of bytes in the bit vector.\r
51           public int sizeInBytes() {\r
52             return (sizeInBits + 7) >> 3;\r
53           }\r
54 \r
55           // Append one bit to the bit vector.\r
56           public void appendBit(int bit) {\r
57             if (!(bit == 0 || bit == 1)) {\r
58               throw new ArgumentException("Bad bit");\r
59             }\r
60             int numBitsInLastByte = sizeInBits & 0x7;\r
61             // We'll expand array if we don't have bits in the last byte.\r
62             if (numBitsInLastByte == 0) {\r
63               appendByte(0);\r
64               sizeInBits -= 8;\r
65             }\r
66             // Modify the last byte.\r
67             array[sizeInBits >> 3] |= (sbyte)(bit << (7 - numBitsInLastByte));\r
68             ++sizeInBits;\r
69           }\r
70 \r
71           // Append "numBits" bits in "value" to the bit vector.\r
72           // REQUIRES: 0<= numBits <= 32.\r
73           //\r
74           // Examples:\r
75           // - appendBits(0x00, 1) adds 0.\r
76           // - appendBits(0x00, 4) adds 0000.\r
77           // - appendBits(0xff, 8) adds 11111111.\r
78           public void appendBits(int value, int numBits) {\r
79             if (numBits < 0 || numBits > 32) {\r
80               throw new ArgumentException("Num bits must be between 0 and 32");\r
81             }\r
82             int numBitsLeft = numBits;\r
83             while (numBitsLeft > 0) {\r
84               // Optimization for byte-oriented appending.\r
85               if ((sizeInBits & 0x7) == 0 && numBitsLeft >= 8) {\r
86                 int newByte = (value >> (numBitsLeft - 8)) & 0xff;\r
87                 appendByte(newByte);\r
88                 numBitsLeft -= 8;\r
89               } else {\r
90                 int bit = (value >> (numBitsLeft - 1)) & 1;\r
91                 appendBit(bit);\r
92                 --numBitsLeft;\r
93               }\r
94             }\r
95           }\r
96 \r
97           // Append "bits".\r
98           public void appendBitVector(BitVector bits) {\r
99             int size = bits.size();\r
100             for (int i = 0; i < size; ++i) {\r
101               appendBit(bits.at(i));\r
102             }\r
103           }\r
104 \r
105           // Modify the bit vector by XOR'ing with "other"\r
106           public void xor(BitVector other) {\r
107             if (sizeInBits != other.size()) {\r
108               throw new ArgumentException("BitVector sizes don't match");\r
109             }\r
110             int sizeInBytes = (sizeInBits + 7) >> 3;\r
111             for (int i = 0; i < sizeInBytes; ++i) {\r
112               // The last byte could be incomplete (i.e. not have 8 bits in\r
113               // it) but there is no problem since 0 XOR 0 == 0.\r
114               array[i] ^= other.array[i];\r
115             }\r
116           }\r
117 \r
118           // Return String like "01110111" for debugging.\r
119           public String toString() {\r
120               StringBuilder result = new StringBuilder(sizeInBits);\r
121             for (int i = 0; i < sizeInBits; ++i) {\r
122               if (at(i) == 0) {\r
123                 result.Append('0');\r
124               } else if (at(i) == 1) {\r
125                 result.Append('1');\r
126               } else {\r
127                 throw new ArgumentException("Byte isn't 0 or 1");\r
128               }\r
129             }\r
130             return result.ToString();\r
131           }\r
132 \r
133           // Callers should not assume that array.length is the exact number of bytes needed to hold\r
134           // sizeInBits - it will typically be larger for efficiency.\r
135           public sbyte[] getArray() {\r
136             return array;\r
137           }\r
138 \r
139           // Add a new byte to the end, possibly reallocating and doubling the size of the array if we've\r
140           // run out of room.\r
141           private void appendByte(int value) {\r
142             if ((sizeInBits >> 3) == array.Length) {\r
143               sbyte[] newArray = new sbyte[(array.Length << 1)];\r
144               System.Array.Copy (array, 0, newArray, 0, array.Length);\r
145               array = newArray;\r
146             }\r
147             array[sizeInBits >> 3] = (sbyte) value;\r
148             sizeInBits += 8;\r
149           }\r
150     }\r
151 }