diff options
author | Luke Shumaker <lukeshu@lukeshu.com> | 2017-03-12 04:05:42 -0400 |
---|---|---|
committer | Luke Shumaker <lukeshu@lukeshu.com> | 2017-03-12 04:05:42 -0400 |
commit | a6db0254bf9bc3f4ed1058c20cf294b66d455be4 (patch) | |
tree | dbdd79b3cf4b1fa9ab315b93a8f353d38bcfe92f /dslog/Read.java |
initial commit
Diffstat (limited to 'dslog/Read.java')
-rw-r--r-- | dslog/Read.java | 143 |
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); + } +} |