Pathaway module improvements (revisited)

View: New views
2 Messages — Rating Filter:   Alert me  

Pathaway module improvements (revisited)

by Andrei Boros :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,

I've done some more work on the Pathaway module. Now it should safely
handle most of date/time errors or inconsistencies seamlessly.
Warnings and more information is available on debug levels 1,3,5 as to
the progress and inconsistencies in the data.

Anyway, by now I get clean conversions on my dataset (which is quite
large, taken with several revisions of pathaway through time).

Module adds dbicon parameter : set database icon (also known as vehicle
by pathaway)
Module adds deficon parameter : set point icon (other then input, or if
not input icon available).
Warnings now are more detailed and available at -D 1
More information on the inconsistent input records at -D 3
Dump of processing progress at -D 5

Date handling now consideres 8 digit date as YYYYMMDD (unless specified
by parameter) or 6 digit date as DDMMYY and uses the 1970 base for Y2K
handling.
Invalid date/time information is corrected or zeroed as much as
possible, also spaces are trimmed out (in newer revisions of Pathaway 4).

Pathaway 4 and 5 for Windows Mobile use a CSV like text file which I
haven't fully figured out yet, they are not handled by this module.

Attached patch is against yesterday's cvs tree.

Andrei


--- gpsbabel-cvs/pathaway.c 2009-07-18 23:25:24.000000000 +0300
+++ gpsbabel/pathaway.c 2009-08-21 21:51:30.000000000 +0300
@@ -70,6 +70,7 @@
 static unsigned char german_release = 0;
 static char *datefmt;
 static int ct;
+static int _warn = 0;
 
 typedef struct ppdb_appdata
 {
@@ -126,7 +127,7 @@
 #endif
 
 
-#define CHECK_INP(i, j, k) is_fatal((i != j), "Error in data structure (%s).", (k))
+#define CHECK_INP(i, j, k, l) is_fatal((i != j), "Error in data structure (in %s? Value is : %s).", (k), (l))
 
 /*
  * utilities
@@ -285,7 +286,7 @@
 
  if (*str < 'A') /* only numeric */
  {
-    CHECK_INP(1, sscanf(str,"%lf", &val), "decode_coord(1)");
+    CHECK_INP(1, sscanf(str,"%lf", &val), "decode_coord(1) DD.dddd", str);
     return val;
  }
  else
@@ -297,12 +298,12 @@
     tmp = strchr(str, ' ');
     if ((tmp) && (tmp - str < 5))
     {
- CHECK_INP(3, sscanf(str,"%c%d %lf", &dir, °, &val), "decode_coord(2)");
+ CHECK_INP(3, sscanf(str,"%c%d %lf", &dir, °, &val), "decode_coord(2) DD MM.mmm", str);
  val = deg + (val / 60.0);
     }
     else
     {
- CHECK_INP(2, sscanf(str,"%c%lf", &dir, &val), "decode_coord(3)");
+ CHECK_INP(2, sscanf(str,"%c%lf", &dir, &val), "decode_coord(3) DD.dddd", str);
     }
     if ((dir == 'S') || (dir == 'W'))
  val = -val;
@@ -318,32 +319,62 @@
  int temp=0;
  char *cx;
     
- while (*str == ' ') str++; /* WORKAROUND may start with or contain several empty spaces, but no date or time info */
+ str = lrtrim(str);              /* time field may start/end with spaces, drop them */
     
- if (*str == '\0') return 0; /* empty date and time */
+        if (*str == '\0')
+        {
+ if (global_opts.debug_level > 0)
+ {
+                warning(MYNAME ": Time value missing, reseting to 0\n");
+                _warn = 1;
+ }
+                return 0;                       /* empty time field */
+        }
 
  if (strchr(str, '.')) /* time in hhmmss.ms */
  {
  CHECK_INP(4, sscanf(str, "%02d%02d%02d.%d",
  &tm->tm_hour, &tm->tm_min, &tm->tm_sec, &msec),
- "decode_tm(1)");
+ "decode_tm(1) hhmmss.ss", str);
  }
  else if (sscanf(str,"%06d",&temp)==1)
  /* WORKAROUND read time info only if a valid 6 digit string found */
  {
  CHECK_INP(3, sscanf(str, "%02d%02d%02d",
  &tm->tm_hour, &tm->tm_min, &tm->tm_sec),
- "decode_tm(2)");
+ "decode_tm(2) hhmmss", str);
  }
  else
  {
+ if (global_opts.debug_level > 0)
+ {
+    warning(MYNAME ": Invalid time value, reseting to 0\n");
+                    _warn = 1;
+ }
  return 0; /* WORKAROUND maybe invalid time, just ignore it and continue */
  }
  cx = strchr(str, ' ');
