package com.colloquial.arithcode; import java.io.InputStream; import java.io.IOException; /** Reads input from an underlying input stream a bit at a time. Bits * are returned as booleans, with <code>true=1</code> and * <code>false=0</code>. * * @see com.colloquial.arithcode.BitOutput * * @author <a href="http://www.colloquial.com/carp/">Bob Carpenter</a> * @version 1.1 * @see BitOutput * @since 1.0 */ public final class BitInput { /** Constructs a bit input from an underlying input stream. * @param in Input stream backing this bit input. * @throws IOException If there is an exception reading from the specified input stream. */ public BitInput(InputStream in) throws IOException { _in = in; readAhead(); } /** Returns number of bits available for reading. Will always be * <code>0</code> or <code>1</code>. * @return Number of bits available for reading. * @throws IOException If there is an exception checking available bytes in the underlying input stream. */ public long available() throws IOException { return endOfStream() ? 0 : 1; } /** Closes the underlying input stream. * @throws IOException If there is an exception closing the underlying input stream. */ public void close() throws IOException { _in.close(); } /** Returns <code>true</code> if all of the available bits have been read. * @return <code>true</code> if all of the available bits have been read. */ public boolean endOfStream() { return _endOfStream; } /** Reads the next bit from the input stream. Returns garbage if reading * while available() is false. * @return The boolean value of the next bit, <code>true</code>=1, <code>false</code>=0. * @throws IOException If there is an exception reading a byte from the underlying stream. */ public boolean readBit() throws IOException { if (_nextBitIndex > 0) return ((_nextByte & (1 << _nextBitIndex--)) != 0); // inspects bit in buffered byte boolean result = ((_nextByte & 1) != 0); // on last bit in byte; buffer new byte readAhead(); return result; } /** Underlying input stream. */ private final InputStream _in; /** Buffered byte from which bits are read. */ private int _nextByte; // implied = 0; /** Position of next bit in the buffered byte. */ private int _nextBitIndex; /** Set to true when all bits have been read. */ private boolean _endOfStream = false; /** Reads the next byte from the input stream into <code>_nextByte</code>. * @throws IOException If there is an IOException reading from the stream. */ private void readAhead() throws IOException { if (_endOfStream) return; _nextByte = _in.read(); if (_nextByte == -1) { _endOfStream = true; return; } _nextBitIndex = 7; } }