git-svn-id: http://zxing.googlecode.com/svn/trunk@6 59b500cc-1b3d-0410-9834-0bbf25fbcc57
[zxing.git] / core / src / com / google / zxing / qrcode / decoder / BitSource.java
1 /*\r
2  * Copyright 2007 Google Inc.\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.qrcode.decoder;\r
18 \r
19 /**\r
20  * 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.\r
22  *\r
23  * @author srowen@google.com (Sean Owen)\r
24  */\r
25 final class BitSource {\r
26 \r
27   private final byte[] bytes;\r
28   private int byteOffset;\r
29   private int bitOffset;\r
30 \r
31   BitSource(byte[] bytes) {\r
32     this.bytes = bytes;\r
33   }\r
34 \r
35   /**\r
36    * @throws IllegalArgumentException if numBits isn't in [1,32]\r
37    */\r
38   int readBits(int numBits) {\r
39     if (numBits < 1 || numBits > 32) {\r
40       throw new IllegalArgumentException();\r
41     }\r
42 \r
43     int result = 0;\r
44 \r
45     // First, read remainder from current byte\r
46     if (bitOffset > 0) {\r
47       int bitsLeft = 8 - bitOffset;\r
48       int toRead = numBits < bitsLeft ? numBits : bitsLeft;\r
49       int bitsToNotRead = bitsLeft - toRead;\r
50       int mask = (0xFF >> (8 - toRead)) << bitsToNotRead;\r
51       result = (bytes[byteOffset] & mask) >> bitsToNotRead;\r
52       numBits -= toRead;\r
53       bitOffset += toRead;\r
54       if (bitOffset == 8) {\r
55         bitOffset = 0;\r
56         byteOffset++;\r
57       }\r
58     }\r
59 \r
60     // Next read whole bytes\r
61     if (numBits > 0) {\r
62       while (numBits >= 8) {\r
63         result = (result << 8) | (bytes[byteOffset] & 0xFF);\r
64         byteOffset++;\r
65         numBits -= 8;\r
66       }\r
67 \r
68       // Finally read a partial byte\r
69       if (numBits > 0) {\r
70         int bitsToNotRead = 8 - numBits;\r
71         int mask = (0xFF >> bitsToNotRead) << bitsToNotRead;\r
72         result = (result << numBits) | ((bytes[byteOffset] & mask) >> bitsToNotRead);\r
73         bitOffset += numBits;\r
74       }\r
75     }\r
76 \r
77     return result;\r
78   }\r
79 \r
80   int available() {\r
81     return 8 * (bytes.length - byteOffset) - bitOffset;\r
82   }\r
83 \r
84 }\r