Committed C# port from Mohamad
[zxing.git] / csharp / common / BitArray.cs
1 /*\r
2 * Copyright 2008 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 namespace com.google.zxing.common\r
17 {\r
18     using System;\r
19     using System.Text;\r
20 \r
21     /// <summary> A class which wraps a 2D array of bytes. The default usage is signed. If you want to use it as a\r
22     /// unsigned container, it's up to you to do byteValue & 0xff at each location.\r
23     /// *\r
24     /// JAVAPORT: I'm not happy about the argument ordering throughout the file, as I always like to have\r
25     /// the horizontal component first, but this is for compatibility with the C++ code. The original\r
26     /// code was a 2D array of ints, but since it only ever gets assigned -1, 0, and 1, I'm going to use\r
27     /// less memory and go with bytes.\r
28     /// *\r
29     /// </summary>\r
30     /// <author>  dswitkin@google.com (Daniel Switkin)\r
31     /// \r
32     /// </author>\r
33     public sealed class BitArray\r
34     {\r
35       // TODO: I have changed these members to be public so ProGuard can inline get() and set(). Ideally\r
36       // they'd be private and we'd use the -allowaccessmodification flag, but Dalvik rejects the\r
37       // resulting binary at runtime on Android. If we find a solution to this, these should be changed\r
38       // back to private.\r
39       public int[] bits;\r
40       public int Size;\r
41 \r
42       public BitArray(int size) {\r
43         if (size < 1) {\r
44           throw new Exception("size must be at least 1");\r
45         }\r
46         this.Size = size;\r
47         this.bits = makeArray(size);\r
48       }\r
49 \r
50       public int getSize() {\r
51         return Size;\r
52       }\r
53 \r
54       /**\r
55        * @param i bit to get\r
56        * @return true iff bit i is set\r
57        */\r
58       public bool get(int i) {\r
59         return (bits[i >> 5] & (1 << (i & 0x1F))) != 0;\r
60       }\r
61 \r
62       /**\r
63        * Sets bit i.\r
64        *\r
65        * @param i bit to set\r
66        */\r
67       public void set(int i) {\r
68         bits[i >> 5] |= 1 << (i & 0x1F);\r
69       }\r
70 \r
71       /**\r
72        * Sets a block of 32 bits, starting at bit i.\r
73        *\r
74        * @param i first bit to set\r
75        * @param newBits the new value of the next 32 bits. Note again that the least-significant bit\r
76        * corresponds to bit i, the next-least-significant to i+1, and so on.\r
77        */\r
78       public void setBulk(int i, int newBits) {\r
79         bits[i >> 5] = newBits;\r
80       }\r
81 \r
82       /**\r
83        * Clears all bits (sets to false).\r
84        */\r
85       public void clear() {\r
86         int max = bits.Length;\r
87         for (int i = 0; i < max; i++) {\r
88           bits[i] = 0;\r
89         }\r
90       }\r
91 \r
92       /**\r
93        * Efficient method to check if a range of bits is set, or not set.\r
94        *\r
95        * @param start start of range, inclusive.\r
96        * @param end end of range, exclusive\r
97        * @param value if true, checks that bits in range are set, otherwise checks that they are not set\r
98        * @return true iff all bits are set or not set in range, according to value argument\r
99        * @throws IllegalArgumentException if end is less than or equal to start\r
100        */\r
101       public bool isRange(int start, int end, bool value) {\r
102         if (end < start) {\r
103           throw new Exception();\r
104         }\r
105         if (end == start) {\r
106           return true; // empty range matches\r
107         }\r
108         end--; // will be easier to treat this as the last actually set bit -- inclusive    \r
109         int firstInt = start >> 5;\r
110         int lastInt = end >> 5;\r
111         for (int i = firstInt; i <= lastInt; i++) {\r
112           int firstBit = i > firstInt ? 0 : start & 0x1F;\r
113           int lastBit = i < lastInt ? 31 : end & 0x1F;\r
114           int mask;\r
115           if (firstBit == 0 && lastBit == 31) {\r
116             mask = -1;\r
117           } else {\r
118             mask = 0;\r
119             for (int j = firstBit; j <= lastBit; j++) {\r
120               mask |= 1 << j;\r
121             }\r
122           }\r
123 \r
124           // Return false if we're looking for 1s and the masked bits[i] isn't all 1s (that is,\r
125           // equals the mask, or we're looking for 0s and the masked portion is not all 0s\r
126           if ((bits[i] & mask) != (value ? mask : 0)) {\r
127             return false;\r
128           }\r
129         }\r
130         return true;\r
131       }\r
132 \r
133       /**\r
134        * @return underlying array of ints. The first element holds the first 32 bits, and the least\r
135        *         significant bit is bit 0.\r
136        */\r
137       public int[] getBitArray() {\r
138         return bits;\r
139       }\r
140 \r
141       /**\r
142        * Reverses all bits in the array.\r
143        */\r
144       public void reverse() {\r
145         int[] newBits = makeArray(Size);\r
146         int max = newBits.Length;\r
147         for (int i = 0; i < max; i++) {\r
148           newBits[i] = 0;\r
149         }\r
150         int size = this.Size;\r
151         for (int i = 0; i < size; i++) {\r
152           if (get(size - i - 1)) {\r
153             newBits[i >> 5] |= 1 << (i & 0x1F);\r
154           }\r
155         }\r
156         bits = newBits;\r
157       }\r
158 \r
159       private static int[] makeArray(int size) {\r
160         int arraySize = size >> 5;\r
161         if ((size & 0x1F) != 0) {\r
162           arraySize++;\r
163         }\r
164         return new int[arraySize];\r
165       }\r
166       \r
167       public String toString() {\r
168         StringBuilder  result = new StringBuilder(Size);\r
169         for (int i = 0; i < Size; i++) {\r
170           if (i % 8 == 0) {\r
171             result.Append(' ');\r
172           }\r
173           result.Append(get(i) ? 'X' : '.');\r
174         }\r
175         return result.ToString();\r
176       }\r
177         }\r
178 }