From 7194ac50b29064a013f177fc9cfc5aaa131a8ec4 Mon Sep 17 00:00:00 2001 From: Niki Roo Date: Mon, 29 Apr 2019 20:10:07 +0200 Subject: [PATCH] code cleanup, fix for ReplaceInputStream --- src/be/nikiroo/utils/Cache.java | 3 +- src/be/nikiroo/utils/IOUtils.java | 12 ++------ src/be/nikiroo/utils/Image.java | 3 +- src/be/nikiroo/utils/streams/Base64.java | 14 +++++---- .../utils/streams/Base64InputStream.java | 30 ++++++++++++------- .../utils/streams/BufferedInputStream.java | 13 ++++++-- .../streams/MarkableFileInputStream.java | 15 ++++++++++ .../utils/streams/NextableInputStream.java | 8 ++++- .../utils/streams/ReplaceInputStream.java | 24 +++++++++++++-- .../utils/streams/ReplaceOutputStream.java | 23 +++++++++++++- 10 files changed, 109 insertions(+), 36 deletions(-) diff --git a/src/be/nikiroo/utils/Cache.java b/src/be/nikiroo/utils/Cache.java index cf8a780..ff2859e 100644 --- a/src/be/nikiroo/utils/Cache.java +++ b/src/be/nikiroo/utils/Cache.java @@ -1,7 +1,6 @@ package be.nikiroo.utils; import java.io.File; -import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; @@ -265,7 +264,7 @@ public class Cache { if (cached.exists() && cached.isFile() && (allowTooOld || !isOld(cached, stable))) { try { - return new MarkableFileInputStream(new FileInputStream(cached)); + return new MarkableFileInputStream(cached); } catch (FileNotFoundException e) { return null; } diff --git a/src/be/nikiroo/utils/IOUtils.java b/src/be/nikiroo/utils/IOUtils.java index 9ab638a..fa18d0d 100644 --- a/src/be/nikiroo/utils/IOUtils.java +++ b/src/be/nikiroo/utils/IOUtils.java @@ -410,19 +410,11 @@ public class IOUtils { write(in, tmp); in.close(); - final FileInputStream fis = new FileInputStream(tmp); - return new MarkableFileInputStream(fis) { + return new MarkableFileInputStream(tmp) { @Override public void close() throws IOException { try { - try { - super.close(); - } finally { - try { - fis.close(); - } catch (IOException e) { - } - } + super.close(); } finally { tmp.delete(); } diff --git a/src/be/nikiroo/utils/Image.java b/src/be/nikiroo/utils/Image.java index f2b9499..58b1f5a 100644 --- a/src/be/nikiroo/utils/Image.java +++ b/src/be/nikiroo/utils/Image.java @@ -3,7 +3,6 @@ package be.nikiroo.utils; import java.io.ByteArrayInputStream; import java.io.Closeable; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; @@ -81,7 +80,7 @@ public class Image implements Closeable { * in case of I/O error */ public InputStream newInputStream() throws IOException { - return new MarkableFileInputStream(new FileInputStream(data)); + return new MarkableFileInputStream(data); } /** diff --git a/src/be/nikiroo/utils/streams/Base64.java b/src/be/nikiroo/utils/streams/Base64.java index a4f1240..76b4be4 100644 --- a/src/be/nikiroo/utils/streams/Base64.java +++ b/src/be/nikiroo/utils/streams/Base64.java @@ -260,7 +260,8 @@ class Base64 { * @return an overestimate for the number of bytes {@code * len} bytes could decode to. */ - public int maxOutputSize(int len) { + @Override + public int maxOutputSize(int len) { return len * 3/4 + 10; } @@ -270,7 +271,8 @@ class Base64 { * @return true if the state machine is still healthy. false if * bad base-64 data has been detected in the input stream. */ - public boolean process(byte[] input, int offset, int len, boolean finish) { + @Override + public boolean process(byte[] input, int offset, int len, boolean finish) { if (this.state == 6) return false; int p = offset; @@ -606,11 +608,13 @@ class Base64 { * @return an overestimate for the number of bytes {@code * len} bytes could encode to. */ - public int maxOutputSize(int len) { + @Override + public int maxOutputSize(int len) { return len * 8/5 + 10; } - public boolean process(byte[] input, int offset, int len, boolean finish) { + @Override + public boolean process(byte[] input, int offset, int len, boolean finish) { // Using local variables makes the encoder about 9% faster. final byte[] alphabet = this.alphabet; final byte[] output = this.output; @@ -638,7 +642,7 @@ class Base64 { ((input[p++] & 0xff) << 8) | (input[p++] & 0xff); tailLen = 0; - }; + } break; case 2: diff --git a/src/be/nikiroo/utils/streams/Base64InputStream.java b/src/be/nikiroo/utils/streams/Base64InputStream.java index b235741..a3afaef 100644 --- a/src/be/nikiroo/utils/streams/Base64InputStream.java +++ b/src/be/nikiroo/utils/streams/Base64InputStream.java @@ -70,28 +70,36 @@ public class Base64InputStream extends FilterInputStream { outputEnd = 0; } - public boolean markSupported() { + @Override + public boolean markSupported() { return false; } - public void mark(int readlimit) { + @SuppressWarnings("sync-override") + @Override + public void mark(int readlimit) { throw new UnsupportedOperationException(); } - public void reset() { + @SuppressWarnings("sync-override") + @Override + public void reset() { throw new UnsupportedOperationException(); } - public void close() throws IOException { + @Override + public void close() throws IOException { in.close(); inputBuffer = null; } - public int available() { + @Override + public int available() { return outputEnd - outputStart; } - public long skip(long n) throws IOException { + @Override + public long skip(long n) throws IOException { if (outputStart >= outputEnd) { refill(); } @@ -103,18 +111,20 @@ public class Base64InputStream extends FilterInputStream { return bytes; } - public int read() throws IOException { + @Override + public int read() throws IOException { if (outputStart >= outputEnd) { refill(); } if (outputStart >= outputEnd) { return -1; - } else { - return coder.output[outputStart++] & 0xff; } + + return coder.output[outputStart++] & 0xff; } - public int read(byte[] b, int off, int len) throws IOException { + @Override + public int read(byte[] b, int off, int len) throws IOException { if (outputStart >= outputEnd) { refill(); } diff --git a/src/be/nikiroo/utils/streams/BufferedInputStream.java b/src/be/nikiroo/utils/streams/BufferedInputStream.java index 397f6fc..42f0d9d 100644 --- a/src/be/nikiroo/utils/streams/BufferedInputStream.java +++ b/src/be/nikiroo/utils/streams/BufferedInputStream.java @@ -14,13 +14,22 @@ import java.util.Arrays; * @author niki */ public class BufferedInputStream extends InputStream { + /** + * The size of the internal buffer (can be different if you pass your own + * buffer, of course). + *

+ * A second buffer of twice the size can sometimes be created as needed for + * the {@link BufferedInputStream#startsWith(byte[])} search operation. + */ + static private final int BUFFER_SIZE = 4096; + /** The current position in the buffer. */ protected int start; /** The index of the last usable position of the buffer. */ protected int stop; /** The buffer itself. */ protected byte[] buffer; - /** An End-Of-File (or buffer, here) marker. */ + /** An End-Of-File (or {@link InputStream}, here) marker. */ protected boolean eof; private boolean closed; @@ -45,7 +54,7 @@ public class BufferedInputStream extends InputStream { public BufferedInputStream(InputStream in) { this.in = in; - this.buffer = new byte[4096]; + this.buffer = new byte[BUFFER_SIZE]; this.originalBuffer = this.buffer; this.start = 0; this.stop = 0; diff --git a/src/be/nikiroo/utils/streams/MarkableFileInputStream.java b/src/be/nikiroo/utils/streams/MarkableFileInputStream.java index dab4cdc..7622b24 100644 --- a/src/be/nikiroo/utils/streams/MarkableFileInputStream.java +++ b/src/be/nikiroo/utils/streams/MarkableFileInputStream.java @@ -1,6 +1,8 @@ package be.nikiroo.utils.streams; +import java.io.File; import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.FilterInputStream; import java.io.IOException; import java.nio.channels.FileChannel; @@ -15,6 +17,19 @@ public class MarkableFileInputStream extends FilterInputStream { private FileChannel channel; private long mark = 0; + /** + * Create a new {@link MarkableFileInputStream} from this file. + * + * @param file + * the {@link File} to wrap + * + * @throws FileNotFoundException + * if the {@link File} cannot be found + */ + public MarkableFileInputStream(File file) throws FileNotFoundException { + this(new FileInputStream(file)); + } + /** * Create a new {@link MarkableFileInputStream} from this stream. * diff --git a/src/be/nikiroo/utils/streams/NextableInputStream.java b/src/be/nikiroo/utils/streams/NextableInputStream.java index 62156e3..550aa24 100644 --- a/src/be/nikiroo/utils/streams/NextableInputStream.java +++ b/src/be/nikiroo/utils/streams/NextableInputStream.java @@ -246,7 +246,13 @@ public class NextableInputStream extends BufferedInputStream { return true; } - public String DEBUG() { + /** + * Display a DEBUG {@link String} representation of this object. + *

+ * Do not use for release code. + */ + @Override + public String toString() { String data = ""; if (stop > 0) { try { diff --git a/src/be/nikiroo/utils/streams/ReplaceInputStream.java b/src/be/nikiroo/utils/streams/ReplaceInputStream.java index b2187af..5332e72 100644 --- a/src/be/nikiroo/utils/streams/ReplaceInputStream.java +++ b/src/be/nikiroo/utils/streams/ReplaceInputStream.java @@ -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). + *

+ * 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,11 +101,18 @@ 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; } @@ -108,12 +125,13 @@ public class ReplaceInputStream extends BufferedInputStream { "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 < len - maxToSize) { boolean replaced = false; diff --git a/src/be/nikiroo/utils/streams/ReplaceOutputStream.java b/src/be/nikiroo/utils/streams/ReplaceOutputStream.java index ff871eb..e7e6c9f 100644 --- a/src/be/nikiroo/utils/streams/ReplaceOutputStream.java +++ b/src/be/nikiroo/utils/streams/ReplaceOutputStream.java @@ -88,9 +88,30 @@ public class ReplaceOutputStream extends BufferedOutputStream { this.tos = tos; } + /** + * Flush the {@link BufferedOutputStream}, write the current buffered data + * to (and optionally also flush) the under-laying stream. + *

+ * If {@link BufferedOutputStream#bypassFlush} is false, all writes to the + * under-laying stream are done in this method. + *

+ * This can be used if you want to write some data in the under-laying + * stream yourself (in that case, flush this {@link BufferedOutputStream} + * with or without flushing the under-laying stream, then you can write to + * the under-laying stream). + *

+ * But be careful! If a replacement could be done with the end o the + * currently buffered data and the start of the data to come, we obviously + * will not be able to do it. + * + * @param includingSubStream + * also flush the under-laying stream + * @throws IOException + * in case of I/O error + */ @Override public void flush(boolean includingSubStream) throws IOException { - // Note: very simple, not efficient implementation, sorry. + // Note: very simple, not efficient implementation; sorry. while (start < stop) { boolean replaced = false; for (int i = 0; i < froms.length; i++) { -- 2.27.0