X-Git-Url: http://git.nikiroo.be/?a=blobdiff_plain;f=src%2Fbe%2Fnikiroo%2Futils%2Fstreams%2FReplaceInputStream.java;h=f5138eefeafc327dbd865e3b89713843c027aa0a;hb=68232a49b2f63e195dfaf1d907bd20c48cf2b394;hp=5eac0b448fef0262b9f2ded53a4c199a2c41d0b7;hpb=8e76f6ab13a8a4a651f2518b6c91d5e6424c7922;p=nikiroo-utils.git diff --git a/src/be/nikiroo/utils/streams/ReplaceInputStream.java b/src/be/nikiroo/utils/streams/ReplaceInputStream.java index 5eac0b4..0860f78 100644 --- a/src/be/nikiroo/utils/streams/ReplaceInputStream.java +++ b/src/be/nikiroo/utils/streams/ReplaceInputStream.java @@ -2,21 +2,31 @@ package be.nikiroo.utils.streams; import java.io.IOException; import java.io.InputStream; -import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.List; + +import be.nikiroo.utils.StringUtils; /** - * This {@link InputStream} will replace some of its content by replacing it - * with something else. + * This {@link InputStream} will change some of its content by replacing it with + * something else. * * @author niki */ public class ReplaceInputStream extends BufferedInputStream { - private byte[] from; - private byte[] to; + /** + * 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[] source; - private int spos; - private int slen; + private byte[][] froms; + private byte[][] tos; + private int bufferSize; + private int maxFromSize; /** * Create a {@link ReplaceInputStream} that will replace from with @@ -30,7 +40,7 @@ public class ReplaceInputStream extends BufferedInputStream { * the {@link String} to replace with */ public ReplaceInputStream(InputStream in, String from, String to) { - this(in, bytes(from), bytes(to)); + this(in, StringUtils.getBytes(from), StringUtils.getBytes(to)); } /** @@ -45,57 +55,163 @@ public class ReplaceInputStream extends BufferedInputStream { * 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);
- this.from = from;
- this.to = to;
- source = new byte[4096];
- spos = 0;
- slen = 0;
+ 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 {
- if (buffer.length < to.length || source.length < to.length * 2) {
- throw new IOException(
- "An underlaying buffer is too small for this replace value");
- }
+ buffer = null; // do not use the buffer.
- if (spos >= slen) {
- spos = 0;
- slen = in.read(source);
+ 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;
}
- // Note: very simple, not efficient implementation, sorry.
- int count = 0;
- while (spos < slen && count < buffer.length - to.length) {
- if (from.length > 0 && startsWith(from, source, spos, slen)) {
- System.arraycopy(to, 0, buffer, spos, to.length);
- count += to.length;
- spos += from.length;
- } else {
- buffer[count++] = source[spos++];
+ List