From 2c9c848ae275705ce315b6061cd06640834c9d9d Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Mon, 13 Mar 2017 18:16:25 -0400 Subject: lazy-parse the version and startTime --- dslog/DseventsReader.java | 106 +++++++++++++++++++------ dslog/DslogReader.java | 136 +++++++++++++++++++++++---------- dslog/Logdir.java | 6 +- dslog/Main.java | 4 +- dslog/PdplogReader.java | 45 +++++++++-- dslog/UnsupportedVersionException.java | 12 +++ 6 files changed, 234 insertions(+), 75 deletions(-) create mode 100644 dslog/UnsupportedVersionException.java diff --git a/dslog/DseventsReader.java b/dslog/DseventsReader.java index 1f7afa7..4ae0215 100644 --- a/dslog/DseventsReader.java +++ b/dslog/DseventsReader.java @@ -1,42 +1,78 @@ package dslog; +import java.io.BufferedInputStream; import java.io.Closeable; import java.io.IOException; import java.io.InputStream; -import java.lang.UnsupportedOperationException; import java.time.Instant; +import java.util.Iterator; +import java.util.NoSuchElementException; -class DseventsReader implements Closeable { - private final InputStream reader; +class DseventsReader implements Closeable, Iterator { + public static class Event { + public Instant time; + public String message; + } - public final int version; - public final Instant startTime; + /*============================================================*\ + || Primitive IO || + \*============================================================*/ + private final InputStream reader; public DseventsReader(InputStream reader) throws IOException { + if (!reader.markSupported()) { + reader = new BufferedInputStream(reader); + } this.reader = reader; - this.version = Read.i32(reader); - switch (this.version) { - case 0: - throw new UnsupportedOperationException("TODO: DSEVENTS v0 support"); - case 1: - case 2: - case 3: // 2016-now - this.startTime = Read.LVTimestamp(reader); - break; - default: - throw new UnsupportedOperationException("DSEVENTS file version ("+this.version+") newer than log reader (3)"); + } + + private boolean atEOF() throws IOException { + reader.mark(2); + boolean eof = (reader.read() < 0); + reader.reset(); + return eof; + } + + /*============================================================*\ + || Parsing || + \*============================================================*/ + + private int m_version; + private boolean m_haveVersion = false; + public int version() throws IOException { + if (!m_haveVersion) { + m_version = Read.i32(reader); + m_haveVersion = true; } + return m_version; } - public static class Event { - public Instant time; - public String message; + private Instant m_startTime; + public Instant startTime() throws IOException { + if (m_startTime == null) { + switch (version()) { + case 0: + throw new UnsupportedVersionException("DSEVENTS (TODO)", 0); + case 1: + case 2: + case 3: // 2016-now + m_startTime = Read.LVTimestamp(reader); + break; + default: + throw new UnsupportedVersionException("DSEVENTS", version(), 3); + } + } + return m_startTime; } public Event readEvent() throws IOException{ - switch (version) { + startTime(); + if (atEOF()) { + return null; + } + switch (version()) { case 0: - throw new UnsupportedOperationException("TODO: DSEVENTS v0 support"); + throw new UnsupportedVersionException("DSEVENTS (TODO)", 0); case 1: case 2: case 3: @@ -45,10 +81,36 @@ class DseventsReader implements Closeable { message = Read.LVString(reader); }}; default: - throw new UnsupportedOperationException("DSEVENTS file version newer than log reader"); + throw new UnsupportedVersionException("DSEVENTS", version(), 3); } } + /*============================================================*\ + || Interfaces || + \*============================================================*/ + + private IOException m_err; + private Event m_next; + public boolean hasNext() { + if (m_next == null) { + try { + m_next = readEvent(); + } catch (IOException e) { + m_err = e; + } + } + return m_next != null; + } + public Event next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + return m_next; + } + public IOException err() { + return m_err; + } + public void close() throws IOException { reader.close(); } diff --git a/dslog/DslogReader.java b/dslog/DslogReader.java index 73d7dc5..1c0af25 100644 --- a/dslog/DslogReader.java +++ b/dslog/DslogReader.java @@ -1,40 +1,16 @@ package dslog; +import java.io.BufferedInputStream; import java.io.Closeable; import java.io.IOException; import java.io.InputStream; -import java.lang.UnsupportedOperationException; import java.time.Duration; import java.time.Instant; +import java.util.Iterator; +import java.util.NoSuchElementException; import java.util.stream.IntStream; -class DslogReader implements Closeable { - private final InputStream reader; - - public final int version; - public final Instant startTime; - private long i = 0; - - public DslogReader(InputStream reader) throws IOException { - this.reader = reader; - this.version = Read.i32(reader); - switch (this.version) { - case 0: // ????-???? 2012 - this.startTime = Read.LVTimestamp(reader); - break; - case 1: // ????-???? 2014 - this.startTime = Read.LVTimestamp(reader); - break; - case 2: // ????-2015 - throw new UnsupportedOperationException("TODO: DSLOG v2 support"); - case 3: // 2016-now - this.startTime = Read.LVTimestamp(reader); - break; - default: - throw new UnsupportedOperationException("DSLOG file version ("+this.version+") newer than log reader (3)"); - } - } - +class DslogReader implements Closeable, Iterator { public static class Entry { public Instant time; @@ -62,14 +38,70 @@ class DslogReader implements Closeable { public short pdpTemperature; } - /** - * @see https://www.chiefdelphi.com/forums/showthread.php?t=104689 - */ - public Entry readEntry() throws IOException{ - switch (version) { + /*============================================================*\ + || Primitive IO || + \*============================================================*/ + + private final InputStream reader; + public DslogReader(InputStream reader) throws IOException { + if (!reader.markSupported()) { + reader = new BufferedInputStream(reader); + } + this.reader = reader; + } + + private boolean atEOF() throws IOException { + reader.mark(2); + boolean eof = (reader.read() < 0); + reader.reset(); + return eof; + } + + /*============================================================*\ + || Parsing || + \*============================================================*/ + + private int m_version; + private boolean m_haveVersion = false; + public int version() throws IOException { + if (!m_haveVersion) { + m_version = Read.i32(reader); + m_haveVersion = true; + } + return m_version; + } + + private Instant m_startTime; + public Instant startTime() throws IOException { + if (m_startTime == null) { + switch (version()) { + case 0: // ????-???? 2012 + m_startTime = Read.LVTimestamp(reader); + break; + case 1: // ????-???? 2014 + m_startTime = Read.LVTimestamp(reader); + break; + case 2: // ????-2015 + throw new UnsupportedVersionException("DSLOG (TODO)", 2); + case 3: // 2016-now + m_startTime = Read.LVTimestamp(reader); + break; + default: + throw new UnsupportedVersionException("DSLOG", version(), 3); + } + } + return m_startTime; + } + + private long i = 0; + public Entry readEntry() throws IOException { + if (atEOF()) { + return null; + } + switch (version()) { case 0: return new Entry() {{ - time = startTime.plusMillis(20*i++); + time = startTime().plusMillis(20*i++); /* 0 = 0 */ /* 0+4= 4 */tripTime = Duration.ofNanos((long)(Read.f32(reader)*1000)); @@ -86,9 +118,7 @@ class DslogReader implements Closeable { }}; case 1: return new Entry() {{ - time = startTime.plusMillis(20*i++); - - time = startTime.plusMillis(20*i++); + time = startTime().plusMillis(20*i++); /* 0 = 0 */ /* 0+4= 4 */tripTime = Duration.ofNanos((long)(Read.f32(reader)*1000)); @@ -104,10 +134,10 @@ class DslogReader implements Closeable { /* 13+1=14 */lostPackets = Read.i8(reader); }}; case 2: - throw new UnsupportedOperationException("TODO: DSLOG v2 support"); + throw new UnsupportedVersionException("DSLOG (TODO)", 2); case 3: return new Entry() {{ - time = startTime.plusMillis(20*i++); + time = startTime().plusMillis(20*i++); // Read the 35-byte structure // Read the 10 bytes of non-PDP data @@ -147,10 +177,36 @@ class DslogReader implements Closeable { /* 24+1=25 */pdpTemperature = Read.u8(reader); }}; default: - throw new UnsupportedOperationException("DSLOG file version newer than log reader"); + throw new UnsupportedVersionException("DSLOG", version(), 3); } } + /*============================================================*\ + || Interfaces || + \*============================================================*/ + + private IOException m_err; + private Entry m_next; + public boolean hasNext() { + if (m_next == null) { + try { + m_next = readEntry(); + } catch (IOException e) { + m_err = e; + } + } + return m_next != null; + } + public Entry next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + return m_next; + } + public IOException err() { + return m_err; + } + public void close() throws IOException { reader.close(); } diff --git a/dslog/Logdir.java b/dslog/Logdir.java index 90661bb..b798757 100644 --- a/dslog/Logdir.java +++ b/dslog/Logdir.java @@ -42,7 +42,7 @@ class Logdir { if (filename.endsWith(".dslog")) { String setname = filename.substring(0, filename.lastIndexOf('.')); try (DslogReader dslog = new DslogReader(Files.newInputStream(filepath))) { - getSet(logsets, setname).dslog = ""+dslog.version; + getSet(logsets, setname).dslog = ""+dslog.version(); } catch (Exception e) { getSet(logsets, setname).pdplog = "☠"; throw e; @@ -50,7 +50,7 @@ class Logdir { } else if (filename.endsWith(".dsevents")) { String setname = filename.substring(0, filename.lastIndexOf('.')); try (DseventsReader dsevents = new DseventsReader(Files.newInputStream(filepath))) { - getSet(logsets, setname).dsevents = ""+dsevents.version; + getSet(logsets, setname).dsevents = ""+dsevents.version(); } catch (Exception e) { getSet(logsets, setname).pdplog = "☠"; throw e; @@ -58,7 +58,7 @@ class Logdir { } else if (filename.endsWith(".pdplog")) { String setname = filename.substring(0, filename.lastIndexOf('.')); try (PdplogReader pdplog = new PdplogReader(Files.newInputStream(filepath))) { - getSet(logsets, setname).pdplog = ""+pdplog.version; + getSet(logsets, setname).pdplog = ""+pdplog.version(); } catch (Exception e) { getSet(logsets, setname).pdplog = "☠"; throw e; diff --git a/dslog/Main.java b/dslog/Main.java index 0c95c50..5ea1a64 100644 --- a/dslog/Main.java +++ b/dslog/Main.java @@ -14,8 +14,8 @@ class Main { for (String filename : args) { System.out.println("Filename: "+filename); DslogReader file = new DslogReader(Files.newInputStream(Paths.get(filename))); - System.out.println("Format Version: "+file.version); - System.out.println("Start Time: "+file.startTime); + System.out.println("Format Version: "+file.version()); + System.out.println("Start Time: "+file.startTime()); CsvWriter.Dslog2CSV(file, System.out); } } diff --git a/dslog/PdplogReader.java b/dslog/PdplogReader.java index 3df9c2b..2618101 100644 --- a/dslog/PdplogReader.java +++ b/dslog/PdplogReader.java @@ -1,25 +1,54 @@ package dslog; +import java.io.BufferedInputStream; import java.io.Closeable; import java.io.IOException; import java.io.InputStream; -import java.lang.UnsupportedOperationException; class PdplogReader implements Closeable { - private final InputStream reader; - public final int version; + /*============================================================*\ + || Primitive IO || + \*============================================================*/ + private final InputStream reader; public PdplogReader(InputStream reader) throws IOException { + if (!reader.markSupported()) { + reader = new BufferedInputStream(reader); + } this.reader = reader; - this.version = Read.i32(reader); - switch (this.version) { + } + + private boolean atEOF() throws IOException { + reader.mark(2); + boolean eof = (reader.read() < 0); + reader.reset(); + return eof; + } + + + /*============================================================* \ + || Parsing || + \*============================================================*/ + + private int m_version; + private boolean m_haveVersion = false; + public int version() throws IOException { + if (!m_haveVersion) { + m_version = Read.i32(reader); + m_haveVersion = true; + } + return m_version; + } + + public void read() throws IOException { + switch (version()) { case 0: // ????-???? - throw new UnsupportedOperationException("TODO: PDPLOG v0 support"); + throw new UnsupportedVersionException("PDPLOG (TODO)", 0); case 1: // ????-2015 - throw new UnsupportedOperationException("TODO: PDPLOG v1 support"); + throw new UnsupportedVersionException("PDPLOG (TODO)", 1); default: - throw new UnsupportedOperationException("Unrecognized PDPLOG version: "+this.version); + throw new UnsupportedVersionException("PDPLOG", version(), 1); } } diff --git a/dslog/UnsupportedVersionException.java b/dslog/UnsupportedVersionException.java new file mode 100644 index 0000000..2667804 --- /dev/null +++ b/dslog/UnsupportedVersionException.java @@ -0,0 +1,12 @@ +package dslog; + +import java.io.IOException; + +class UnsupportedVersionException extends IOException { + public UnsupportedVersionException(String thing, int version) { + super("Unsupported file format version: "+thing+" v"+version); + } + public UnsupportedVersionException(String thing, int version, int cur) { + super("File format version ("+thing+" v"+version+") new that log reader ("+cur+")"); + } +} -- cgit v1.2.3