From d251f3dd38a8f9d369a7cf627185eacc4f66ece5 Mon Sep 17 00:00:00 2001 From: Niki Roo Date: Mon, 29 Apr 2019 23:58:39 +0200 Subject: [PATCH] code cleanup + fixes --- .../utils/serial/CustomSerializer.java | 2 +- src/be/nikiroo/utils/serial/Importer.java | 41 ++++++--- .../utils/streams/BufferedInputStream.java | 27 +++++- .../test_code/NextableInputStreamTest.java | 91 +++++++++++++++---- 4 files changed, 130 insertions(+), 31 deletions(-) diff --git a/src/be/nikiroo/utils/serial/CustomSerializer.java b/src/be/nikiroo/utils/serial/CustomSerializer.java index fe63f71..496fcb1 100644 --- a/src/be/nikiroo/utils/serial/CustomSerializer.java +++ b/src/be/nikiroo/utils/serial/CustomSerializer.java @@ -171,7 +171,7 @@ public abstract class CustomSerializer { } public static boolean isCustom(BufferedInputStream in) throws IOException { - return in.startsWiths("custom^"); + return in.startsWith("custom^"); } public static String typeOf(String encodedValue) { diff --git a/src/be/nikiroo/utils/serial/Importer.java b/src/be/nikiroo/utils/serial/Importer.java index 5b75d31..6718fb8 100644 --- a/src/be/nikiroo/utils/serial/Importer.java +++ b/src/be/nikiroo/utils/serial/Importer.java @@ -89,8 +89,8 @@ public class Importer { } first = false; - boolean zip = stream.startsWiths("ZIP:"); - boolean b64 = stream.startsWiths("B64:"); + boolean zip = stream.startsWith("ZIP:"); + boolean b64 = stream.startsWith("B64:"); if (zip || b64) { stream.skip("XXX:".length()); @@ -137,8 +137,9 @@ public class Importer { * @throws IOException * if the content cannot be read (for instance, corrupt data) */ - private boolean processLine(BufferedInputStream in) throws NoSuchFieldException, - NoSuchMethodException, ClassNotFoundException, IOException { + private boolean processLine(BufferedInputStream in) + throws NoSuchFieldException, NoSuchMethodException, + ClassNotFoundException, IOException { // Defer to latest child if any if (child != null) { @@ -153,16 +154,34 @@ public class Importer { return false; } - // TODO use the stream, Luke - String line = IOUtils.readSmallStream(in); - - if (line.equals("{")) { // START: new child if needed + // Start/Stop object + if (in.is("{")) { // START: new child if needed if (link != null) { child = new Importer(map); } - } else if (line.equals("}")) { // STOP: report self to parent + in.end(); + return false; + } else if (in.is("}")) { // STOP: report self to parent + in.end(); return true; - } else if (line.startsWith("REF ")) { // REF: create/link self + } + + // Custom objects + if (CustomSerializer.isCustom(in)) { + // not a field value but a direct value + String line = IOUtils.readSmallStream(in); + me = SerialUtils.decode(line); + return false; + } + + // TODO use the stream, Luke + // .. at least for REF + String line = IOUtils.readSmallStream(in); + + if (line.startsWith("REF ")) { // REF: create/link self + // TODO: here, line is REF type@999:xxx + // xxx is optional + // note: use .end() when containsKey(ref) String[] tab = line.substring("REF ".length()).split("@"); String type = tab[0]; tab = tab[1].split(":"); @@ -188,7 +207,7 @@ public class Importer { // field value is compound currentFieldName = line.substring(0, line.length() - 1); } else if (line.startsWith(":") || !line.contains(":") - || line.startsWith("\"") || CustomSerializer.isCustom(line)) { + || line.startsWith("\"")) { // not a field value but a direct value me = SerialUtils.decode(line); } else { diff --git a/src/be/nikiroo/utils/streams/BufferedInputStream.java b/src/be/nikiroo/utils/streams/BufferedInputStream.java index 336dba4..d1f53df 100644 --- a/src/be/nikiroo/utils/streams/BufferedInputStream.java +++ b/src/be/nikiroo/utils/streams/BufferedInputStream.java @@ -174,7 +174,7 @@ public class BufferedInputStream extends InputStream { */ public boolean is(byte[] search) throws IOException { if (startsWith(search)) { - return stop == search.length; + return (stop - start) == search.length; } return false; @@ -196,7 +196,7 @@ public class BufferedInputStream extends InputStream { * in case of I/O error or if the size of the search term is * greater than the internal buffer */ - public boolean startsWiths(String search) throws IOException { + public boolean startsWith(String search) throws IOException { return startsWith(StringUtils.getBytes(search)); } @@ -204,6 +204,9 @@ public class BufferedInputStream extends InputStream { * Check if the current content (what will be read next) starts with the * given search term. *

+ * An empty string will always return true (unless the stream is closed, + * which would throw an {@link IOException}). + *

* Note: the search term size must be smaller or equal the internal * buffer size. * @@ -232,7 +235,7 @@ public class BufferedInputStream extends InputStream { if (available() >= search.length) { // Easy path return StreamUtils.startsWith(search, buffer, start, stop); - } else if (!eof) { + } else if (in != null && !eof) { // Harder path if (buffer2 == null && buffer.length == originalBuffer.length) { buffer2 = Arrays.copyOf(buffer, buffer.length * 2); @@ -280,6 +283,24 @@ public class BufferedInputStream extends InputStream { return !hasMoreData(); } + /** + * Read the whole {@link InputStream} until the end and return the number of + * bytes read. + * + * @return the number of bytes read + * + * @throws IOException + * in case of I/O error + */ + public long end() throws IOException { + long skipped = 0; + while (hasMoreData()) { + skipped += skip(buffer.length); + } + + return skipped; + } + @Override public int read() throws IOException { checkClose(); diff --git a/src/be/nikiroo/utils/test_code/NextableInputStreamTest.java b/src/be/nikiroo/utils/test_code/NextableInputStreamTest.java index 70123b9..f8031f0 100644 --- a/src/be/nikiroo/utils/test_code/NextableInputStreamTest.java +++ b/src/be/nikiroo/utils/test_code/NextableInputStreamTest.java @@ -103,10 +103,9 @@ public class NextableInputStreamTest extends TestLauncher { new NextableInputStreamStep(12)); checkNext(this, "FIRST", in, new byte[] { 42 }); - checkNextAll(this, "REST", in, - new byte[] { 0, 127, 12, 51, 11, 12 }); - assertEquals("The stream still has some data", false, - in.next()); + checkNextAll(this, "REST", in, new byte[] { 0, 127, 12, 51, 11, + 12 }); + assertEquals("The stream still has some data", false, in.next()); } }); @@ -146,8 +145,19 @@ public class NextableInputStreamTest extends TestLauncher { NextableInputStream in = new NextableInputStream(data, null); in.next(); + byte[] rest = new byte[] { 12, 51, 11, 12 }; + in.skip(4); - checkArrays(this, "ONLY", in, new byte[] { 12, 51, 11, 12 }); + assertEquals("STARTS_WITH OK_1", true, in.startsWith(rest)); + assertEquals("STARTS_WITH KO_1", false, + in.startsWith(new byte[] { 0 })); + assertEquals("STARTS_WITH KO_2", false, in.startsWith(data)); + assertEquals("STARTS_WITH KO_3", false, + in.startsWith(new byte[] { 1, 2, 3 })); + assertEquals("STARTS_WITH OK_2", true, in.startsWith(rest)); + assertEquals("READ REST", IOUtils.readSmallStream(in), + new String(rest)); + in.close(); } }); @@ -169,17 +179,21 @@ public class NextableInputStreamTest extends TestLauncher { // no assertEquals("It actually does not start with that", false, in.startsWith(new byte[] { 12 })); - assertEquals("It actually does not start with that", false, - in.startsWith( - new byte[] { 42, 12, 0, 127, 12, 51, 11, 11 })); + assertEquals( + "It actually does not start with that", + false, + in.startsWith(new byte[] { 42, 12, 0, 127, 12, 51, 11, + 11 })); // too big try { - in.startsWith( - new byte[] { 42, 12, 0, 127, 12, 51, 11, 12, 0 }); + in.startsWith(new byte[] { 42, 12, 0, 127, 12, 51, 11, 12, + 0 }); fail("Searching a prefix bigger than the array should throw an IOException"); } catch (IOException e) { } + + in.close(); } }); @@ -193,24 +207,69 @@ public class NextableInputStreamTest extends TestLauncher { // yes assertEquals("It actually starts with that", true, - in.startsWiths("F")); + in.startsWith("F")); assertEquals("It actually starts with that", true, - in.startsWiths("Fanfan et")); + in.startsWith("Fanfan et")); assertEquals("It actually is the same text", true, - in.startsWiths(text)); + in.startsWith(text)); // no assertEquals("It actually does not start with that", false, - in.startsWiths("Toto")); + in.startsWith("Toto")); assertEquals("It actually does not start with that", false, - in.startsWiths("Fanfan et Toto vont à la mee")); + in.startsWith("Fanfan et Toto vont à la mee")); // too big try { - in.startsWiths("Fanfan et Toto vont à la mer."); + in.startsWith("Fanfan et Toto vont à la mer."); fail("Searching a prefix bigger than the array should throw an IOException"); } catch (IOException e) { } + + in.close(); + } + }); + + addTest(new TestCase("Starts With strings + steps") { + @Override + public void test() throws Exception { + String data = "{\nREF: fanfan\n}"; + NextableInputStream in = new NextableInputStream( + data.getBytes("UTF-8"), new NextableInputStreamStep( + '\n')); + in.next(); + + assertEquals("STARTS_WITH OK", true, in.startsWith("{")); + in.skip(1); + assertEquals("STARTS_WITH WHEN SPENT", false, + in.startsWith("{")); + + checkNext(this, "PARTIAL CONTENT", in, + "REF: fanfan".getBytes("UTF-8")); + } + }); + + addTest(new TestCase("InputStream is(String)") { + @Override + public void test() throws Exception { + String data = "{\nREF: fanfan\n}"; + NextableInputStream in = new NextableInputStream( + new ByteArrayInputStream(data.getBytes("UTF-8")), + new NextableInputStreamStep('\n')); + + in.next(); + assertEquals("Item 1 OK", true, in.is("{")); + assertEquals("Item 1 KO_1", false, in.is("|")); + assertEquals("Item 1 KO_2", false, in.is("{}")); + in.skip(1); + in.next(); + assertEquals("Item 2 OK", true, in.is("REF: fanfan")); + assertEquals("Item 2 KO", false, in.is("REF: fanfan.")); + IOUtils.readSmallStream(in); + in.next(); + assertEquals("Item 3 OK", true, in.is("}")); + + in.close(); } }); } -- 2.27.0