JBBPBitInputStream extends FilterInputStream implements JBBPCountableBitStream { public int readBits(final JBBPBitNumber numOfBitsToRead) throws IOException { int result; final int numOfBitsAsNumber = numOfBitsToRead.getBitNumber(); if (this.bitsInBuffer == 0 && numOfBitsAsNumber == 8) { result = this.readByteFromStream(); if (result >= 0) { this.byteCounter++; } return result; } else { result = 0; if (numOfBitsAsNumber == this.bitsInBuffer) { result = this.bitBuffer; this.bitBuffer = 0; this.bitsInBuffer = 0; this.byteCounter++; return result; } int i = numOfBitsAsNumber; int theBitBuffer = this.bitBuffer; int theBitBufferCounter = this.bitsInBuffer; final boolean doIncCounter = theBitBufferCounter != 0; while (i > 0) { if (theBitBufferCounter == 0) { if (doIncCounter) { this.byteCounter++; } final int nextByte = this.readByteFromStream(); if (nextByte < 0) { if (i == numOfBitsAsNumber) { return nextByte; } else { break; } } else { theBitBuffer = nextByte; theBitBufferCounter = 8; } } result = (result << 1) | (theBitBuffer & 1); theBitBuffer >>= 1; theBitBufferCounter--; i--; } this.bitBuffer = theBitBuffer; this.bitsInBuffer = theBitBufferCounter; return JBBPUtils.reverseBitsInByte(JBBPBitNumber.decode(numOfBitsAsNumber - i), (byte) result) & 0xFF; } } JBBPBitInputStream(final InputStream in);  JBBPBitInputStream(final InputStream in, final JBBPBitOrder order); boolean[] readBoolArray(final int items); byte[] readBitsArray(final int items, final JBBPBitNumber bitNumber); byte[] readByteArray(final int items); byte[] readByteArray(final int items, final JBBPByteOrder byteOrder); short[] readShortArray(final int items, final JBBPByteOrder byteOrder); char[] readUShortArray(final int items, final JBBPByteOrder byteOrder); int[] readIntArray(final int items, final JBBPByteOrder byteOrder); float[] readFloatArray(final int items, final JBBPByteOrder byteOrder); long[] readLongArray(final int items, final JBBPByteOrder byteOrder); double[] readDoubleArray(final int items, final JBBPByteOrder byteOrder); int readUnsignedShort(final JBBPByteOrder byteOrder); int readInt(final JBBPByteOrder byteOrder); float readFloat(final JBBPByteOrder byteOrder); long readLong(final JBBPByteOrder byteOrder); double readDouble(final JBBPByteOrder byteOrder); @Override long getCounter(); @Override int getBitBuffer(); @Override int getBufferedBitsNumber(); @Override JBBPBitOrder getBitOrder(); byte readBitField(final JBBPBitNumber numOfBitsToRead); int readBits(final JBBPBitNumber numOfBitsToRead); boolean readBoolean(); int readByte(); @Override synchronized void reset(); @Override synchronized void mark(final int readlimit); void align(final long alignByteNumber); @Override long skip(final long numOfBytes); void alignByte(); boolean hasAvailableData(); @SuppressWarnings("NullableProblems") @Override int read(final byte[] array, final int offset, final int length); @Override void resetCounter(); @SuppressWarnings("NullableProblems") @Override int read(final byte[] array); @Override int read(); String readString(final JBBPByteOrder byteOrder); String[] readStringArray(final int items, final JBBPByteOrder byteOrder);  }
@Test public void testReadBits_ExceptionForWrongArgument() throws Exception { final JBBPBitInputStream inLe = new JBBPBitInputStream(new ByteArrayInputStream(JBBPUtils.str2bin(TEST_BYTES, JBBPBitOrder.LSB0))); try { inLe.readBits(JBBPBitNumber.decode(0)); fail("Must throw IAE"); } catch (IllegalArgumentException ex) { } try { inLe.readBits(JBBPBitNumber.decode(-5)); fail("Must throw IAE"); } catch (IllegalArgumentException ex) { } try { inLe.readBits(JBBPBitNumber.decode(9)); fail("Must throw IAE"); } catch (IllegalArgumentException ex) { } }