diff --git a/SaneTsv/SaneTsv.cs b/SaneTsv/SaneTsv.cs index 52c4c18..aaefe20 100644 --- a/SaneTsv/SaneTsv.cs +++ b/SaneTsv/SaneTsv.cs @@ -33,6 +33,18 @@ public class SaneTsv public Type[] ColumnTypes { get; protected set; } public List Records { get; protected set; } public string FileComment { get; protected set; } = null; + protected static bool? _littleEndian = null; + public static bool LittleEndian + { + get + { + if (_littleEndian == null) + { + _littleEndian = BitConverter.GetBytes(double.NegativeInfinity)[7] == 255; + } + return _littleEndian.Value; + } + } public static SaneTsv ParseSimpleTsv(byte[] inputBuffer) { @@ -303,6 +315,44 @@ public class SaneTsv parsedFields[j] = fields[j]; continue; } + else if (parsed.ColumnTypes[j] == typeof(Float32LEType)) + { + byte[] floatBytes; + if (!LittleEndian) + { + floatBytes = new byte[sizeof(float)]; + for (int k = 0; k < sizeof(float); k++) + { + floatBytes[k] = fields[j][sizeof(float) - 1 - k]; + } + } + else + { + floatBytes = fields[j]; + } + parsedFields[j] = BitConverter.ToSingle(floatBytes, 0); + + continue; + } + else if (parsed.ColumnTypes[j] == typeof(Float64LEType)) + { + byte[] floatBytes; + if (!LittleEndian) + { + floatBytes = new byte[sizeof(double)]; + for (int k = 0; k < sizeof(double); k++) + { + floatBytes[k] = fields[j][sizeof(double) - 1 - k]; + } + } + else + { + floatBytes = fields[j]; + } + parsedFields[j] = BitConverter.ToDouble(floatBytes, 0); + + continue; + } string fieldString; try @@ -347,13 +397,6 @@ public class SaneTsv parsedFields[j] = parsedFloat; } - else if (parsed.ColumnTypes[j] == typeof(Float32LEType)) - { - throw new NotImplementedException(); - // TODO: Implement and do byte-swapping if necessary - - //parsedFields[j] = parsedFloat; - } else if (parsed.ColumnTypes[j] == typeof(Float64Type)) { if (!double.TryParse(fieldString, out double parsedDouble)) @@ -363,13 +406,6 @@ public class SaneTsv parsedFields[j] = parsedDouble; } - else if (parsed.ColumnTypes[j] == typeof(Float64LEType)) - { - throw new NotImplementedException(); - // TODO: Implement and do byte-swapping if necessary - - //parsedFields[j] = parsedFloat; - } else if (parsed.ColumnTypes[j] == typeof(UInt32Type)) { if (!UInt32.TryParse(fieldString, out UInt32 parsedUInt32)) diff --git a/SaneTsv/SaneTsvTest/Program.cs b/SaneTsv/SaneTsvTest/Program.cs index f12a974..fd1fc0e 100644 --- a/SaneTsv/SaneTsvTest/Program.cs +++ b/SaneTsv/SaneTsvTest/Program.cs @@ -1,4 +1,5 @@ using NathanMcRae; +using System.Linq; using System.Text; { @@ -68,6 +69,24 @@ using System.Text; } } +{ + string testName = "Float binary test"; + var bytes = new List(); + bytes.AddRange(Encoding.UTF8.GetBytes("somefloat:float64\tbinfloat:float64-le" + + "\n1.5\t")); bytes.AddRange(BitConverter.GetBytes(1.5)); + bytes.AddRange(Encoding.UTF8.GetBytes("\n-8.0000005E-14\t")); bytes.AddRange(BitConverter.GetBytes(-8.0000005E-14)); + + SaneTsv parsed = SaneTsv.ParseTypedTsv(bytes.ToArray()); + if ((double)parsed.Records[0]["binfloat"] == (double)parsed.Records[0]["somefloat"]) + { + Console.WriteLine($"Passed {testName}"); + } + else + { + Console.WriteLine($"Failed {testName}"); + } +} + Console.WriteLine("Done with tests");