package org.apache.poi.util;
import java.io.BufferedInputStream;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
public class LittleEndianInputStream extends FilterInputStream implements LittleEndianInput {
private static final int BUFFERED_SIZE = 8096;
private static final int EOF = -1;
private int readIndex = 0;
private int markIndex = -1;
public LittleEndianInputStream(InputStream is) {
super(is.markSupported() ? is : new BufferedInputStream(is, BUFFERED_SIZE));
}
@Override
@SuppressForbidden("just delegating")
public int available() {
try {
return super.available();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public byte readByte() {
return (byte)readUByte();
}
@Override
public int readUByte() {
byte[] buf = new byte[1];
try {
checkEOF(read(buf), 1);
} catch (IOException e) {
throw new RuntimeException(e);
}
return LittleEndian.getUByte(buf);
}
public float readFloat() {
return Float.intBitsToFloat( readInt() );
}
@Override
public double readDouble() {
return Double.longBitsToDouble(readLong());
}
@Override
public int readInt() {
byte[] buf = new byte[LittleEndianConsts.INT_SIZE];
try {
checkEOF(read(buf), buf.length);
} catch (IOException e) {
throw new RuntimeException(e);
}
return LittleEndian.getInt(buf);
}
public long readUInt() {
long retNum = readInt();
return retNum & 0x00FFFFFFFFL;
}
@Override
public long readLong() {
byte[] buf = new byte[LittleEndianConsts.LONG_SIZE];
try {
checkEOF(read(buf), LittleEndianConsts.LONG_SIZE);
} catch (IOException e) {
throw new RuntimeException(e);
}
return LittleEndian.getLong(buf);
}
@Override
public short readShort() {
return (short)readUShort();
}
@Override
public int readUShort() {
byte[] buf = new byte[LittleEndianConsts.SHORT_SIZE];
try {
checkEOF(read(buf), LittleEndianConsts.SHORT_SIZE);
} catch (IOException e) {
throw new RuntimeException(e);
}
return LittleEndian.getUShort(buf);
}
private static void checkEOF(int actualBytes, int expectedBytes) {
if (expectedBytes != 0 && (actualBytes == -1 || actualBytes != expectedBytes)) {
throw new RuntimeException("Unexpected end-of-file");
}
}
@Override
public void readFully(byte[] buf) {
readFully(buf, 0, buf.length);
}
@Override
public void readFully(byte[] buf, int off, int len) {
try {
checkEOF(_read(buf, off, len), len);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
int readBytes = super.read(b, off, len);
readIndex += readBytes;
return readBytes;
}
@Override
public synchronized void mark(int readlimit) {
super.mark(readlimit);
markIndex = readIndex;
}
@Override
public synchronized void reset() throws IOException {
super.reset();
if (markIndex > -1) {
readIndex = markIndex;
markIndex = -1;
}
}
public int getReadIndex() {
return readIndex;
}
private int _read(byte[] buffer, int offset, int length) throws IOException {
int remaining = length;
while (remaining > 0) {
int location = length - remaining;
int count = read(buffer, offset + location, remaining);
if (EOF == count) {
break;
}
remaining -= count;
}
return length - remaining;
}
@Override
public void readPlain(byte[] buf, int off, int len) {
readFully(buf, off, len);
}
public void skipFully(int len) throws IOException {
IOUtils.skipFully(this, len);
}
}