package SevenZip.Compression.Branch;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Vector;
import SevenZip.Compression.LZ.OutWindow;
import SevenZip.ICompressCoder2;
import SevenZip.ICompressProgressInfo;
import SevenZip.Common.InBuffer;
import SevenZip.HRESULT;
public class BCJ2_x86_Decoder implements ICompressCoder2 {
public static final int kNumMoveBits = 5;
InBuffer _mainInStream = new InBuffer();
InBuffer _callStream = new InBuffer();
InBuffer _jumpStream = new InBuffer();
SevenZip.Compression.RangeCoder.BitDecoder _statusE8Decoder[] = new SevenZip.Compression.RangeCoder.BitDecoder[256];
SevenZip.Compression.RangeCoder.BitDecoder _statusE9Decoder = new SevenZip.Compression.RangeCoder.BitDecoder(kNumMoveBits);
SevenZip.Compression.RangeCoder.BitDecoder _statusJccDecoder = new SevenZip.Compression.RangeCoder.BitDecoder(kNumMoveBits);
OutWindow _outStream = new OutWindow();
SevenZip.Compression.RangeCoder.Decoder _rangeDecoder = new SevenZip.Compression.RangeCoder.Decoder();
// static final boolean IsJcc(int b0, int b1) {
// return ((b0 == 0x0F) && ((b1 & 0xF0) == 0x80));
// }
int CodeReal(
Vector<InputStream> inStreams,
//Object useless1, // const UInt64 ** /* inSizes */,
int numInStreams,
Vector<OutputStream> outStreams,
//Object useless2, // const UInt64 ** /* outSizes */,
int numOutStreams,
ICompressProgressInfo progress) throws java.io.IOException {
if (numInStreams != 4 || numOutStreams != 1)
throw new IllegalArgumentException("numInStreams != 4 || numOutStreams != 1");
_mainInStream.Create(1 << 16);
_callStream.Create(1 << 20);
_jumpStream.Create(1 << 16);
_rangeDecoder.Create(1 << 20);
_outStream.Create(1 << 16);
_mainInStream.SetStream(inStreams.get(0));
_callStream.SetStream(inStreams.get(1));
_jumpStream.SetStream(inStreams.get(2));
_rangeDecoder.SetStream(inStreams.get(3));
_outStream.SetStream(outStreams.get(0));
_mainInStream.Init();
_callStream.Init();
_jumpStream.Init();
_rangeDecoder.Init();
_outStream.Init();
for (int i = 0; i < 256; i++) {
_statusE8Decoder[i] = new SevenZip.Compression.RangeCoder.BitDecoder(kNumMoveBits);
_statusE8Decoder[i].Init();
}
_statusE9Decoder.Init();
_statusJccDecoder.Init();
int prevByte = 0;
int processedBytes = 0;
for (;;) {
if (processedBytes > (1 << 20) && progress != null) {
long nowPos64 = _outStream.GetProcessedSize();
progress.SetRatioInfo(ICompressProgressInfo.INVALID, nowPos64);
processedBytes = 0;
}
processedBytes++;
int b = _mainInStream.read();
if (b == -1) {
Flush();
return HRESULT.S_OK;
}
_outStream.WriteByte(b); // System.out.println("0:"+b);
// if ((b != 0xE8) && (b != 0xE9) && (!IsJcc(prevByte, b))) {
if ((b != 0xE8) && (b != 0xE9) && (!((prevByte == 0x0F) && ((b & 0xF0) == 0x80)))) {
prevByte = b;
continue;
}
boolean status;
if (b == 0xE8)
status = (_statusE8Decoder[prevByte].Decode(_rangeDecoder) == 1);
else if (b == 0xE9)
status = (_statusE9Decoder.Decode(_rangeDecoder) == 1);
else
status = (_statusJccDecoder.Decode(_rangeDecoder) == 1);
if (status) {
int src;
if (b == 0xE8) {
int b0 = _callStream.read();
// if(b0 == -1) return HRESULT.S_FALSE;
src = ((int)b0) << 24;
b0 = _callStream.read();
// if(b0 == -1) return HRESULT.S_FALSE;
src |= ((int)b0) << 16;
b0 = _callStream.read();
// if(b0 == -1) return HRESULT.S_FALSE;
src |= ((int)b0) << 8;
b0 = _callStream.read();
if (b0 == -1) return HRESULT.S_FALSE;
src |= ((int)b0);
} else {
int b0 = _jumpStream.read();
// if(b0 == -1) return HRESULT.S_FALSE;
src = ((int)b0) << 24;
b0 = _jumpStream.read();
// if(b0 == -1) return HRESULT.S_FALSE;
src |= ((int)b0) << 16;
b0 = _jumpStream.read();
// if(b0 == -1) return HRESULT.S_FALSE;
src |= ((int)b0) << 8;
b0 = _jumpStream.read();
if(b0 == -1) return HRESULT.S_FALSE;
src |= ((int)b0);
}
int dest = src - ((int)_outStream.GetProcessedSize() + 4) ;
_outStream.WriteByte(dest);
_outStream.WriteByte((dest >> 8));
_outStream.WriteByte((dest >> 16));
_outStream.WriteByte((dest >> 24));
prevByte = (int)(dest >> 24) & 0xFF;
processedBytes += 4;
} else
prevByte = b;
}
}
public void Flush() throws IOException {
_outStream.Flush();
}
@Override
public int Code(
Vector<InputStream> inStreams, // ISequentialInStream **inStreams,
//Object useless_inSizes, // const UInt64 ** /* inSizes */,
int numInStreams,
Vector<OutputStream> outStreams, // ISequentialOutStream **outStreams
//Object useless_outSizes, // const UInt64 ** /* outSizes */,
int numOutStreams,
ICompressProgressInfo progress) throws java.io.IOException {
try {
return CodeReal(inStreams, /*useless_inSizes,*/ numInStreams,
outStreams, /*useless_outSizes,*/ numOutStreams, progress);
} catch(java.io.IOException e) {
throw e;
} finally {
ReleaseStreams();
}
}
void ReleaseStreams() throws java.io.IOException {
_mainInStream.ReleaseStream();
_callStream.ReleaseStream();
_jumpStream.ReleaseStream();
_rangeDecoder.ReleaseStream();
_outStream.ReleaseStream();
}
@Override
public void close() throws java.io.IOException {
ReleaseStreams();
}
}