- if (cx == NULL) return 0; /* no date */
 
- while (*cx == ' ') cx++;
- if (*cx == '\0') return 0; /* no date */
+        if (cx == NULL)
+        {
+ if (global_opts.debug_level > 0)
+ {
+                warning(MYNAME ": Date value missing, reseting to 0\n");
+                _warn = 1;
+ }
+                return 0;       /* empty date field */
+        }
+
+        cx = lrtrim(cx);
+        if (*cx == '\0')
+        {
+ if (global_opts.debug_level > 0)
+ {
+                warning(MYNAME ": Date value missing, found only spaces, reseting to 0\n");
+                _warn = 1;
+ }
+                return 0;       /* empty date field */
+        }
 
  if (datefmt)
  {
@@ -363,28 +394,23 @@
  time_t tnow;
  struct tm now;
 
- if (strlen(cx) != 8)
- {
- printf(MYNAME ": Date from first record is %s.\n", cx);
- printf(MYNAME ": Please use option 'date' to specify how this is formatted.\n");
- fatal(MYNAME  ": (... -i pathaway,date=DDMMYY ...)\n");
- }
-
- CHECK_INP(4, sscanf(cx, "%02d%02d%02d%02d", &d1, &d2, &d3, &d4), "decode_tm(3)");
 
  tnow = current_time();
  now = *localtime(&tnow);
  now.tm_year += 1900;
  now.tm_mon++;
 
- year = (d1 * 100) + d2;
+ if (strlen(cx) == 8)
+ {    
+    CHECK_INP(4, sscanf(cx, "%02d%02d%02d%02d", &d1, &d2, &d3, &d4), "decode_tm(3) invalid date (YYYYMMDD)", cx);
 
+    year = (d1 * 100) + d2;
  /* the coordinates comes before date and time in
    the dataset, so the flag "german_release" is set yet. */
 
  /* next code works for most, except for 19. and 20. of month */
 
- if ((german_release != 0) || (year < 1980) || (year > now.tm_year)) /* YYYYMMDD or DDMMYYY ????? */
+    if ((german_release != 0) || (year < 1980) || (year > now.tm_year)) /* YYYYMMDD or DDMMYYYY ????? */
  {
     tm->tm_year = (d3 * 100) + d4;
     tm->tm_mon = d2;
@@ -396,6 +422,26 @@
     tm->tm_mon = d3;
     tm->tm_mday = d4;
  }
+ } else if (strlen(cx) == 6)
+ {
+    CHECK_INP(3, sscanf(cx, "%02d%02d%02d", &d1, &d2, &d3), "decode_tm(3) invalid date (DDMMYY)", cx);
+    if (d3 < 1970) /* Usual Y2K interpretation */
+ year = d3 + 2000;
+    else
+ year = d3 + 1900;
+    
+/* I don't know how a german release handles this
+ * so for now I will assume only DDMMYY if date has 6 digits
+ */
+    tm->tm_year = year;
+    tm->tm_mon = d2;
+    tm->tm_mday = d1;
+ } else /* date string is neither 8 nor 6 digits */
+ {
+ printf(MYNAME ": Date from first record is %s.\n", cx);
+ printf(MYNAME ": Please use option 'date' to specify how this is formatted.\n");
+ fatal(MYNAME  ": (... -i pathaway,date=DDMMYY ...)\n");
+ }
  }
  return 1;
 }
@@ -412,7 +458,15 @@
  int line = 0;
  char *tmp = data;
 
-// while ((str = csv_lineparse(tmp, ",", """", line++))) {
+/* Print the whole input record. All input records are printed before processing. */
+               if (global_opts.debug_level >= 5)
+               {
+                       DBG(("\n\
+--- BEGIN Input data record -----------------------------------------------\n\
+%s\n\
+--- END Input data record -------------------------------------------------\n",data));
+               }
+
  while ((str = csv_lineparse(tmp, ",", "\"", line++))) {
     tmp = NULL;
     switch(line)
@@ -426,7 +480,7 @@
  case 3: /* altitude */
     if (*str != '\0')
     {
- CHECK_INP(1, sscanf(str, "%lf", &altfeet), "altitude");
+ CHECK_INP(1, sscanf(str, "%lf", &altfeet), "altitude", str);
  if (altfeet != -9999)
     wpt_tmp->altitude = FEET_TO_METERS(altfeet);
     }
@@ -456,6 +510,16 @@
     }
  }
 
