gnssview_old/plugins/gnss/lib/nmea/parser.dart

263 lines
5.5 KiB
Dart
Raw Permalink Normal View History

2024-07-31 19:04:11 +08:00
import 'sentence.dart';
import 'types.dart';
class Parser {
BaseSentence baseSentence;
String? _err;
Parser(this.baseSentence);
void assertType(String typ) {
if (baseSentence.type != typ) {
setErr('type', baseSentence.type);
}
}
String? err() {
return _err;
}
void setErr(String context, String value) {
_err ??= 'nmea: ${baseSentence.prefix()} invalid $context: $value';
}
String string(int i, String context) {
if (_err != null) {
return '';
}
if (i < 0 || i >= baseSentence.fields.length) {
setErr(context, 'index out of range');
return '';
}
return baseSentence.fields[i];
}
List<String> listString(int from, String context) {
if (_err != null) {
return [];
}
if (from < 0 || from >= baseSentence.fields.length) {
setErr(context, 'index out of range');
return [];
}
return baseSentence.fields.sublist(from);
}
String enumString(
int i,
String context,
List<String> options,
) {
String? s = string(i, context);
if (_err != null || s == '') {
return '';
}
if (options.contains(s)) {
return s;
} else {
setErr(context, s);
return '';
}
}
List<String> enumChars(int i, String context, List<String> options) {
String? s = string(i, context);
if (_err != null || s == '') {
return [];
}
List<String> strs = [];
for (int j = 0; j < s.length; j++) {
String rs = s[j];
if (options.contains(rs)) {
strs.add(rs);
}
}
if (strs.length != s.length) {
setErr(context, s);
return [];
}
return strs;
}
int hexInt64(int i, String context) {
String? s = string(i, context);
if (_err != null) {
return 0;
}
if (s == '') {
return 0;
}
int value = int.parse(s, radix: 16);
return value;
}
int int64(int i, String context) {
return nullInt64(i, context).value;
}
Int64 nullInt64(int i, String context) {
String? s = string(i, context);
if (_err != null) {
return Int64(0, false);
}
if (s == '') {
return Int64(0, false);
}
int? v = int.tryParse(s);
if (v == null) {
setErr(context, s);
return Int64(0, false);
}
return Int64(v, true);
}
double float64(int i, String context) {
return nullFloat64(i, context).value;
}
Float64 nullFloat64(int i, String context) {
String? s = string(i, context);
if (_err != null) {
return Float64(0, false);
}
if (s == '') {
return Float64(0, false);
}
double? v = double.tryParse(s);
if (v == null) {
setErr(context, s);
return Float64(0, false);
}
return Float64(v, true);
}
Time time(int i, String context) {
String? s = string(i, context);
if (_err != null) {
return Time(false, 0, 0, 0, 0);
}
try {
return parseTime(s);
} catch (e) {
setErr(context, s);
return Time(false, 0, 0, 0, 0);
}
}
Date date(int i, String context) {
String? s = string(i, context);
if (_err != null) {
return Date(false, 0, 0, 0);
}
try {
return parseDate(s);
} catch (e) {
setErr(context, s);
return Date(false, 0, 0, 0);
}
}
double latLong(int i, int j, String context) {
String a = string(i, context);
String b = string(j, context);
if (_err != null) {
return 0;
}
String s = '$a $b';
double? v = parseLatLong(s);
if ((b == 'North' || b == 'South') && (v < -90.0 || v > 90.0)) {
setErr(context, 'latitude is not in range (-90, 90)');
return 0;
} else if ((b == 'West' || b == 'East') && (v < -180.0 || v > 180.0)) {
setErr(context, 'longitude is not in range (-180, 180)');
return 0;
}
return v;
}
List<int> sixBitASCIIArmour(int i, int fillBits, String context) {
if (_err != null) {
return [];
}
if (fillBits < 0 || fillBits >= 6) {
setErr(context, 'fill bits');
return [];
}
List<int> payload = string(i, 'encoded payload').codeUnits;
int numBits = payload.length * 6 - fillBits;
if (numBits < 0) {
setErr(context, 'num bits');
return [];
}
List<int> result = List.filled(numBits, 0);
int resultIndex = 0;
for (int v in payload) {
if (v < 48 || v >= 120) {
setErr(context, 'data byte');
return [];
}
int d = v - 48;
if (d > 40) {
d -= 8;
}
for (int i = 5; i >= 0 && resultIndex < result.length; i--) {
result[resultIndex] = (d >> i) & 1;
resultIndex++;
}
}
return result;
}
}
class Time {
bool isValid;
int hour;
int minute;
int second;
int millisecond;
Time(this.isValid, this.hour, this.minute, this.second, this.millisecond);
}
Time parseTime(String s) {
if (s == "") {
return Time(false, 0, 0, 0, 0);
}
RegExp timeRe = RegExp(r"^\d{6}(\.\d*)?$");
if (!timeRe.hasMatch(s)) {
throw Exception("parse time: expected hhmmss.ss format, got '$s'");
}
int hour = int.parse(s.substring(0, 2));
int minute = int.parse(s.substring(2, 4));
double second = double.parse(s.substring(4));
int whole = second.floor(); // 获取整数部分
double frac = second - whole; // 获取小数部分
return Time(true, hour, minute, whole.toInt(), (frac * 1000).round());
}
mixin math {}
class Int64 {
int value;
bool valid;
Int64(this.value, this.valid);
}
class Float64 {
double value;
bool valid;
Float64(this.value, this.valid);
}