PUD: nmealib: fix parsing of date in GPRMC
authorFerry Huberts <ferry.huberts@pelagic.nl>
Tue, 12 Mar 2013 16:16:25 +0000 (17:16 +0100)
committerFerry Huberts <ferry.huberts@pelagic.nl>
Tue, 12 Mar 2013 16:17:16 +0000 (17:17 +0100)
It appears that the field is optional/can be empty and that parsing
such an empty field would fail.

Signed-off-by: Ferry Huberts <f.huberts@mindef.nl>
lib/pud/nmealib/src/parse.c

index 092a703..392c887 100644 (file)
@@ -76,6 +76,35 @@ static bool _nmea_parse_time(const char *s, const int len, nmeaTIME *t) {
 }
 
 /**
+ * Parse nmeaTIME (date only, no time) from a string.
+ * The month is adjusted -1 to comply with the nmeaTIME month range of [0, 11].
+ * The year is adjusted +100 for years before 90 to comply with the nmeaTIME
+ * year range of [90, 189].
+ *
+ * @param date the date
+ * @param t a pointer to the nmeaTIME structure in which to store the parsed date
+ * @return true on success, false otherwise
+ */
+static bool _nmea_parse_date(const int date, nmeaTIME *t) {
+       assert(t);
+
+       if ((date < 0) || (date > 999999)) {
+               nmea_error("Parse error: invalid time format in %d", date);
+               return false;
+       }
+
+       t->day = date / 10000;
+       t->mon = (date / 100) % 100;
+       t->mon--;
+       t->year = date % 100;
+       if (t->year < 90) {
+               t->year += 100;
+       }
+
+       return true;
+}
+
+/**
  * Validate the time fields in an nmeaTIME structure.
  * Expects:
  * <pre>
@@ -617,6 +646,7 @@ int nmea_parse_GPGSV(const char *s, const int len, nmeaGPGSV *pack) {
 int nmea_parse_GPRMC(const char *s, const int len, nmeaGPRMC *pack) {
        int token_count;
        char time_buff[NMEA_TIMEPARSE_BUF];
+       int date;
        size_t time_buff_len = 0;
 
        assert(s);
@@ -628,6 +658,7 @@ int nmea_parse_GPRMC(const char *s, const int len, nmeaGPRMC *pack) {
         * Clear before parsing, to be able to detect absent fields
         */
        time_buff[0] = '\0';
+       date = -1;
        pack->present = 0;
        pack->utc.year = -1;
        pack->utc.mon = -1;
@@ -648,31 +679,18 @@ int nmea_parse_GPRMC(const char *s, const int len, nmeaGPRMC *pack) {
        pack->mode = 0;
 
        /* parse */
-       token_count = nmea_scanf(s, len, "$GPRMC,%s,%c,%f,%c,%f,%c,%f,%f,%2d%2d%2d,%f,%c,%c*", &time_buff[0], &pack->status,
-                       &pack->lat, &pack->ns, &pack->lon, &pack->ew, &pack->speed, &pack->track, &pack->utc.day, &pack->utc.mon,
-                       &pack->utc.year, &pack->magvar, &pack->magvar_ew, &pack->mode);
+       token_count = nmea_scanf(s, len, "$GPRMC,%s,%c,%f,%c,%f,%c,%f,%f,%d,%f,%c,%c*", &time_buff[0], &pack->status,
+                       &pack->lat, &pack->ns, &pack->lon, &pack->ew, &pack->speed, &pack->track, date,
+                       &pack->magvar, &pack->magvar_ew, &pack->mode);
 
        /* see that we have enough tokens */
-       if ((token_count != 13) && (token_count != 14)) {
-               nmea_error("GPRMC parse error: need 13 or 14 tokens, got %d in %s", token_count, s);
+       if ((token_count != 11) && (token_count != 12)) {
+               nmea_error("GPRMC parse error: need 11 or 12 tokens, got %d in %s", token_count, s);
                return 0;
        }
 
        /* determine which fields are present and validate them */
 
-       if ((pack->utc.year != -1) && (pack->utc.mon != -1) && (pack->utc.day != -1)) {
-               if (pack->utc.year < 90) {
-                       pack->utc.year += 100;
-               }
-               pack->utc.mon -= 1;
-
-               if (!validateDate(&pack->utc)) {
-                       return 0;
-               }
-
-               nmea_INFO_set_present(&pack->present, UTCDATE);
-       }
-
        time_buff_len = strlen(&time_buff[0]);
        if (time_buff_len) {
                if (!_nmea_parse_time(&time_buff[0], time_buff_len, &pack->utc)) {
@@ -715,6 +733,19 @@ int nmea_parse_GPRMC(const char *s, const int len, nmeaGPRMC *pack) {
        if (!isnan(pack->track)) {
                nmea_INFO_set_present(&pack->present, TRACK);
        }
+
+       if (date != -1) {
+               if (!_nmea_parse_date(date, &pack->utc)) {
+                       return 0;
+               }
+
+               if (!validateDate(&pack->utc)) {
+                       return 0;
+               }
+
+               nmea_INFO_set_present(&pack->present, UTCDATE);
+       }
+
        if (!isnan(pack->magvar) && (pack->magvar_ew)) {
                if (!validateNSEW(&pack->magvar_ew, false)) {
                        return 0;