+/* Print the whole input record, should a warning be triggered.
+ * Use warning() here instead of DBG() to print the data record
+ * right after the warning is issued.
+ */
+               if (_warn && (global_opts.debug_level > 1) && (global_opts.debug_level < 5))
+               {
+                       warning("Faulty input data record : %s\n",data);
+                       _warn = 0;
+               }
+
  if (head && isRoute )
     route_add_wpt(head, wpt_tmp);
  else if (head)
@@ -671,8 +735,7 @@
  /* 6 icon */
 
  tmp = str_pool_getcpy(wpt->icon_descr, opt_deficon); /* point icon or deficon from options */
- buff = ppdb_strcat(buff, tmp, "0", &len);
- /* buff = ppdb_strcat(buff, opt_deficon, "0", &len);*/
+ buff = ppdb_strcat(buff, tmp, NULL, &len);
  buff = ppdb_strcat(buff, ",", NULL, &len);
  /* 7 description */
 
@@ -710,13 +773,15 @@
  file_out->version = 3;
 
 /* Waypoint target does use vehicleStr from appinfo block
- Actually, all 3 types have vehicle information.
- if (global_opts.objective != wptdata) / * Waypoint target do not need appinfo block * /
- {   */
+ * Actually, all 3 types have vehicle information.
+ * if (global_opts.objective != wptdata) / * Waypoint target do not need appinfo block * /
+ * {  
+ */
     appinfo = xcalloc(1, sizeof(*appinfo));
     file_out->appinfo = (void *)appinfo;
     file_out->appinfo_len = PPDB_APPINFO_SIZE;
-/* }   */
+/* }  
+ */
  if (opt_dbicon != NULL) strncpy(appinfo->vehicleStr, opt_dbicon, VEHICLE_LEN);
 
  switch(global_opts.objective) /* Only one target is possible */

------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Gpsbabel-code mailing list  http://www.gpsbabel.org
Gpsbabel-code@...
https://lists.sourceforge.net/lists/listinfo/gpsbabel-code

Re: Pathaway module improvements (revisited)

by Robert Lipe-4 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Thanx.  I've applied this.  I also took this chance to move '_warn' out of C reserved namespace.

Can you please provide a few sentences of doc for the new options?

Thanx,
RJL

On Fri, Aug 21, 2009 at 2:11 PM, Andrei Boros <andrei@...> wrote:
Hi,

I've done some more work on the Pathaway module. Now it should safely
handle most of date/time errors or inconsistencies seamlessly.
Warnings and more information is available on debug levels 1,3,5 as to
the progress and inconsistencies in the data.

Anyway, by now I get clean conversions on my dataset (which is quite
large, taken with several revisions of pathaway through time).

Module adds dbicon parameter : set database icon (also known as vehicle
by pathaway)
Module adds deficon parameter : set point icon (other then input, or if
not input icon available).
Warnings now are more detailed and available at -D 1
More information on the inconsistent input records at -D 3
Dump of processing progress at -D 5

Date handling now consideres 8 digit date as YYYYMMDD (unless specified
by parameter) or 6 digit date as DDMMYY and uses the 1970 base for Y2K
handling.
Invalid date/time information is corrected or zeroed as much as
possible, also spaces are trimmed out (in newer revisions of Pathaway 4).

Pathaway 4 and 5 for Windows Mobile use a CSV like text file which I
haven't fully figured out yet, they are not handled by this module.

Attached patch is against yesterday's cvs tree.

Andrei


--- gpsbabel-cvs/pathaway.c     2009-07-18 23:25:24.000000000 +0300
+++ gpsbabel/pathaway.c 2009-08-21 21:51:30.000000000 +0300
@@ -70,6 +70,7 @@
 static unsigned char german_release = 0;
 static char *datefmt;
 static int ct;
+static int _warn = 0;

 typedef struct ppdb_appdata
 {
@@ -126,7 +127,7 @@
 #endif


-#define CHECK_INP(i, j, k) is_fatal((i != j), "Error in data structure (%s).", (k))
+#define CHECK_INP(i, j, k, l) is_fatal((i != j), "Error in data structure (in %s? Value is : %s).", (k), (l))

 /*
 * utilities
@@ -285,7 +286,7 @@

       if (*str < 'A')         /* only numeric */
       {
-           CHECK_INP(1, sscanf(str,"%lf", &val), "decode_coord(1)");
+           CHECK_INP(1, sscanf(str,"%lf", &val), "decode_coord(1) DD.dddd", str);
           return val;
       }
       else
@@ -297,12 +298,12 @@
           tmp = strchr(str, ' ');
           if ((tmp) && (tmp - str < 5))
           {
-               CHECK_INP(3, sscanf(str,"%c%d %lf", &dir, &deg, &val), "decode_coord(2)");
+               CHECK_INP(3, sscanf(str,"%c%d %lf", &dir, &deg, &val), "decode_coord(2) DD MM.mmm", str);
               val = deg + (val / 60.0);
           }
           else
           {
-               CHECK_INP(2, sscanf(str,"%c%lf", &dir, &val), "decode_coord(3)");
+               CHECK_INP(2, sscanf(str,"%c%lf", &dir, &val), "decode_coord(3) DD.dddd", str);
           }
           if ((dir == 'S') || (dir == 'W'))
               val = -val;
@@ -318,32 +319,62 @@
       int temp=0;
       char *cx;

-       while (*str == ' ') str++;      /* WORKAROUND may start with or contain several empty spaces, but no date or time info */
+       str = lrtrim(str);              /* time field may start/end with spaces, drop them */

-       if (*str == '\0') return 0;     /* empty date and time */
+        if (*str == '\0')
+        {
+               if (global_opts.debug_level > 0)
+               {
+                   warning(MYNAME ": Time value missing, reseting to 0\n");
+                   _warn = 1;
+               }
+                return 0;                       /* empty time field */
+        }

       if (strchr(str, '.'))           /* time in hhmmss.ms */
       {
               CHECK_INP(4, sscanf(str, "%02d%02d%02d.%d",
                       &tm->tm_hour, &tm->tm_min, &tm->tm_sec, &msec),
-                       "decode_tm(1)");
+                       "decode_tm(1) hhmmss.ss", str);
       }
       else if (sscanf(str,"%06d",&temp)==1)
                                       /* WORKAROUND read time info only if a valid 6 digit string found */
       {
               CHECK_INP(3, sscanf(str, "%02d%02d%02d",
                       &tm->tm_hour, &tm->tm_min, &tm->tm_sec),
-                       "decode_tm(2)");
+                       "decode_tm(2) hhmmss", str);
       }
       else
       {
+               if (global_opts.debug_level > 0)
+               {
+                   warning(MYNAME ": Invalid time value, reseting to 0\n");
+                    _warn = 1;
+               }
               return 0;               /* WORKAROUND maybe invalid time, just ignore it and continue */
       }
       cx = strchr(str, ' ');
