summaryrefslogtreecommitdiff
path: root/songdbj/de/jarnbjo/util/io/ByteArrayBitInputStream.java
diff options
context:
space:
mode:
Diffstat (limited to 'songdbj/de/jarnbjo/util/io/ByteArrayBitInputStream.java')
-rw-r--r--songdbj/de/jarnbjo/util/io/ByteArrayBitInputStream.java352
1 files changed, 352 insertions, 0 deletions
diff --git a/songdbj/de/jarnbjo/util/io/ByteArrayBitInputStream.java b/songdbj/de/jarnbjo/util/io/ByteArrayBitInputStream.java
new file mode 100644
index 0000000000..9c84c7daca
--- /dev/null
+++ b/songdbj/de/jarnbjo/util/io/ByteArrayBitInputStream.java
@@ -0,0 +1,352 @@
1/*
2 * $ProjectName$
3 * $ProjectRevision$
4 * -----------------------------------------------------------
5 * $Id$
6 * -----------------------------------------------------------
7 *
8 * $Author$
9 *
10 * Description:
11 *
12 * Copyright 2002-2003 Tor-Einar Jarnbjo
13 * -----------------------------------------------------------
14 *
15 * Change History
16 * -----------------------------------------------------------
17 * $Log$
18 * Revision 1.1 2005/07/11 15:42:36 hcl
19 * Songdb java version, source. only 1.5 compatible
20 *
21 * Revision 1.1.1.1 2004/04/04 22:09:12 shred
22 * First Import
23 *
24 * Revision 1.3 2003/04/10 19:48:31 jarnbjo
25 * no message
26 *
27 * Revision 1.2 2003/03/16 01:11:39 jarnbjo
28 * no message
29 *
30 * Revision 1.1 2003/03/03 21:02:20 jarnbjo
31 * no message
32 *
33 */
34
35package de.jarnbjo.util.io;
36
37import java.io.IOException;
38
39/**
40 * Implementation of the <code>BitInputStream</code> interface,
41 * using a byte array as data source.
42*/
43
44public class ByteArrayBitInputStream implements BitInputStream {
45
46 private byte[] source;
47 private byte currentByte;
48
49 private int endian;
50
51 private int byteIndex=0;
52 private int bitIndex=0;
53
54 public ByteArrayBitInputStream(byte[] source) {
55 this(source, LITTLE_ENDIAN);
56 }
57
58 public ByteArrayBitInputStream(byte[] source, int endian) {
59 this.endian=endian;
60 this.source=source;
61 currentByte=source[0];
62 bitIndex=(endian==LITTLE_ENDIAN)?0:7;
63 }
64
65 public boolean getBit() throws IOException {
66 if(endian==LITTLE_ENDIAN) {
67 if(bitIndex>7) {
68 bitIndex=0;
69 currentByte=source[++byteIndex];
70 }
71 return (currentByte&(1<<(bitIndex++)))!=0;
72 }
73 else {
74 if(bitIndex<0) {
75 bitIndex=7;
76 currentByte=source[++byteIndex];
77 }
78 return (currentByte&(1<<(bitIndex--)))!=0;
79 }
80 }
81
82 public int getInt(int bits) throws IOException {
83 if(bits>32) {
84 throw new IllegalArgumentException("Argument \"bits\" must be <= 32");
85 }
86 int res=0;
87 if(endian==LITTLE_ENDIAN) {
88 for(int i=0; i<bits; i++) {
89 if(getBit()) {
90 res|=(1<<i);
91 }
92 }
93 }
94 else {
95 if(bitIndex<0) {
96 bitIndex=7;
97 currentByte=source[++byteIndex];
98 }
99 if(bits<=bitIndex+1) {
100 int ci=((int)currentByte)&0xff;
101 int offset=1+bitIndex-bits;
102 int mask=((1<<bits)-1)<<offset;
103 res=(ci&mask)>>offset;
104 bitIndex-=bits;
105 }
106 else {
107 res=(((int)currentByte)&0xff&((1<<(bitIndex+1))-1))<<(bits-bitIndex-1);
108 bits-=bitIndex+1;
109 currentByte=source[++byteIndex];
110 while(bits>=8) {
111 bits-=8;
112 res|=(((int)source[byteIndex])&0xff)<<bits;
113 currentByte=source[++byteIndex];
114 }
115 if(bits>0) {
116 int ci=((int)source[byteIndex])&0xff;
117 res|=(ci>>(8-bits))&((1<<bits)-1);
118 bitIndex=7-bits;
119 }
120 else {
121 currentByte=source[--byteIndex];
122 bitIndex=-1;
123 }
124 }
125 }
126
127 return res;
128 }
129
130 public int getSignedInt(int bits) throws IOException {
131 int raw=getInt(bits);
132 if(raw>=1<<(bits-1)) {
133 raw-=1<<bits;
134 }
135 return raw;
136 }
137
138 public int getInt(HuffmanNode root) throws IOException {
139 while(root.value==null) {
140 if(bitIndex>7) {
141 bitIndex=0;
142 currentByte=source[++byteIndex];
143 }
144 root=(currentByte&(1<<(bitIndex++)))!=0?root.o1:root.o0;
145 }
146 return root.value.intValue();
147 }
148
149 public long getLong(int bits) throws IOException {
150 if(bits>64) {
151 throw new IllegalArgumentException("Argument \"bits\" must be <= 64");
152 }
153 long res=0;
154 if(endian==LITTLE_ENDIAN) {
155 for(int i=0; i<bits; i++) {
156 if(getBit()) {
157 res|=(1L<<i);
158 }
159 }
160 }
161 else {
162 for(int i=bits-1; i>=0; i--) {
163 if(getBit()) {
164 res|=(1L<<i);
165 }
166 }
167 }
168 return res;
169 }
170
171 /**
172 * <p>reads an integer encoded as "signed rice" as described in
173 * the FLAC audio format specification</p>
174 *
175 * <p><b>not supported for little endian</b></p>
176 *
177 * @param order
178 * @return the decoded integer value read from the stream
179 *
180 * @throws IOException if an I/O error occurs
181 * @throws UnsupportedOperationException if the method is not supported by the implementation
182 */
183
184 public int readSignedRice(int order) throws IOException {
185
186 int msbs=-1, lsbs=0, res=0;
187
188 if(endian==LITTLE_ENDIAN) {
189 // little endian
190 throw new UnsupportedOperationException("ByteArrayBitInputStream.readSignedRice() is only supported in big endian mode");
191 }
192 else {
193 // big endian
194
195 byte cb=source[byteIndex];
196 do {
197 msbs++;
198 if(bitIndex<0) {
199 bitIndex=7;
200 byteIndex++;
201 cb=source[byteIndex];
202 }
203 } while((cb&(1<<bitIndex--))==0);
204
205 int bits=order;
206
207 if(bitIndex<0) {
208 bitIndex=7;
209 byteIndex++;
210 }
211 if(bits<=bitIndex+1) {
212 int ci=((int)source[byteIndex])&0xff;
213 int offset=1+bitIndex-bits;
214 int mask=((1<<bits)-1)<<offset;
215 lsbs=(ci&mask)>>offset;
216 bitIndex-=bits;
217 }
218 else {
219 lsbs=(((int)source[byteIndex])&0xff&((1<<(bitIndex+1))-1))<<(bits-bitIndex-1);
220 bits-=bitIndex+1;
221 byteIndex++;
222 while(bits>=8) {
223 bits-=8;
224 lsbs|=(((int)source[byteIndex])&0xff)<<bits;
225 byteIndex++;
226 }
227 if(bits>0) {
228 int ci=((int)source[byteIndex])&0xff;
229 lsbs|=(ci>>(8-bits))&((1<<bits)-1);
230 bitIndex=7-bits;
231 }
232 else {
233 byteIndex--;
234 bitIndex=-1;
235 }
236 }
237
238 res=(msbs<<order)|lsbs;
239 }
240
241 return (res&1)==1?-(res>>1)-1:(res>>1);
242 }
243
244 /**
245 * <p>fills the array from <code>offset</code> with <code>len</code>
246 * integers encoded as "signed rice" as described in
247 * the FLAC audio format specification</p>
248 *
249 * <p><b>not supported for little endian</b></p>
250 *
251 * @param order
252 * @param buffer
253 * @param offset
254 * @param len
255 * @return the decoded integer value read from the stream
256 *
257 * @throws IOException if an I/O error occurs
258 * @throws UnsupportedOperationException if the method is not supported by the implementation
259 */
260
261 public void readSignedRice(int order, int[] buffer, int off, int len) throws IOException {
262
263 if(endian==LITTLE_ENDIAN) {
264 // little endian
265 throw new UnsupportedOperationException("ByteArrayBitInputStream.readSignedRice() is only supported in big endian mode");
266 }
267 else {
268 // big endian
269 for(int i=off; i<off+len; i++) {
270
271 int msbs=-1, lsbs=0;
272
273 byte cb=source[byteIndex];
274 do {
275 msbs++;
276 if(bitIndex<0) {
277 bitIndex=7;
278 byteIndex++;
279 cb=source[byteIndex];
280 }
281 } while((cb&(1<<bitIndex--))==0);
282
283 int bits=order;
284
285 if(bitIndex<0) {
286 bitIndex=7;
287 byteIndex++;
288 }
289 if(bits<=bitIndex+1) {
290 int ci=((int)source[byteIndex])&0xff;
291 int offset=1+bitIndex-bits;
292 int mask=((1<<bits)-1)<<offset;
293 lsbs=(ci&mask)>>offset;
294 bitIndex-=bits;
295 }
296 else {
297 lsbs=(((int)source[byteIndex])&0xff&((1<<(bitIndex+1))-1))<<(bits-bitIndex-1);
298 bits-=bitIndex+1;
299 byteIndex++;
300 while(bits>=8) {
301 bits-=8;
302 lsbs|=(((int)source[byteIndex])&0xff)<<bits;
303 byteIndex++;
304 }
305 if(bits>0) {
306 int ci=((int)source[byteIndex])&0xff;
307 lsbs|=(ci>>(8-bits))&((1<<bits)-1);
308 bitIndex=7-bits;
309 }
310 else {
311 byteIndex--;
312 bitIndex=-1;
313 }
314 }
315
316 int res=(msbs<<order)|lsbs;
317 buffer[i]=(res&1)==1?-(res>>1)-1:(res>>1);
318 }
319 }
320 }
321
322 public void align() {
323 if(endian==BIG_ENDIAN && bitIndex>=0) {
324 bitIndex=7;
325 byteIndex++;
326 }
327 else if(endian==LITTLE_ENDIAN && bitIndex<=7) {
328 bitIndex=0;
329 byteIndex++;
330 }
331 }
332
333 public void setEndian(int endian) {
334 if(this.endian==BIG_ENDIAN && endian==LITTLE_ENDIAN) {
335 bitIndex=0;
336 byteIndex++;
337 }
338 else if(this.endian==LITTLE_ENDIAN && endian==BIG_ENDIAN) {
339 bitIndex=7;
340 byteIndex++;
341 }
342 this.endian=endian;
343 }
344
345 /**
346 * @return the byte array used as a source for this instance
347 */
348
349 public byte[] getSource() {
350 return source;
351 }
352} \ No newline at end of file