package be.nikiroo.utils.streams; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import be.nikiroo.utils.StringUtils; /** * This {@link InputStream} will change some of its content by replacing it with * something else. * * @author niki */ public class ReplaceInputStream extends BufferedInputStream { /** * The minimum size of the internal buffer (could be more if at least one of * the 'FROM' bytes arrays is > 2048 bytes — in that case the * buffer will be twice the largest size of the 'FROM' bytes arrays). *
* This is a different buffer than the one from the inherited class. */ static private final int MIN_BUFFER_SIZE = 4096; private byte[][] froms; private byte[][] tos; private int bufferSize; private int maxFromSize; /** * Create a {@link ReplaceInputStream} that will replace from with * to. * * @param in * the under-laying {@link InputStream} * @param from * the {@link String} to replace * @param to * the {@link String} to replace with */ public ReplaceInputStream(InputStream in, String from, String to) { this(in, StringUtils.getBytes(from), StringUtils.getBytes(to)); } /** * Create a {@link ReplaceInputStream} that will replace from with * to. * * @param in * the under-laying {@link InputStream} * @param from * the value to replace * @param to * the value to replace with */ public ReplaceInputStream(InputStream in, byte[] from, byte[] to) { this(in, new byte[][] { from }, new byte[][] { to }); } /** * Create a {@link ReplaceInputStream} that will replace all froms * with tos. *
* Note that they will be replaced in order, and that for each from * a to must correspond. * * @param in * the under-laying {@link InputStream} * @param froms * the values to replace * @param tos * the values to replace with */ public ReplaceInputStream(InputStream in, String[] froms, String[] tos) { this(in, StreamUtils.getBytes(froms), StreamUtils.getBytes(tos)); } /** * Create a {@link ReplaceInputStream} that will replace all froms * with tos. *
* Note that they will be replaced in order, and that for each from
* a to must correspond.
*
* @param in
* the under-laying {@link InputStream}
* @param froms
* the values to replace
* @param tos
* the values to replace with
*/
public ReplaceInputStream(InputStream in, byte[][] froms, byte[][] tos) {
super(in);
if (froms.length != tos.length) {
throw new IllegalArgumentException(
"For replacing, each FROM must have a corresponding TO");
}
this.froms = froms;
this.tos = tos;
maxFromSize = 0;
for (int i = 0; i < froms.length; i++) {
maxFromSize = Math.max(maxFromSize, froms[i].length);
}
int maxToSize = 0;
for (int i = 0; i < tos.length; i++) {
maxToSize = Math.max(maxToSize, tos[i].length);
}
// We need at least maxFromSize so we can iterate and replace
bufferSize = Math.max(4 * Math.max(maxToSize, maxFromSize),
MIN_BUFFER_SIZE);
}
@Override
protected boolean preRead() throws IOException {
boolean rep = super.preRead();
start = stop;
return rep;
}
@Override
protected int read(InputStream in, byte[] buffer) throws IOException {
buffer = null; // do not use the buffer.
byte[] newBuffer = new byte[bufferSize];
int read = 0;
while (read < bufferSize / 2) {
int thisTime = in.read(newBuffer, read, bufferSize / 2 - read);
if (thisTime <= 0) {
break;
}
read += thisTime;
}
List