-       if (cx == NULL) return 0;       /* no date */

-       while (*cx == ' ') cx++;
-       if (*cx == '\0') return 0;      /* no date */
+        if (cx == NULL)
+        {
+               if (global_opts.debug_level > 0)
+               {
+                   warning(MYNAME ": Date value missing, reseting to 0\n");
+                   _warn = 1;
+               }
+                return 0;       /* empty date field */
+        }
+
+        cx = lrtrim(cx);
+        if (*cx == '\0')
+        {
+               if (global_opts.debug_level > 0)
+               {
+                   warning(MYNAME ": Date value missing, found only spaces, reseting to 0\n");
+                   _warn = 1;
+               }
+                return 0;       /* empty date field */
+        }

       if (datefmt)
       {
@@ -363,28 +394,23 @@
               time_t tnow;
               struct tm now;

-               if (strlen(cx) != 8)
-               {
-                       printf(MYNAME ": Date from first record is %s.\n", cx);
-                       printf(MYNAME ": Please use option 'date' to specify how this is formatted.\n");
-                       fatal(MYNAME  ": (... -i pathaway,date=DDMMYY ...)\n");
-               }
-
-               CHECK_INP(4, sscanf(cx, "%02d%02d%02d%02d", &d1, &d2, &d3, &d4), "decode_tm(3)");

               tnow = current_time();
               now = *localtime(&tnow);
               now.tm_year += 1900;
               now.tm_mon++;

-               year = (d1 * 100) + d2;
+               if (strlen(cx) == 8)
+               {
+                   CHECK_INP(4, sscanf(cx, "%02d%02d%02d%02d", &d1, &d2, &d3, &d4), "decode_tm(3) invalid date (YYYYMMDD)", cx);

+                   year = (d1 * 100) + d2;
               /* the coordinates comes before date and time in
                  the dataset, so the flag "german_release" is set yet. */

               /* next code works for most, except for 19. and 20. of month */

-               if ((german_release != 0) || (year < 1980) || (year > now.tm_year))     /* YYYYMMDD or DDMMYYY ????? */
+                   if ((german_release != 0) || (year < 1980) || (year > now.tm_year)) /* YYYYMMDD or DDMMYYYY ????? */
               {
                   tm->tm_year = (d3 * 100) + d4;
                   tm->tm_mon = d2;
@@ -396,6 +422,26 @@
                   tm->tm_mon = d3;
                   tm->tm_mday = d4;
               }
+               } else if (strlen(cx) == 6)
+               {
+                   CHECK_INP(3, sscanf(cx, "%02d%02d%02d", &d1, &d2, &d3), "decode_tm(3) invalid date (DDMMYY)", cx);
+                   if (d3 < 1970)                      /* Usual Y2K interpretation */
+                       year = d3 + 2000;
+                   else
+                       year = d3 + 1900;
+
+/* I don't know how a german release handles this
+ * so for now I will assume only DDMMYY if date has 6 digits
+ */
+                   tm->tm_year = year;
+                   tm->tm_mon = d2;
+                   tm->tm_mday = d1;
+               } else                  /* date string is neither 8 nor 6 digits */
+               {
+                       printf(MYNAME ": Date from first record is %s.\n", cx);
+                       printf(MYNAME ": Please use option 'date' to specify how this is formatted.\n");
+                       fatal(MYNAME  ": (... -i pathaway,date=DDMMYY ...)\n");
+               }
       }
       return 1;
 }
