From 4098af704dfa22ce4a60003940753c28030374fa Mon Sep 17 00:00:00 2001 From: Niki Date: Wed, 24 Apr 2019 16:29:50 +0200 Subject: [PATCH] NextableInputStream, step 2 --- src/be/nikiroo/utils/NextableInputStream.java | 67 +++++++++++++++++-- .../utils/NextableInputStreamStep.java | 52 ++++++++++++++ .../test_code/NextableInputStreamTest.java | 62 +++++++++++++++++ src/be/nikiroo/utils/test_code/Test.java | 1 + 4 files changed, 175 insertions(+), 7 deletions(-) create mode 100755 src/be/nikiroo/utils/NextableInputStreamStep.java diff --git a/src/be/nikiroo/utils/NextableInputStream.java b/src/be/nikiroo/utils/NextableInputStream.java index 0bcbe14..6f3afc2 100644 --- a/src/be/nikiroo/utils/NextableInputStream.java +++ b/src/be/nikiroo/utils/NextableInputStream.java @@ -2,8 +2,13 @@ package be.nikiroo.utils; import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; public class NextableInputStream extends InputStream { + private List steps = new ArrayList(); + private NextableInputStreamStep step = null; + private InputStream in; private boolean eof; private int pos = 0; @@ -14,6 +19,25 @@ public class NextableInputStream extends InputStream { this.in = in; } + public void addStep(NextableInputStreamStep step) { + steps.add(step); + } + + public boolean next() { + if (!hasMoreData() && step != null) { + len = step.getResumeLen(); + pos += step.getSkip(); + eof = false; + step = null; + + checkNexts(false); + + return true; + } + + return false; + } + @Override public int read() throws IOException { preRead(); @@ -40,27 +64,56 @@ public class NextableInputStream extends InputStream { } int done = 0; - while (!eof && done < blen) { + while (hasMoreData() && done < blen) { preRead(); - for (int i = pos; i < blen && i < len; i++) { - b[boff + done] = buffer[i]; - pos++; - done++; + if (hasMoreData()) { + for (int i = pos; i < blen && i < len; i++) { + b[boff + done] = buffer[i]; + pos++; + done++; + } } } return done > 0 ? done : -1; } + @Override + public int available() throws IOException { + return Math.max(0, len - pos); + } + private void preRead() throws IOException { - if (in != null && !eof && pos >= len) { + if (!eof && in != null && pos >= len && step == null) { pos = 0; len = in.read(buffer); - // checkNexts(); + checkNexts(true); } if (pos >= len) { eof = true; } } + + private boolean hasMoreData() { + return !(eof && pos >= len); + } + + private void checkNexts(boolean newBuffer) { + if (!eof) { + for (NextableInputStreamStep step : steps) { + if (newBuffer) { + step.clearBuffer(); + } + + int stopAt = step.stop(buffer, pos, len); + if (stopAt >= 0) { + this.step = step; + len = stopAt; + eof = true; + break; + } + } + } + } } diff --git a/src/be/nikiroo/utils/NextableInputStreamStep.java b/src/be/nikiroo/utils/NextableInputStreamStep.java new file mode 100755 index 0000000..ab22562 --- /dev/null +++ b/src/be/nikiroo/utils/NextableInputStreamStep.java @@ -0,0 +1,52 @@ +package be.nikiroo.utils; + +public class NextableInputStreamStep { + private int stopAt; + private boolean disabled; + private int pos; + private int resumeLen; + private int last = -1; + private int skip; + + public NextableInputStreamStep(int byt) { + stopAt = byt; + } + + // do NOT stop twice on the same item + public int stop(byte[] buffer, int pos, int len) { + for (int i = pos; i < len; i++) { + if (buffer[i] == stopAt) { + if (i > this.last) { + // we skip the sep + this.skip = 1; + + this.pos = pos; + this.resumeLen = len; + this.last = i; + return i; + } + } + } + + return -1; + } + + public int getResumeLen() { + return resumeLen; + } + + public int getSkip() { + return skip; + } + + public void clearBuffer() { + this.last = -1; + this.pos = 0; + this.skip = 0; + this.resumeLen = 0; + } + + public boolean isEnabled() { + return !disabled; + } +} diff --git a/src/be/nikiroo/utils/test_code/NextableInputStreamTest.java b/src/be/nikiroo/utils/test_code/NextableInputStreamTest.java index 1b0064d..51ff128 100644 --- a/src/be/nikiroo/utils/test_code/NextableInputStreamTest.java +++ b/src/be/nikiroo/utils/test_code/NextableInputStreamTest.java @@ -5,6 +5,7 @@ import java.io.InputStream; import be.nikiroo.utils.IOUtils; import be.nikiroo.utils.NextableInputStream; +import be.nikiroo.utils.NextableInputStreamStep; import be.nikiroo.utils.test.TestCase; import be.nikiroo.utils.test.TestLauncher; @@ -29,5 +30,66 @@ public class NextableInputStreamTest extends TestLauncher { } } }); + + addTest(new TestCase("Stop at 12") { + @Override + public void test() throws Exception { + byte[] expected = new byte[] { 42, 12, 0, 127 }; + InputStream bin = new ByteArrayInputStream(expected); + NextableInputStream in = new NextableInputStream(bin); + in.addStep(new NextableInputStreamStep(12)); + byte[] actual = IOUtils.toByteArray(in); + + assertEquals( + "The resulting array has not the correct number of items", + 1, actual.length); + for (int i = 0; i < actual.length; i++) { + assertEquals("Item " + i + " (0-based) is not the same", + expected[i], actual[i]); + } + } + }); + + addTest(new TestCase("Stop at 12, resume, stop again, resume") { + @Override + public void test() throws Exception { + byte[] expected = new byte[] { 42, 12, 0, 127, 12, 51, 11, 12 }; + NextableInputStream in = new NextableInputStream( + new ByteArrayInputStream(expected)); + in.addStep(new NextableInputStreamStep(12)); + + byte[] actual1 = IOUtils.toByteArray(in); + byte[] expected1 = new byte[] { 42 }; + assertEquals( + "The FIRST resulting array has not the correct number of items", + expected1.length, actual1.length); + for (int i = 0; i < actual1.length; i++) { + assertEquals("Item " + i + " (0-based) is not the same", + expected1[i], actual1[i]); + } + + assertEquals("Cannot get SECOND entry", true, in.next()); + byte[] actual2 = IOUtils.toByteArray(in); + byte[] expected2 = new byte[] { 0, 127 }; + assertEquals( + "The SECOND resulting array has not the correct number of items", + expected2.length, actual2.length); + for (int i = 0; i < actual2.length; i++) { + assertEquals("Item " + i + " (0-based) is not the same", + expected2[i], actual2[i]); + } + + assertEquals("Cannot get next THIRD entry", true, in.next()); + byte[] actual3 = IOUtils.toByteArray(in); + byte[] expected3 = new byte[] { 51, 11 }; + assertEquals( + "The THIRD resulting array has not the correct number of items", + expected3.length, actual3.length); + for (int i = 0; i < actual3.length; i++) { + assertEquals("Item " + i + " (0-based) is not the same", + expected3[i], actual3[i]); + } + } + }); } } diff --git a/src/be/nikiroo/utils/test_code/Test.java b/src/be/nikiroo/utils/test_code/Test.java index f25c02d..01766ac 100644 --- a/src/be/nikiroo/utils/test_code/Test.java +++ b/src/be/nikiroo/utils/test_code/Test.java @@ -33,6 +33,7 @@ public class Test extends TestLauncher { addSeries(new StringUtilsTest(args)); addSeries(new TempFilesTest(args)); addSeries(new CryptUtilsTest(args)); + addSeries(new NextableInputStreamTest(args)); // TODO: test cache and downloader Cache cache = null; -- 2.27.0