package com.e2u.tree;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import com.e2u.bit.*;
public class Inflater
{
private HuffmanNode root = null;
private HuffmanNode curNode = null;
private int emptyBitInLastByte = -1;
private int prevInputLastByte = Integer.MIN_VALUE;
private List<Byte> decodeByteList = null;
public Inflater(HuffmanNode root)
{
this.root = root;
curNode = this.root;
emptyBitInLastByte = -1;
prevInputLastByte = Integer.MIN_VALUE;
decodeByteList = new LinkedList<Byte>();
}
private void reset()
{
curNode = this.root;
emptyBitInLastByte = -1;
prevInputLastByte = Integer.MIN_VALUE;
decodeByteList.clear();
}
public void addDecompressInputData(byte[] data, int len)
{
if(prevInputLastByte != Integer.MIN_VALUE)
{
decode((byte)prevInputLastByte);
}
prevInputLastByte = data[len - 1];
int index = 0;
if(emptyBitInLastByte < 0)
{
emptyBitInLastByte = data[0];
index++;
}
for( ; index < len - 1; index++)
{
decode(data[index]);
}
}
public byte[] finishDecompress()
{
if(prevInputLastByte != Integer.MIN_VALUE)
{
decode((byte)prevInputLastByte, 8 - emptyBitInLastByte);
if(curNode != root)
{
throw new IllegalArgumentException("Format Error");
}
}
//output
byte[] result = new byte[decodeByteList.size()];
Iterator<Byte> iter = decodeByteList.iterator();
for(int i = 0; iter.hasNext(); i++)
{
result[i] = iter.next();
}
reset();
return result;
}
public byte[] decompress(byte[] data)
{
addDecompressInputData(data, data.length);
return finishDecompress();
}
private void decode(byte b)
{
decode(b, 8);
}
private void decode(byte b, int len)
{
String byteStr = BitUtil.toBin(b);
for(int offset = 0; offset < len; offset++)
{
if(byteStr.charAt(offset) == '0')
{
curNode = curNode.lchild;
}
else if(byteStr.charAt(offset) == '1')
{
curNode = curNode.rchild;
}
if(curNode.isLeaf())
{
decodeByteList.add(curNode.element);
curNode = root;
}
}
}
}