code cleanup, fix for ReplaceInputStream
[nikiroo-utils.git] / src / be / nikiroo / utils / streams / ReplaceInputStream.java
index eea3a1ab9b74b42158d5b40e565b59c839cb690a..5332e72d11651cb7da0588e817bbb10310a39449 100644 (file)
@@ -10,8 +10,18 @@ import java.io.InputStream;
  * @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).
+        * <p>
+        * 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 maxFromSize;
        private int maxToSize;
 
        private byte[] source;
@@ -91,36 +101,46 @@ public class ReplaceInputStream extends BufferedInputStream {
                this.froms = froms;
                this.tos = tos;
 
+               maxFromSize = 0;
+               for (int i = 0; i < froms.length; i++) {
+                       maxFromSize = Math.max(maxFromSize, froms[i].length);
+               }
+
+               maxToSize = 0;
                for (int i = 0; i < tos.length; i++) {
                        maxToSize = Math.max(maxToSize, tos[i].length);
                }
 
-               source = new byte[4096];
+               // We need at least maxFromSize so we can iterate and replace
+               source = new byte[Math.max(2 * maxFromSize, MIN_BUFFER_SIZE)];
                spos = 0;
                slen = 0;
        }
 
        @Override
-       protected int read(InputStream in, byte[] buffer) throws IOException {
-               if (buffer.length < maxToSize || source.length < maxToSize * 2) {
+       protected int read(InputStream in, byte[] buffer, int off, int len)
+                       throws IOException {
+               if (len < maxToSize || source.length < maxToSize * 2) {
                        throw new IOException(
                                        "An underlaying buffer is too small for these replace values");
                }
 
-               if (spos >= slen) {
+               // We need at least one byte of data to process
+               if (available() < Math.max(maxFromSize, 1) && !eof) {
                        spos = 0;
                        slen = in.read(source);
                }
 
-               // Note: very simple, not efficient implementation, sorry.
+               // Note: very simple, not efficient implementation; sorry.
                int count = 0;
-               while (spos < slen && count < buffer.length - maxToSize) {
+               while (spos < slen && count < len - maxToSize) {
                        boolean replaced = false;
                        for (int i = 0; i < froms.length; i++) {
                                if (froms[i] != null && froms[i].length > 0
                                                && StreamUtils.startsWith(froms[i], source, spos, slen)) {
                                        if (tos[i] != null && tos[i].length > 0) {
-                                               System.arraycopy(tos[i], 0, buffer, spos, tos[i].length);
+                                               System.arraycopy(tos[i], 0, buffer, off + spos,
+                                                               tos[i].length);
                                                count += tos[i].length;
                                        }
 
@@ -131,7 +151,7 @@ public class ReplaceInputStream extends BufferedInputStream {
                        }
 
                        if (!replaced) {
-                               buffer[count++] = source[spos++];
+                               buffer[off + count++] = source[spos++];
                        }
                }