From: Niki Roo Date: Sat, 27 Apr 2019 17:32:15 +0000 (+0200) Subject: ReplaceStreams: allow multiple replacements strings X-Git-Url: http://git.nikiroo.be/?p=nikiroo-utils.git;a=commitdiff_plain;h=627f866e6cd474bd7494750dc3846c5ad898f2ec ReplaceStreams: allow multiple replacements strings --- diff --git a/src/be/nikiroo/utils/streams/ReplaceInputStream.java b/src/be/nikiroo/utils/streams/ReplaceInputStream.java index f5138ee..eea3a1a 100644 --- a/src/be/nikiroo/utils/streams/ReplaceInputStream.java +++ b/src/be/nikiroo/utils/streams/ReplaceInputStream.java @@ -10,8 +10,9 @@ import java.io.InputStream; * @author niki */ public class ReplaceInputStream extends BufferedInputStream { - private byte[] from; - private byte[] to; + private byte[][] froms; + private byte[][] tos; + private int maxToSize; private byte[] source; private int spos; @@ -44,9 +45,55 @@ 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.bytes(froms), StreamUtils.bytes(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; + + if (froms.length != tos.length) { + throw new IllegalArgumentException( + "For replacing, each FROM must have a corresponding TO"); + } + + this.froms = froms; + this.tos = tos; + + for (int i = 0; i < tos.length; i++) { + maxToSize = Math.max(maxToSize, tos[i].length); + } source = new byte[4096]; spos = 0; @@ -55,9 +102,9 @@ public class ReplaceInputStream extends BufferedInputStream { @Override protected int read(InputStream in, byte[] buffer) throws IOException { - if (buffer.length < to.length || source.length < to.length * 2) { + if (buffer.length < maxToSize || source.length < maxToSize * 2) { throw new IOException( - "An underlaying buffer is too small for this replace value"); + "An underlaying buffer is too small for these replace values"); } if (spos >= slen) { @@ -67,13 +114,23 @@ public class ReplaceInputStream extends BufferedInputStream { // Note: very simple, not efficient implementation, sorry. int count = 0; - while (spos < slen && count < buffer.length - to.length) { - if (from.length > 0 - && StreamUtils.startsWith(from, source, spos, slen)) { - System.arraycopy(to, 0, buffer, spos, to.length); - count += to.length; - spos += from.length; - } else { + while (spos < slen && count < buffer.length - 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); + count += tos[i].length; + } + + spos += froms[i].length; + replaced = true; + break; + } + } + + if (!replaced) { buffer[count++] = source[spos++]; } } diff --git a/src/be/nikiroo/utils/streams/ReplaceOutputStream.java b/src/be/nikiroo/utils/streams/ReplaceOutputStream.java index e889b76..dcb0207 100644 --- a/src/be/nikiroo/utils/streams/ReplaceOutputStream.java +++ b/src/be/nikiroo/utils/streams/ReplaceOutputStream.java @@ -10,8 +10,8 @@ import java.io.OutputStream; * @author niki */ public class ReplaceOutputStream extends BufferedOutputStream { - private byte[] from; - private byte[] to; + private byte[][] froms; + private byte[][] tos; /** * Create a {@link ReplaceOutputStream} that will replace from with @@ -40,23 +40,76 @@ public class ReplaceOutputStream extends BufferedOutputStream { * the value to replace with */ public ReplaceOutputStream(OutputStream out, byte[] from, byte[] to) { + this(out, new byte[][] { from }, new byte[][] { to }); + } + + /** + * Create a {@link ReplaceOutputStream} 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 out + * the under-laying {@link OutputStream} + * @param froms + * the values to replace + * @param tos + * the values to replace with + */ + public ReplaceOutputStream(OutputStream out, String[] froms, String[] tos) { + this(out, StreamUtils.bytes(froms), StreamUtils.bytes(tos)); + } + + /** + * Create a {@link ReplaceOutputStream} 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 out + * the under-laying {@link OutputStream} + * @param froms + * the values to replace + * @param tos + * the values to replace with + */ + public ReplaceOutputStream(OutputStream out, byte[][] froms, byte[][] tos) { super(out); bypassFlush = false; - this.from = from; - this.to = to; + if (froms.length != tos.length) { + throw new IllegalArgumentException( + "For replacing, each FROM must have a corresponding TO"); + } + + this.froms = froms; + this.tos = tos; } @Override protected void flush(boolean includingSubStream) throws IOException { // Note: very simple, not efficient implementation, sorry. while (start < stop) { - if (from.length > 0 - && StreamUtils.startsWith(from, buffer, start, stop)) { - out.write(to); - bytesWritten += to.length; - start += from.length; - } else { + boolean replaced = false; + for (int i = 0; i < froms.length; i++) { + if (froms[i] != null + && froms[i].length > 0 + && StreamUtils + .startsWith(froms[i], buffer, start, stop)) { + if (tos[i] != null && tos[i].length > 0) { + out.write(tos[i]); + bytesWritten += tos[i].length; + } + + start += froms[i].length; + replaced = true; + break; + } + } + + if (!replaced) { out.write(buffer[start++]); bytesWritten++; } diff --git a/src/be/nikiroo/utils/streams/StreamUtils.java b/src/be/nikiroo/utils/streams/StreamUtils.java index 6b8251a..9b9ffe6 100644 --- a/src/be/nikiroo/utils/streams/StreamUtils.java +++ b/src/be/nikiroo/utils/streams/StreamUtils.java @@ -55,7 +55,7 @@ class StreamUtils { * UTF-8. * * @param str - * the string to transform into bytes + * the {@link String} to transform into bytes * @return the content in bytes */ static public byte[] bytes(String str) { @@ -67,4 +67,26 @@ class StreamUtils { return null; } } + + /** + * Return the bytes array representation of the given {@link String} in + * UTF-8. + * + * @param strs + * the {@link String}s to transform into bytes + * @return the content in bytes + */ + static public byte[][] bytes(String[] strs) { + try { + byte[][] bytes = new byte[strs.length][]; + for (int i = 0; i < strs.length; i++) { + bytes[i] = strs[i].getBytes("UTF-8"); + } + return bytes; + } catch (UnsupportedEncodingException e) { + // All conforming JVM must support UTF-8 + e.printStackTrace(); + return null; + } + } }