summaryrefslogtreecommitdiff
path: root/dslog/Read.java
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2017-03-12 04:05:42 -0400
committerLuke Shumaker <lukeshu@lukeshu.com>2017-03-12 04:05:42 -0400
commita6db0254bf9bc3f4ed1058c20cf294b66d455be4 (patch)
treedbdd79b3cf4b1fa9ab315b93a8f353d38bcfe92f /dslog/Read.java
initial commit
Diffstat (limited to 'dslog/Read.java')
-rw-r--r--dslog/Read.java143
1 files changed, 143 insertions, 0 deletions
diff --git a/dslog/Read.java b/dslog/Read.java
new file mode 100644
index 0000000..04537d5
--- /dev/null
+++ b/dslog/Read.java
@@ -0,0 +1,143 @@
+package dslog;
+
+import java.math.BigInteger;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.EOFException;
+import java.time.Instant;
+
+class Read {
+ public static void full(InputStream in, byte b[]) throws IOException {
+ int n = 0;
+ while (n < b.length) {
+ int count = in.read(b, n, b.length - n);
+ if (count < 0)
+ throw new EOFException();
+ n += count;
+ }
+ }
+
+ public static short u8(InputStream in) throws IOException {
+ int n = in.read();
+ if (n < 0)
+ throw new EOFException();
+ return (short)n;
+ }
+
+ public static byte i8(InputStream in) throws IOException {
+ return (byte)u8(in);
+ }
+
+
+ public static int u16(InputStream in) throws IOException {
+ byte bytes[] = new byte[2];
+ full(in, bytes);
+ return (((bytes[0] & 0xff) << 8) +
+ ((bytes[1] & 0xff) << 0));
+ }
+
+ public static short i16(InputStream in) throws IOException {
+ return (short)u16(in);
+ }
+
+ public static int i32(InputStream in) throws IOException {
+ byte bytes[] = new byte[4];
+ full(in, bytes);
+ return (((bytes[0] & 0xff) << 32) +
+ ((bytes[1] & 0xff) << 16) +
+ ((bytes[2] & 0xff) << 8) +
+ ((bytes[3] & 0xff) << 0));
+ }
+
+ public static long u32(InputStream in) throws IOException {
+ byte bytes[] = new byte[4];
+ full(in, bytes);
+ return (((long)(bytes[0] & 0xff) << 32) +
+ ((long)(bytes[1] & 0xff) << 16) +
+ ((long)(bytes[2] & 0xff) << 8) +
+ ((long)(bytes[3] & 0xff) << 0));
+ }
+
+ public static long i64(InputStream in) throws IOException {
+ byte bytes[] = new byte[8];
+ full(in, bytes);
+ return (((long)(bytes[0] & 0xff) << 56) +
+ ((long)(bytes[1] & 0xff) << 48) +
+ ((long)(bytes[2] & 0xff) << 40) +
+ ((long)(bytes[3] & 0xff) << 32) +
+ ((long)(bytes[4] & 0xff) << 24) +
+ ((long)(bytes[5] & 0xff) << 16) +
+ ((long)(bytes[6] & 0xff) << 8) +
+ ((long)(bytes[7] & 0xff) << 0));
+ }
+
+ public static BigInteger u64(InputStream in) throws IOException {
+ byte bytes[] = new byte[8];
+ full(in, bytes);
+ return BigInteger.valueOf(0)
+ .add(BigInteger.valueOf(bytes[0] & 0xff).shiftLeft(56))
+ .add(BigInteger.valueOf(bytes[1] & 0xff).shiftLeft(48))
+ .add(BigInteger.valueOf(bytes[2] & 0xff).shiftLeft(40))
+ .add(BigInteger.valueOf(bytes[3] & 0xff).shiftLeft(32))
+ .add(BigInteger.valueOf(bytes[4] & 0xff).shiftLeft(24))
+ .add(BigInteger.valueOf(bytes[5] & 0xff).shiftLeft(16))
+ .add(BigInteger.valueOf(bytes[6] & 0xff).shiftLeft( 8))
+ .add(BigInteger.valueOf(bytes[7] & 0xff).shiftLeft( 0));
+ }
+
+ public static float f32(InputStream in) throws IOException {
+ return Float.intBitsToFloat(i32(in));
+ }
+
+ public static double f64(InputStream in) throws IOException {
+ return Double.longBitsToDouble(i64(in));
+ }
+
+ public static int[] u10x4(InputStream in) throws IOException {
+ byte bytes[] = new byte[5];
+ full(in, bytes);
+ return new int[]{
+ ((bytes[0] & 0b1111_1111) << 2)+
+ ((bytes[1] & 0b1100_0000) >> 6),
+ ((bytes[1] & 0b0011_1111) << 4)+
+ ((bytes[2] & 0b1111_0000) >> 4),
+ ((bytes[2] & 0b0000_1111) << 6)+
+ ((bytes[3] & 0b1111_1100) >> 2),
+ ((bytes[3] & 0b0000_1111) << 8)+
+ ((bytes[4] & 0b1111_1111) >> 0),
+ };
+ }
+
+ public static final Instant LABVIEW_EPOCH = Instant.parse("1904-01-01T00:00:00.00Z");
+
+ /**
+ * @bug LabVIEW timestamps have greater precision
+ * (sub-attosecond) than Java time.Instant (nanosecond)
+ * or Java util.Date (millisecond), so converting to a
+ * native Java timestamp necessarily loses some
+ * precision.
+ *
+ * @see http://www.ni.com/tutorial/7900/en/
+ */
+ public static Instant LVTimestamp(InputStream in) throws IOException {
+ // seconds since the epoch 01/01/1904 00:00:00.00 UTC
+ // (using the Gregorian calendar and ignoring leap
+ // seconds),
+ long secs = i64(in);
+ // positive fractions of a second; 2¯⁶⁴ths of a second
+ BigInteger frac = u64(in);
+ // To get from (2¯⁶⁴s to ns, we need to divide by
+ // precisely 18446744073.709551616 (=10¯⁹/2¯⁶⁴)... but
+ // rounding up already gives us sub-nanosecond
+ // precision, so don't worry about the .709...
+ long nanos = frac.divide(BigInteger.valueOf(18446744074L)).longValue();
+ return LABVIEW_EPOCH.plusSeconds(secs).plusNanos(nanos);
+ }
+
+ public static String LVString(InputStream in) throws IOException {
+ int len = i32(in);
+ byte[] bytes = new byte[len];
+ full(in, bytes);
+ return new String(bytes);
+ }
+}