Issue 508
[zxing.git] / core / src / com / google / zxing / common / BitSource.java
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 \r
17 package com.google.zxing.common;\r
18 \r
19 /**\r
20  * <p>This provides an easy abstraction to read bits at a time from a sequence of bytes, where the\r
21  * number of bits read is not often a multiple of 8.</p>\r
22  *\r
23  * <p>This class is thread-safe but not reentrant. Unless the caller modifies the bytes array\r
24  * it passed in, in which case all bets are off.</p>\r
25  *\r
26  * @author Sean Owen\r
27  */\r
28 public final class BitSource {\r
29 \r
30   private final byte[] bytes;\r
31   private int byteOffset;\r
32   private int bitOffset;\r
33 \r
34   /**\r
35    * @param bytes bytes from which this will read bits. Bits will be read from the first byte first.\r
36    * Bits are read within a byte from most-significant to least-significant bit.\r
37    */\r
38   public BitSource(byte[] bytes) {\r
39     this.bytes = bytes;\r
40   }\r
41 \r
42   /**\r
43    * @param numBits number of bits to read\r
44    * @return int representing the bits read. The bits will appear as the least-significant\r
45    *         bits of the int\r
46    * @throws IllegalArgumentException if numBits isn't in [1,32]\r
47    */\r
48   public int readBits(int numBits) {\r
49     if (numBits < 1 || numBits > 32) {\r
50       throw new IllegalArgumentException();\r
51     }\r
52 \r
53     int result = 0;\r
54 \r
55     // First, read remainder from current byte\r
56     if (bitOffset > 0) {\r
57       int bitsLeft = 8 - bitOffset;\r
58       int toRead = numBits < bitsLeft ? numBits : bitsLeft;\r
59       int bitsToNotRead = bitsLeft - toRead;\r
60       int mask = (0xFF >> (8 - toRead)) << bitsToNotRead;\r
61       result = (bytes[byteOffset] & mask) >> bitsToNotRead;\r
62       numBits -= toRead;\r
63       bitOffset += toRead;\r
64       if (bitOffset == 8) {\r
65         bitOffset = 0;\r
66         byteOffset++;\r
67       }\r
68     }\r
69 \r
70     // Next read whole bytes\r
71     if (numBits > 0) {\r
72       while (numBits >= 8) {\r
73         result = (result << 8) | (bytes[byteOffset] & 0xFF);\r
74         byteOffset++;\r
75         numBits -= 8;\r
76       }\r
77 \r
78       // Finally read a partial byte\r
79       if (numBits > 0) {\r
80         int bitsToNotRead = 8 - numBits;\r
81         int mask = (0xFF >> bitsToNotRead) << bitsToNotRead;\r
82         result = (result << numBits) | ((bytes[byteOffset] & mask) >> bitsToNotRead);\r
83         bitOffset += numBits;\r
84       }\r
85     }\r
86 \r
87     return result;\r
88   }\r
89 \r
90   /**\r
91    * @return number of bits that can be read successfully\r
92    */\r
93   public int available() {\r
94     return 8 * (bytes.length - byteOffset) - bitOffset;\r
95   }\r
96 \r
97 }\r