package java.io;
/**
* This is a minimal implementation of BufferedWriter.
* Normally BufferedWriter extends the abstract class Writer.
* The main reason for NXJ including this is to allow the new-line
* character in text.
* NOTE: Text writing is not synchronized either like standard Java.
*
* @author BB
*
*/
public class BufferedInputStream extends FilterInputStream
{
private static final int DEFAULT_BUFFERSIZE = 64;
private static final int MIN_BUFFERSIZE = 1;
private final byte[] buffer;
private int offset;
private int limit;
/**
* In the standard Java API the constructor accepts a Writer
* object, such as InputStreamWriter.
* @param out
*/
public BufferedInputStream(InputStream out)
{
this(out, DEFAULT_BUFFERSIZE);
}
public BufferedInputStream(InputStream out, int size)
{
super(out);
if (size < MIN_BUFFERSIZE)
size = MIN_BUFFERSIZE;
this.buffer = new byte[size];
}
@Override
public void close() throws IOException
{
this.limit = -1;
this.in.close();
}
@Override
public int available() throws IOException
{
checkOpen();
return this.limit - this.offset + this.in.available();
}
private void checkOpen() throws IOException
{
if (this.limit < 0)
throw new IOException("stream is closed");
}
private boolean fillBuffer() throws IOException
{
if (this.offset >= this.limit)
{
int len = 0;
//some InputStream may be return 0, which is bad behavior actually
while (len == 0)
len = this.in.read(this.buffer, 0, this.buffer.length);
if (len < 0)
return false;
this.offset = 0;
this.limit = len;
}
return true;
}
@Override
public int read() throws IOException
{
checkOpen();
if (!fillBuffer())
return -1;
return this.buffer[this.offset++] & 0xFF;
}
@Override
public int read(byte[] b, int off, int len) throws IOException
{
checkOpen();
int blen = this.limit - this.offset;
// case 1: buffer is not empty
if (blen > 0)
{
if (blen > len)
blen = len;
System.arraycopy(this.buffer, this.offset, b, off, blen);
this.offset += blen;
return blen;
}
// case 2: buffer is empty
return this.in.read(b, off, len);
}
@Override
public long skip(long n) throws IOException
{
checkOpen();
int blen = this.limit - this.offset;
if (n <= blen)
{
this.offset += (int)n;
return n;
}
long norig = n;
//it holds n > blen
n -= blen;
this.offset = this.limit;
while (n > 0)
{
int len = this.in.read(this.buffer, 0, this.buffer.length);
if (len < 0)
break;
n -= len;
}
return norig - n;
}
}