1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.location.cts.asn1.base;
18 
19 /**
20  * Reads a stream of bits.
21  *
22  * <p>This class is not thread-safe.
23  *
24  */
25 public class BitStreamReader {
26   private static final int BITS_IN_BYTE = 8;
27 
28   private final byte[] buffer;
29   private int position = 0;
30   private int bitsRead = 0;
31 
BitStreamReader(byte[] bytes)32   public BitStreamReader(byte[] bytes) {
33     buffer = bytes;
34   }
35 
36   /**
37    * Returns true if the next bit in the stream is set.
38    * @throws IndexOutOfBoundsException if there is no more data.
39    */
readBit()40   public boolean readBit() {
41     bitsRead++;
42     if (bitsRead > BITS_IN_BYTE) {
43       position++;
44       bitsRead = 1;
45     }
46     return ((buffer[position] >> (BITS_IN_BYTE - bitsRead)) & 1) == 1;
47   }
48 
49   /**
50    * Returns true if there is another readable bit in the stream.
51    */
hasBit()52   public boolean hasBit() {
53     return position + 1 < buffer.length
54            || (bitsRead < BITS_IN_BYTE && position < buffer.length);
55   }
56 
spoolToByteBoundary()57   public void spoolToByteBoundary() {
58     if (bitsRead == 0) {
59       return;
60     }
61     bitsRead = 0;
62     position++;
63   }
64 
65   /**
66    * Returns next byte's worth of data (8 bits) from the stream.
67    * @throws IndexOutOfBoundsException if there is no more data.
68    */
readByte()69   public byte readByte() {
70     int mask = (1 << (8 - bitsRead)) - 1;
71     byte result = (byte) ((buffer[position] & mask) << bitsRead);
72     position++;
73     if (bitsRead > 0) {
74       result = (byte) (result | (buffer[position] & 0xFF) >>> (8 - bitsRead));
75     }
76     return result;
77   }
78 
79   /**
80    * Returns next {@code howMany} bits as the low bits in the returned byte.
81    * @throws IndexOutOfBoundsException if there is no more data.
82    */
readLowBits(int howMany)83   public int readLowBits(int howMany) {
84     int result = 0;
85     for (int i = 0; i < howMany; i++) {
86       result <<= 1;
87       result |= (readBit() ? 1 : 0);
88     }
89     return result;
90   }
91 }
92