Rev 2976 |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/*
* Copyright (C) 2008 Steve Ratcliffe
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* Author: Steve Ratcliffe
* Create date: 29-Aug-2008
*/
package uk.me.parabola.imgfmt.app;
/**
* Read an array as a bit stream.
*
* @author Steve Ratcliffe
*/
public class BitReader
{
private final byte[] buf
;
private int bitPosition
;
public BitReader
(byte[] buf
) {
this.
buf = buf
;
}
public boolean get1
() {
int off = bitPosition
% 8;
byte b = buf
[bitPosition /
8];
bitPosition++
;
return ((b
>> off
) & 1) ==
1;
}
public int get
(int n
) {
int res =
0;
int pos =
0;
while (pos
< n
) {
int index = bitPosition /
8;
int off = bitPosition
% 8;
byte b = buf
[index
];
b
>>= off
;
int nbits = n - pos
;
if (nbits
> (8-off
))
nbits =
8 - off
;
int mask =
((1 << nbits
) -
1);
res |=
((b
& mask
) << pos
);
pos += nbits
;
bitPosition += nbits
;
}
return res
;
}
/**
* Get a signed quantity.
*
* The sign bit is the last bit in the field.
*
* @param n The field width, including the sign bit.
* @return A signed number.
*/
public int sget
(int n
) {
int res = get
(n
);
int top =
1 << (n -
1);
if ((res
& top
) !=
0) {
int mask = top -
1;
res = ~mask | res
;
}
return res
;
}
/**
* Get a signed n-bit value, treating 1 << (n-1) as a flag to read another signed n-bit value
* for extended range.
*/
public int sget2
(int n
) {
int top =
1 << (n -
1);
int mask = top -
1;
int base =
0;
int res = get
(n
);
while (res == top
) {
// Add to the base value, and read another
base += mask
;
res = get
(n
);
}
// The final byte determines the sign of the result. Add or subtract the base as
// appropriate.
if ((res
& top
) ==
0)
res += base
;
else
res =
(res | ~mask
) - base
; // Make negative and subtract the base
return res
;
}
public int getBitPosition
() {
return bitPosition
;
}
public int getNumberOfBits
() {
return buf.
length * 8;
}
/**
* Debugging routine that returns the remainder of the stream as a string.
* The bits are in little endian order, so that numbers can be read from left
* to right, although the whole string has to read from right to left.
*
* @return A string in binary.
*/
public String remainder
() {
int save = bitPosition
;
StringBuilder sb =
new StringBuilder();
while (bitPosition
< buf.
length * 8) {
sb.
insert(0, get1
() ? "1" :
"0");
}
bitPosition = save
;
return sb.
toString();
}
}