@@ -412,7 +458,15 @@
               int line = 0;
               char *tmp = data;

-//             while ((str = csv_lineparse(tmp, ",", """", line++))) {
+/* Print the whole input record. All input records are printed before processing. */
+               if (global_opts.debug_level >= 5)
+               {
+                       DBG(("\n\
+--- BEGIN Input data record -----------------------------------------------\n\
+%s\n\
+--- END Input data record -------------------------------------------------\n",data));
+               }
+
               while ((str = csv_lineparse(tmp, ",", "\"", line++))) {
                   tmp = NULL;
                   switch(line)
@@ -426,7 +480,7 @@
                       case 3:         /* altitude */
                           if (*str != '\0')
                           {
-                               CHECK_INP(1, sscanf(str, "%lf", &altfeet), "altitude");
+                               CHECK_INP(1, sscanf(str, "%lf", &altfeet), "altitude", str);
                               if (altfeet != -9999)
                                   wpt_tmp->altitude = FEET_TO_METERS(altfeet);
                           }
@@ -456,6 +510,16 @@
                   }
               }

+/* Print the whole input record, should a warning be triggered.
+ * Use warning() here instead of DBG() to print the data record
+ * right after the warning is issued.
+ */
+               if (_warn && (global_opts.debug_level > 1) && (global_opts.debug_level < 5))
+               {
+                       warning("Faulty input data record : %s\n",data);
+                       _warn = 0;
+               }
+
               if (head && isRoute )
                   route_add_wpt(head, wpt_tmp);
               else if (head)
@@ -671,8 +735,7 @@
                               /* 6 icon */

       tmp = str_pool_getcpy(wpt->icon_descr, opt_deficon);    /* point icon or deficon from options */
-       buff = ppdb_strcat(buff, tmp, "0", &len);
-       /* buff = ppdb_strcat(buff, opt_deficon, "0", &len);*/
+       buff = ppdb_strcat(buff, tmp, NULL, &len);
       buff = ppdb_strcat(buff, ",", NULL, &len);
                               /* 7 description */

@@ -710,13 +773,15 @@
       file_out->version = 3;

 /*     Waypoint target does use vehicleStr from appinfo block
-       Actually, all 3 types have vehicle information.
-       if (global_opts.objective != wptdata)   / * Waypoint target do not need appinfo block * /
-       {   */
+ *     Actually, all 3 types have vehicle information.
+ *     if (global_opts.objective != wptdata)   / * Waypoint target do not need appinfo block * /
+ *     {
+ */
           appinfo = xcalloc(1, sizeof(*appinfo));
           file_out->appinfo = (void *)appinfo;
           file_out->appinfo_len = PPDB_APPINFO_SIZE;
-/*     }   */
+/*     }
+ */
       if (opt_dbicon != NULL) strncpy(appinfo->vehicleStr, opt_dbicon, VEHICLE_LEN);

       switch(global_opts.objective)           /* Only one target is possible */

------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Gpsbabel-code mailing list  http://www.gpsbabel.org
Gpsbabel-code@...
https://lists.sourceforge.net/lists/listinfo/gpsbabel-code



------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
Gpsbabel-code mailing list  http://www.gpsbabel.org
Gpsbabel-code@...
https://lists.sourceforge.net/lists/listinfo/gpsbabel-code