package org.amse.ys.zip;
import java.io.*;
import org.geometerplus.zlibrary.core.util.InputStreamHolder;
final class MyBufferedInputStream extends InputStream {
private final InputStreamHolder myStreamHolder;
private InputStream myFileInputStream;
private final byte[] myBuffer;
int myBytesReady;
int myPositionInBuffer;
private int myCurrentPosition;
public MyBufferedInputStream(InputStreamHolder streamHolder, int bufferSize) throws IOException {
myStreamHolder = streamHolder;
myFileInputStream = streamHolder.getInputStream();
myBuffer = new byte[bufferSize];
myBytesReady = 0;
myPositionInBuffer = 0;
}
public MyBufferedInputStream(InputStreamHolder streamHolder) throws IOException {
this(streamHolder, 1 << 10);
}
@Override
public int available() throws IOException {
return (myFileInputStream.available() + myBytesReady);
}
int offset() {
return myCurrentPosition;
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
int ready = (len < myBytesReady) ? len : myBytesReady;
if (ready > 0) {
if (b != null) {
System.arraycopy(myBuffer, myPositionInBuffer, b, off, ready);
}
len -= ready;
myBytesReady -= ready;
myPositionInBuffer += ready;
off += ready;
}
if (len > 0) {
final int ready2 = myFileInputStream.read(b, off, len);
if (ready2 >= 0) {
ready += ready2;
}
}
myCurrentPosition += ready;
return ready > 0 ? ready : -1;
}
@Override
public int read() throws IOException {
myCurrentPosition++;
if (myBytesReady <= 0) {
myPositionInBuffer = 0;
myBytesReady = myFileInputStream.read(myBuffer);
if (myBytesReady <= 0) {
return -1;
}
}
myBytesReady--;
return myBuffer[myPositionInBuffer++] & 255;
}
int read2Bytes() throws IOException {
int low = read();
int high = read();
if (high < 0) {
throw new ZipException("unexpected end of file at position " + offset());
}
return (high << 8) + low;
}
int read4Bytes() throws IOException {
int firstByte = read();
int secondByte = read();
int thirdByte = read();
int fourthByte = read();
if (fourthByte < 0) {
throw new ZipException("unexpected end of file at position " + offset());
}
return (fourthByte << 24) + (thirdByte << 16) + (secondByte << 8) + firstByte;
}
private static final boolean isUtf8String(byte[] array) {
int nonLeadingCharsCounter = 0;
for (byte b : array) {
if (nonLeadingCharsCounter == 0) {
if ((b & 0x80) != 0) {
if ((b & 0xE0) == 0xC0) {
nonLeadingCharsCounter = 1;
} else if ((b & 0xF0) == 0xE0) {
nonLeadingCharsCounter = 2;
} else if ((b & 0xF8) == 0xF0) {
nonLeadingCharsCounter = 3;
} else {
return false;
}
}
} else {
if ((b & 0xC0) != 0x80) {
return false;
}
--nonLeadingCharsCounter;
}
}
return nonLeadingCharsCounter == 0;
}
String readString(int stringLength) throws IOException {
final byte[] array = new byte[stringLength];
read(array);
if (isUtf8String(array)) {
return new String(array, "utf-8");
}
final char[] chars = new char[stringLength];
for (int i = 0; i < stringLength; i++) {
chars[i] = (char)(array[i] & 0xFF);
}
return new String(chars);
}
@Override
public long skip(long n) throws IOException {
if (myBytesReady >= n) {
myBytesReady -= n;
myPositionInBuffer += n;
myCurrentPosition += n;
return n;
} else {
long left = n - myBytesReady;
myBytesReady = 0;
left -= myFileInputStream.skip(left);
while (left > 0) {
int skipped = myFileInputStream.read(myBuffer, 0, Math.min((int)left, myBuffer.length));
if (skipped <= 0) {
break;
}
left -= skipped;
}
myCurrentPosition += n - left;
return n - left;
}
}
public void backSkip(int n) throws IOException {
if (n <= 0) {
return;
}
myFileInputStream.close();
myFileInputStream = myStreamHolder.getInputStream();
myBytesReady = 0;
myPositionInBuffer = 0;
int position = myCurrentPosition - n;
myCurrentPosition = 0;
skip(position);
}
public void setPosition(int position) throws IOException {
if (myCurrentPosition < position) {
skip(position - myCurrentPosition);
} else {
backSkip(myCurrentPosition - position);
}
}
/*
public void setPosition(int position) throws IOException {
if (myCurrentPosition < position) {
skip(position - myCurrentPosition);
} else {
myFileInputStream.close();
myFileInputStream = myStreamHolder.getInputStream();
myBytesReady = 0;
skip(position);
myCurrentPosition = position;
}
}
*/
@Override
public void close() throws IOException {
myFileInputStream.close();
myBytesReady = 0;
}
}