All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.darkmist.alib.io.InputStreamBitsInput Maven / Gradle / Ivy

/*
 *  Copyright (C) 2012 Ed Schaller 
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package net.darkmist.alib.io;

import java.io.IOException;
import java.io.EOFException;
import java.io.InputStream;

import net.darkmist.alib.str.Binary;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class InputStreamBitsInput implements BitsInput
{
	private static final Class CLASS = InputStreamBitsInput.class;
	private static final Logger logger = LoggerFactory.getLogger(CLASS);
	private InputStream in;
	private long bits = 0;
	private int numBits = 0;
	private boolean eof = false;

	public InputStreamBitsInput(InputStream in)
	{
		this.in = in;
	}

	private void addBits(int b)
	{
		int finalNumBits;
		if((finalNumBits = numBits + Byte.SIZE) > Long.SIZE)
			throw new IllegalStateException("Attempt to add more bits than can be fit into the current buffer.");
		bits <<= Byte.SIZE;
		bits |= b&0xFF;
		numBits=finalNumBits;
	}

	private void fillBits() throws IOException
	{
		int bytesNeeded = ((Long.SIZE - numBits)/Byte.SIZE);
		byte[] buf;
		int amount;

		if(eof || bytesNeeded == 0)
			return;
		buf = new byte[bytesNeeded];

		if((amount=IOUtils.readFully(in,buf)) Integer.SIZE)
			throw new IllegalArgumentException("Number of bits requested (" + num + " is larger than the number of bits a integer can hold (" + Integer.SIZE + ')');
		if(num <= 0)
			throw new IllegalArgumentException("Number of bits requested (" + num + " is less than or equal to zero.");
		if(numBits < num)
		{
			if(eof)
				throw new EOFException("bits left=" + numBits + " bits needed=" + num);
			fillBits();
		}
		if(logger.isDebugEnabled())
		{
			logger.debug("bits={}", Binary.toString(bits));
			logger.debug("used={}", Binary.toString((~0l)>>>(Long.SIZE - numBits),' ','^'));
		}
		numBitsAfter = numBits - num;
		if(numBitsAfter < 0)
			throw new EOFException("bits left=" + numBits + " bits needed=" + num);

		// get mask for the bits we need
		out = (~(0l)) >>> (Long.SIZE - num);

		// shift mask into position
		out <<= numBitsAfter;

		// get bits
		out &= bits;

		// shift bits back into position
		out >>>= numBitsAfter;

		// fixup the bit count
		numBits = numBitsAfter;

		return (int)out;
	}

	@Override
	public boolean readBit() throws IOException
	{
		return (readBits(1)!=0x0);
	}

	@Override
	public void close()throws IOException
	{
		eof = true;
		numBits = 0;
		in.close();
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy