-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathGGAReader.cs
More file actions
39 lines (35 loc) · 1.58 KB
/
GGAReader.cs
File metadata and controls
39 lines (35 loc) · 1.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
const byte fieldSeparator = (byte)',';
ReadOnlySpan<byte> buffer = "$GPGGA,123519.00,4807.038,N,01131.000,E,1,08,0.9,545.4,M,-164.0,M,,*47"u8;
MemoryExtensions.SpanSplitEnumerator<byte> fields = buffer.Split(fieldSeparator);
if (!fields.MoveNext()) return;
ReadOnlySpan<byte> field = buffer[fields.Current];
if (field[0] is not (byte)'$' || !field.EndsWith("GGA"u8)) return;
if (!fields.MoveNext()) return;
field = buffer[fields.Current];
if (field.Length < 6 ||
!Utf8Parser.TryParse(field.Slice(0, 2), out byte hour, out int bytesConsumed) ||
bytesConsumed is not 2 ||
!Utf8Parser.TryParse(field.Slice(2, 2), out byte minute, out bytesConsumed) ||
bytesConsumed is not 2 ||
!Utf8Parser.TryParse(field.Slice(4), out double second, out bytesConsumed) ||
bytesConsumed < 2) return;
TimeOnly utcTime = new(TimeSpan.TicksPerHour * hour + TimeSpan.TicksPerMinute * minute + double.ConvertToIntegerNative<long>(double.FusedMultiplyAdd(TimeSpan.TicksPerSecond, second, .5d)));
if (!fields.MoveNext()) return;
field = buffer[fields.Current];
if (!Utf8Parser.TryParse(field.Slice(0, 2), out byte latDeg, out bytesConsumed) ||
bytesConsumed is not 2 ||
!Utf8Parser.TryParse(field.Slice(2), out double latMin, out bytesConsumed) ||
bytesConsumed < 2) return;
double lat = double.FusedMultiplyAdd(1d / 60d, latMin, latDeg);
if (!fields.MoveNext()) return;
field = buffer[fields.Current];
if (field.Length is not 1) return;
switch (field[0])
{
case (byte)'E':
lat = -lat;
break;
case not (byte)'N':
return;
}
// Not ready...