expand BitInputStream to allow reading of up to 63 bits at once
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/compress/trunk@1654638 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/main/java/org/apache/commons/compress/archivers/zip/BitStream.java b/src/main/java/org/apache/commons/compress/archivers/zip/BitStream.java
index 3064641..d40c1ad 100644
--- a/src/main/java/org/apache/commons/compress/archivers/zip/BitStream.java
+++ b/src/main/java/org/apache/commons/compress/archivers/zip/BitStream.java
@@ -42,7 +42,7 @@
* @return The next bit (0 or 1) or -1 if the end of the stream has been reached
*/
int nextBit() throws IOException {
- return readBits(1);
+ return (int) readBits(1);
}
/**
@@ -51,11 +51,11 @@
* @param n the number of bits read (up to 8)
* @return The value formed by the n bits, or -1 if the end of the stream has been reached
*/
- int nextBits(final int n) throws IOException {
+ long nextBits(final int n) throws IOException {
return readBits(n);
}
int nextByte() throws IOException {
- return readBits(8);
+ return (int) readBits(8);
}
}
diff --git a/src/main/java/org/apache/commons/compress/archivers/zip/ExplodingInputStream.java b/src/main/java/org/apache/commons/compress/archivers/zip/ExplodingInputStream.java
index aa9a5ce..87d3c52 100644
--- a/src/main/java/org/apache/commons/compress/archivers/zip/ExplodingInputStream.java
+++ b/src/main/java/org/apache/commons/compress/archivers/zip/ExplodingInputStream.java
@@ -124,7 +124,7 @@
if (literalTree != null) {
literal = literalTree.read(bits);
} else {
- literal = bits.nextBits(8);
+ literal = bits.nextByte();
}
if (literal == -1) {
@@ -137,7 +137,7 @@
} else if (bit == 0) {
// back reference
int distanceLowSize = dictionarySize == 4096 ? 6 : 7;
- int distanceLow = bits.nextBits(distanceLowSize);
+ int distanceLow = (int) bits.nextBits(distanceLowSize);
int distanceHigh = distanceTree.read(bits);
if (distanceHigh == -1 && distanceLow <= 0) {
// end of stream reached, nothing left to decode
diff --git a/src/main/java/org/apache/commons/compress/compressors/lzw/LZWInputStream.java b/src/main/java/org/apache/commons/compress/compressors/lzw/LZWInputStream.java
index df866e5..6900b7c 100644
--- a/src/main/java/org/apache/commons/compress/compressors/lzw/LZWInputStream.java
+++ b/src/main/java/org/apache/commons/compress/compressors/lzw/LZWInputStream.java
@@ -121,7 +121,10 @@
* Reads the next code from the stream.
*/
protected int readNextCode() throws IOException {
- return in.readBits(codeSize);
+ if (codeSize > 31) {
+ throw new IllegalArgumentException("code size must not be bigger than 31");
+ }
+ return (int) in.readBits(codeSize);
}
/**
diff --git a/src/main/java/org/apache/commons/compress/compressors/z/ZCompressorInputStream.java b/src/main/java/org/apache/commons/compress/compressors/z/ZCompressorInputStream.java
index fb41052..1bb65b5 100644
--- a/src/main/java/org/apache/commons/compress/compressors/z/ZCompressorInputStream.java
+++ b/src/main/java/org/apache/commons/compress/compressors/z/ZCompressorInputStream.java
@@ -40,9 +40,9 @@
public ZCompressorInputStream(InputStream inputStream) throws IOException {
super(inputStream, ByteOrder.LITTLE_ENDIAN);
- int firstByte = in.readBits(8);
- int secondByte = in.readBits(8);
- int thirdByte = in.readBits(8);
+ int firstByte = (int) in.readBits(8);
+ int secondByte = (int) in.readBits(8);
+ int thirdByte = (int) in.readBits(8);
if (firstByte != MAGIC_1 || secondByte != MAGIC_2 || thirdByte < 0) {
throw new IOException("Input is not in .Z format");
}
diff --git a/src/main/java/org/apache/commons/compress/utils/BitInputStream.java b/src/main/java/org/apache/commons/compress/utils/BitInputStream.java
index d8988c7..dd1d9b6 100644
--- a/src/main/java/org/apache/commons/compress/utils/BitInputStream.java
+++ b/src/main/java/org/apache/commons/compress/utils/BitInputStream.java
@@ -29,8 +29,8 @@
* @NotThreadSafe
*/
public class BitInputStream implements Closeable {
- private static final int MAXIMUM_CACHE_SIZE = 31; // bits in int minus sign bit
- private static final int[] MASKS = new int[MAXIMUM_CACHE_SIZE + 1];
+ private static final int MAXIMUM_CACHE_SIZE = 63; // bits in long minus sign bit
+ private static final long[] MASKS = new long[MAXIMUM_CACHE_SIZE + 1];
static {
for (int i = 1; i <= MAXIMUM_CACHE_SIZE; i++) {
@@ -40,7 +40,7 @@
private final InputStream in;
private final ByteOrder byteOrder;
- private int bitsCached = 0;
+ private long bitsCached = 0;
private int bitsCachedSize = 0;
/**
@@ -68,20 +68,20 @@
}
/**
- * Returns at most 31 bits read from the underlying stream.
+ * Returns at most 63 bits read from the underlying stream.
*
* @param count the number of bits to read, must be a positive
- * number not bigger than 31.
- * @return the bits concatenated as an integer using the stream's byte order.
+ * number not bigger than 63.
+ * @return the bits concatenated as a long using the stream's byte order.
* -1 if the end of the underlying stream has been reached before reading
* the requested number of bits
*/
- public int readBits(final int count) throws IOException {
+ public long readBits(final int count) throws IOException {
if (count < 0 || count > MAXIMUM_CACHE_SIZE) {
throw new IllegalArgumentException("count must not be negative or greater than " + MAXIMUM_CACHE_SIZE);
}
while (bitsCachedSize < count) {
- final int nextByte = in.read();
+ final long nextByte = in.read();
if (nextByte < 0) {
return nextByte;
}
@@ -94,7 +94,7 @@
bitsCachedSize += 8;
}
- final int bitsOut;
+ final long bitsOut;
if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
bitsOut = (bitsCached & MASKS[count]);
bitsCached >>>= count;
diff --git a/src/test/java/org/apache/commons/compress/utils/BitInputStreamTest.java b/src/test/java/org/apache/commons/compress/utils/BitInputStreamTest.java
index ed146cf..9c1eeca 100644
--- a/src/test/java/org/apache/commons/compress/utils/BitInputStreamTest.java
+++ b/src/test/java/org/apache/commons/compress/utils/BitInputStreamTest.java
@@ -35,9 +35,9 @@
}
@Test(expected = IllegalArgumentException.class)
- public void shouldNotAllowReadingOfMoreThan31BitsAtATime() throws IOException {
+ public void shouldNotAllowReadingOfMoreThan63BitsAtATime() throws IOException {
BitInputStream bis = new BitInputStream(getStream(), ByteOrder.LITTLE_ENDIAN);
- bis.readBits(32);
+ bis.readBits(64);
}
@Test