|
|
|
package acr.browser.lightning;
|
|
|
|
|
|
|
|
import java.io.FilterInputStream;
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.InputStream;
|
|
|
|
import java.util.Deque;
|
|
|
|
import java.util.Iterator;
|
|
|
|
import java.util.LinkedList;
|
|
|
|
|
|
|
|
public class ReplacingInputStream extends FilterInputStream {
|
|
|
|
|
|
|
|
Deque<Integer> inQueue = new LinkedList<Integer>();
|
|
|
|
|
|
|
|
Deque<Integer> outQueue = new LinkedList<Integer>();
|
|
|
|
|
|
|
|
final byte[] search, replacement;
|
|
|
|
|
|
|
|
protected ReplacingInputStream(InputStream in, byte[] search,
|
|
|
|
byte[] replacement) {
|
|
|
|
super(in);
|
|
|
|
this.search = search;
|
|
|
|
this.replacement = replacement;
|
|
|
|
}
|
|
|
|
|
|
|
|
private boolean isMatchFound() {
|
|
|
|
Iterator<Integer> inIter = inQueue.iterator();
|
|
|
|
for (int i = 0; i < search.length; i++) {
|
|
|
|
if (!inIter.hasNext() || search[i] != inIter.next()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void readAhead() throws IOException {
|
|
|
|
// Work up some look-ahead.
|
|
|
|
while (inQueue.size() < search.length) {
|
|
|
|
int next = super.read();
|
|
|
|
inQueue.offer(next);
|
|
|
|
if (next == -1) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int read() throws IOException {
|
|
|
|
|
|
|
|
// Next byte already determined.
|
|
|
|
if (outQueue.isEmpty()) {
|
|
|
|
|
|
|
|
readAhead();
|
|
|
|
|
|
|
|
if (isMatchFound()) {
|
|
|
|
for (int i = 0; i < search.length; i++) {
|
|
|
|
inQueue.remove();
|
|
|
|
}
|
|
|
|
|
|
|
|
for (byte b : replacement) {
|
|
|
|
outQueue.offer((int) b);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
outQueue.add(inQueue.remove());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return outQueue.remove();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns false. REFilterInputStream does not support mark() and reset() methods.
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public boolean markSupported() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reads from the stream into the provided array.
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public int read(byte[] b, int off, int len) throws IOException {
|
|
|
|
int i;
|
|
|
|
int ok = 0;
|
|
|
|
while (len-- > 0) {
|
|
|
|
i = read();
|
|
|
|
if (i == -1) {
|
|
|
|
return (ok == 0) ? -1 : ok;
|
|
|
|
}
|
|
|
|
b[off++] = (byte) i;
|
|
|
|
ok++;
|
|
|
|
}
|
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int read(byte[] buffer) throws IOException {
|
|
|
|
|
|
|
|
return read(buffer, 0, buffer.length);
|
|
|
|
}
|
|
|
|
}
|