169 lines
4.0 KiB
Java
169 lines
4.0 KiB
Java
|
/* Copyright (C) 1998, 1999 Cygnus Solutions
|
||
|
|
||
|
This file is part of libgcj.
|
||
|
|
||
|
This software is copyrighted work licensed under the terms of the
|
||
|
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
|
||
|
details. */
|
||
|
|
||
|
package java.io;
|
||
|
|
||
|
/**
|
||
|
* @author Warren Levy <warrenl@cygnus.com>
|
||
|
* @date October 8, 1998.
|
||
|
*/
|
||
|
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
|
||
|
* "The Java Language Specification", ISBN 0-201-63451-1
|
||
|
* plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
|
||
|
* Status: Believed complete and correct.
|
||
|
*/
|
||
|
|
||
|
public class BufferedInputStream extends FilterInputStream
|
||
|
{
|
||
|
/* Internal buffer array for data. */
|
||
|
protected byte[] buf;
|
||
|
|
||
|
/* Index one greater than the last valid byte in the buffer. */
|
||
|
protected int count = 0;
|
||
|
|
||
|
/* The current position in the buffer. */
|
||
|
protected int pos = 0;
|
||
|
|
||
|
/* The value of pos the last time mark() was called. */
|
||
|
protected int markpos = -1;
|
||
|
|
||
|
/* The maximum read-ahead allowed before calls to reset() fail. */
|
||
|
protected int marklimit = 0;
|
||
|
|
||
|
public BufferedInputStream(InputStream in)
|
||
|
{
|
||
|
this(in, 2048);
|
||
|
}
|
||
|
|
||
|
public BufferedInputStream(InputStream in, int size)
|
||
|
{
|
||
|
super(in);
|
||
|
if (size <= 0)
|
||
|
throw new IllegalArgumentException();
|
||
|
buf = new byte[size];
|
||
|
}
|
||
|
|
||
|
public synchronized int available() throws IOException
|
||
|
{
|
||
|
return count - pos + super.available();
|
||
|
}
|
||
|
|
||
|
public void close() throws IOException
|
||
|
{
|
||
|
// Free up the array memory.
|
||
|
buf = null;
|
||
|
super.close();
|
||
|
}
|
||
|
|
||
|
public synchronized void mark(int readlimit)
|
||
|
{
|
||
|
marklimit = readlimit;
|
||
|
markpos = pos;
|
||
|
}
|
||
|
|
||
|
public boolean markSupported()
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
public synchronized int read() throws IOException
|
||
|
{
|
||
|
if (pos >= count && !refill())
|
||
|
return -1; // EOF
|
||
|
|
||
|
if (markpos >= 0 && pos - markpos > marklimit)
|
||
|
markpos = -1;
|
||
|
|
||
|
return ((int) buf[pos++]) & 0xFF;
|
||
|
}
|
||
|
|
||
|
public synchronized int read(byte[] b, int off, int len) throws IOException
|
||
|
{
|
||
|
if (off < 0 || len < 0 || off + len > b.length)
|
||
|
throw new ArrayIndexOutOfBoundsException();
|
||
|
|
||
|
if (pos >= count && !refill())
|
||
|
return -1; // No bytes were read before EOF.
|
||
|
|
||
|
int remain = Math.min(count - pos, len);
|
||
|
System.arraycopy(buf, pos, b, off, remain);
|
||
|
pos += remain;
|
||
|
|
||
|
if (markpos >= 0 && pos - markpos > marklimit)
|
||
|
markpos = -1;
|
||
|
|
||
|
return remain;
|
||
|
}
|
||
|
|
||
|
public synchronized void reset() throws IOException
|
||
|
{
|
||
|
if (markpos < 0)
|
||
|
throw new IOException();
|
||
|
|
||
|
pos = markpos;
|
||
|
}
|
||
|
|
||
|
public synchronized long skip(long n) throws IOException
|
||
|
{
|
||
|
final long origN = n;
|
||
|
|
||
|
while (n > 0L)
|
||
|
{
|
||
|
if (pos >= count && !refill())
|
||
|
if (n < origN)
|
||
|
break;
|
||
|
else
|
||
|
return -1; // No bytes were read before EOF.
|
||
|
|
||
|
int numread = (int) Math.min((long) (count - pos), n);
|
||
|
pos += numread;
|
||
|
n -= numread;
|
||
|
|
||
|
if (markpos >= 0 && pos - markpos > marklimit)
|
||
|
markpos = -1;
|
||
|
}
|
||
|
|
||
|
return origN - n;
|
||
|
}
|
||
|
|
||
|
private boolean refill() throws IOException
|
||
|
{
|
||
|
if (markpos < 0)
|
||
|
count = pos = 0;
|
||
|
else if (markpos > 0)
|
||
|
{
|
||
|
// Shift the marked bytes (if any) to the beginning of the array
|
||
|
// but don't grow it. This saves space in case a reset is done
|
||
|
// before we reach the max capacity of this array.
|
||
|
System.arraycopy(buf, markpos, buf, 0, count - markpos);
|
||
|
count -= markpos;
|
||
|
pos -= markpos;
|
||
|
markpos = 0;
|
||
|
}
|
||
|
else if (marklimit >= buf.length) // BTW, markpos == 0
|
||
|
{
|
||
|
// Need to grow the buffer now to have room for marklimit bytes.
|
||
|
// Note that the new buffer is one greater than marklimit.
|
||
|
// This is so that there will be one byte past marklimit to be read
|
||
|
// before having to call refill again, thus allowing marklimit to be
|
||
|
// invalidated. That way refill doesn't have to check marklimit.
|
||
|
byte[] newbuf = new byte[marklimit + 1];
|
||
|
System.arraycopy(buf, 0, newbuf, 0, count);
|
||
|
buf = newbuf;
|
||
|
}
|
||
|
|
||
|
int numread = super.read(buf, count, buf.length - count);
|
||
|
|
||
|
if (numread < 0) // EOF
|
||
|
return false;
|
||
|
|
||
|
count += numread;
|
||
|
return true;
|
||
|
}
|
||
|
}
|