package mireka.filter.misc;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
public abstract class ThresholdingInputStream extends FilterInputStream {
/** When to trigger */
int threshold;
/** Number of bytes read so far */
int read = 0;
/**
* Number of bytes read when the {@link #mark(int)} method was called last
* time
*/
int markPosition = 0;
boolean thresholdReached = false;
/**
*/
public ThresholdingInputStream(InputStream in, int thresholdBytes) {
super(in);
this.in = in;
this.threshold = thresholdBytes;
}
/*
* (non-Javadoc)
*
* @see java.io.FilterInputStream#mark(int)
*/
@Override
public synchronized void mark(int readlimit) {
super.mark(readlimit);
this.markPosition = read;
}
/*
* (non-Javadoc)
*
* @see java.io.InputStream#read(byte[], int, int)
*/
@Override
public int read(byte[] b, int off, int len) throws IOException {
int actualLength = this.in.read(b, off, len);
if (actualLength == -1)
return -1;
this.read += actualLength;
this.checkThreshold();
return actualLength;
}
/*
* (non-Javadoc)
*
* @see java.io.InputStream#read(byte[])
*/
@Override
public int read(byte[] b) throws IOException {
int actualLength = this.in.read(b);
if (actualLength == -1)
return -1;
this.read += actualLength;
this.checkThreshold();
return actualLength;
}
/*
* (non-Javadoc)
*
* @see java.io.InputStream#read()
*/
@Override
public int read() throws IOException {
int ch = this.in.read();
if (ch == -1)
return -1;
this.read++;
this.checkThreshold();
return ch;
}
/*
* (non-Javadoc)
*
* @see java.io.FilterInputStream#reset()
*/
@Override
public synchronized void reset() throws IOException {
super.reset();
this.read = markPosition;
}
/*
* (non-Javadoc)
*
* @see java.io.FilterInputStream#skip(long)
*/
@Override
public long skip(long n) throws IOException {
long skipped = this.in.skip(n);
if (skipped > Integer.MAX_VALUE)
throw new IOException(
"Skipping more then MAX_INT bytes are not supported");
if (skipped <= 0)
return skipped;
int actualLength = (int) skipped;
this.read += actualLength;
this.checkThreshold();
return skipped;
}
/**
* Checks whether reading count bytes would cross the limit.
*/
protected void checkThreshold() throws IOException {
if (!this.thresholdReached && this.read > this.threshold) {
this.thresholdReached(this.read);
this.thresholdReached = true;
}
}
/**
* @return the current threshold value.
*/
public int getThreshold() {
return this.threshold;
}
/**
* Called when the threshold is about to be exceeded. This isn't exact; it's
* called whenever a write would occur that would cross the amount. Once it
* is called, it isn't called again.
*
* @param current
* is the current number of bytes that have been written
*/
abstract protected void thresholdReached(int current) throws IOException;
}