]> git.mxchange.org Git - flightgear.git/commitdiff
Clean-up date/time option parser.
authorThorstenB <brehmt@gmail.com>
Sun, 30 Oct 2011 13:48:53 +0000 (14:48 +0100)
committerThorstenB <brehmt@gmail.com>
Sun, 30 Oct 2011 13:48:53 +0000 (14:48 +0100)
Add range checks and provide error messages.
Extend time offset to 64bit - so we're safe for 2038-01-19 (and the next
couple of millions years beyond...).
Support partial date/time strings, such as --start-date-gmt=2011 or
--start-date-gmt=:::12:00:00

src/Main/options.cxx
src/Time/TimeManager.cxx
src/Time/TimeManager.hxx

index 180b12fd65455ea9a6f14637ac0edce8398aed41..5ca9cd2cffe7781c4e7304b129dacaa161902933 100644 (file)
@@ -283,6 +283,57 @@ parse_wind (const string &wind, double * min_hdg, double * max_hdg,
   return true;
 }
 
+static bool
+parseIntValue(char** ppParserPos, int* pValue,int min, int max, const char* field, const char* argument)
+{
+    if ( !strlen(*ppParserPos) )
+        return true;
+
+    char num[256];
+    int i = 0;
+
+    while ( isdigit((*ppParserPos)[0]) && (i<255) )
+    {
+        num[i] = (*ppParserPos)[0];
+        (*ppParserPos)++;
+        i++;
+    }
+    num[i] = '\0';
+
+    switch ((*ppParserPos)[0])
+    {
+        case 0:
+            break;
+        case ':':
+            (*ppParserPos)++;
+            break;
+        default:
+            SG_LOG(SG_GENERAL, SG_ALERT, "Illegal character in time string for " << field << ": '" <<
+                    (*ppParserPos)[0] << "'.");
+            // invalid field - skip rest of string to avoid further errors
+            while ((*ppParserPos)[0])
+                (*ppParserPos)++;
+            return false;
+    }
+
+    if (i<=0)
+        return true;
+
+    int value = atoi(num);
+    if ((value < min)||(value > max))
+    {
+        SG_LOG(SG_GENERAL, SG_ALERT, "Invalid " << field << " in '" << argument <<
+               "'. Valid range is " << min << "-" << max << ".");
+        return false;
+    }
+    else
+    {
+        *pValue = value;
+        return true;
+    }
+}
+
+#ifndef HAVE_RINT
 // parse a time string ([+/-]%f[:%f[:%f]]) into hours
 static double
 parse_time(const string& time_in) {
@@ -363,113 +414,65 @@ parse_time(const string& time_in) {
 
     return(sign * result);
 }
-
+#endif
 
 // parse a date string (yyyy:mm:dd:hh:mm:ss) into a time_t (seconds)
 static long int
-parse_date( const string& date)
+parse_date( const string& date, const char* timeType)
 {
-    struct tm gmt;
-    char * date_str, num[256];
-    int i;
-    // initialize to zero
-    gmt.tm_sec = 0;
-    gmt.tm_min = 0;
-    gmt.tm_hour = 0;
-    gmt.tm_mday = 0;
-    gmt.tm_mon = 0;
-    gmt.tm_year = 0;
-    gmt.tm_isdst = 0; // ignore daylight savings time for the moment
-    date_str = (char *)date.c_str();
-    // get year
-    if ( strlen(date_str) ) {
-       i = 0;
-       while ( (date_str[0] != ':') && (date_str[0] != '\0') ) {
-           num[i] = date_str[0];
-           date_str++;
-           i++;
-       }
-       if ( date_str[0] == ':' ) {
-           date_str++;
-       }
-       num[i] = '\0';
-       gmt.tm_year = atoi(num) - 1900;
-    }
-    // get month
-    if ( strlen(date_str) ) {
-       i = 0;
-       while ( (date_str[0] != ':') && (date_str[0] != '\0') ) {
-           num[i] = date_str[0];
-           date_str++;
-           i++;
-       }
-       if ( date_str[0] == ':' ) {
-           date_str++;
-       }
-       num[i] = '\0';
-       gmt.tm_mon = atoi(num) -1;
-    }
-    // get day
-    if ( strlen(date_str) ) {
-       i = 0;
-       while ( (date_str[0] != ':') && (date_str[0] != '\0') ) {
-           num[i] = date_str[0];
-           date_str++;
-           i++;
-       }
-       if ( date_str[0] == ':' ) {
-           date_str++;
-       }
-       num[i] = '\0';
-       gmt.tm_mday = atoi(num);
-    }
-    // get hour
-    if ( strlen(date_str) ) {
-       i = 0;
-       while ( (date_str[0] != ':') && (date_str[0] != '\0') ) {
-           num[i] = date_str[0];
-           date_str++;
-           i++;
-       }
-       if ( date_str[0] == ':' ) {
-           date_str++;
-       }
-       num[i] = '\0';
-       gmt.tm_hour = atoi(num);
-    }
-    // get minute
-    if ( strlen(date_str) ) {
-       i = 0;
-       while ( (date_str[0] != ':') && (date_str[0] != '\0') ) {
-           num[i] = date_str[0];
-           date_str++;
-           i++;
-       }
-       if ( date_str[0] == ':' ) {
-           date_str++;
-       }
-       num[i] = '\0';
-       gmt.tm_min = atoi(num);
+    struct tm gmt,*pCurrentTime;
+    int year,month,day,hour,minute,second;
+    char *argument, *date_str;
+
+    SGTime CurrentTime = SGTime();
+    CurrentTime.update(0,0,0,0);
+
+    // FIXME This should obtain system/aircraft/GMT time depending on timeType
+    pCurrentTime = CurrentTime.getGmt();
+
+    // initialize all fields with current time
+    year   = pCurrentTime->tm_year + 1900;
+    month  = pCurrentTime->tm_mon + 1;
+    day    = pCurrentTime->tm_mday;
+    hour   = pCurrentTime->tm_hour;
+    minute = pCurrentTime->tm_min;
+    second = pCurrentTime->tm_sec;
+
+    argument = (char *)date.c_str();
+    date_str = argument;
+
+    // start with parsing year
+    if (!strlen(date_str) ||
+        !parseIntValue(&date_str,&year,0,9999,"year",argument))
+    {
+        return -1;
     }
-    // get second
-    if ( strlen(date_str) ) {
-       i = 0;
-       while ( (date_str[0] != ':') && (date_str[0] != '\0') ) {
-           num[i] = date_str[0];
-           date_str++;
-           i++;
-       }
-       if ( date_str[0] == ':' ) {
-           date_str++;
-       }
-       num[i] = '\0';
-       gmt.tm_sec = atoi(num);
+
+    if (year < 1970)
+    {
+        SG_LOG(SG_GENERAL, SG_ALERT, "Invalid year '" << year << "'. Use 1970 or later.");
+        return -1;
     }
+
+    parseIntValue(&date_str, &month,  1, 12, "month",  argument);
+    parseIntValue(&date_str, &day,    1, 31, "day",    argument);
+    parseIntValue(&date_str, &hour,   0, 23, "hour",   argument);
+    parseIntValue(&date_str, &minute, 0, 59, "minute", argument);
+    parseIntValue(&date_str, &second, 0, 59, "second", argument);
+
+    gmt.tm_sec  = second;
+    gmt.tm_min  = minute;
+    gmt.tm_hour = hour;
+    gmt.tm_mday = day;
+    gmt.tm_mon  = month - 1;
+    gmt.tm_year = year -1900;
+    gmt.tm_isdst = 0; // ignore daylight savings time for the moment
+
     time_t theTime = sgTimeGetGMT( gmt.tm_year, gmt.tm_mon, gmt.tm_mday,
-                                  gmt.tm_hour, gmt.tm_min, gmt.tm_sec );
-    //printf ("Date is %s\n", ctime(&theTime));
-    //printf ("in seconds that is %d\n", theTime);
-    //exit(1);
+                                   gmt.tm_hour, gmt.tm_min, gmt.tm_sec );
+
+    SG_LOG(SG_GENERAL, SG_INFO, "Configuring startup time to " << ctime(&theTime));
+
     return (theTime);
 }
 
@@ -486,9 +489,9 @@ parse_degree( const string& degree_str) {
 
 
 // parse time offset string into seconds
-static int
+static long int
 parse_time_offset( const string& time_str) {
-    int result;
+   long int result;
 
     // printf("time offset = %s\n", time_str);
 
@@ -811,7 +814,7 @@ fgOptBpp( const char *arg )
 static int
 fgOptTimeOffset( const char *arg )
 {
-    fgSetInt("/sim/startup/time-offset",
+    fgSetLong("/sim/startup/time-offset",
                 parse_time_offset( arg ));
     fgSetString("/sim/startup/time-offset-type", "system-offset");
     return FG_OPTIONS_OK;
@@ -820,24 +823,36 @@ fgOptTimeOffset( const char *arg )
 static int
 fgOptStartDateSys( const char *arg )
 {
-    fgSetInt("/sim/startup/time-offset", parse_date( arg ) );
-    fgSetString("/sim/startup/time-offset-type", "system");
+    long int theTime = parse_date( arg, "system" );
+    if (theTime>=0)
+    {
+        fgSetLong("/sim/startup/time-offset",  theTime);
+        fgSetString("/sim/startup/time-offset-type", "system");
+    }
     return FG_OPTIONS_OK;
 }
 
 static int
 fgOptStartDateLat( const char *arg )
 {
-    fgSetInt("/sim/startup/time-offset", parse_date( arg ) );
-    fgSetString("/sim/startup/time-offset-type", "latitude");
+    long int theTime = parse_date( arg, "latitude" );
+    if (theTime>=0)
+    {
+        fgSetLong("/sim/startup/time-offset", theTime);
+        fgSetString("/sim/startup/time-offset-type", "latitude");
+    }
     return FG_OPTIONS_OK;
 }
 
 static int
 fgOptStartDateGmt( const char *arg )
 {
-    fgSetInt("/sim/startup/time-offset", parse_date( arg ) );
-    fgSetString("/sim/startup/time-offset-type", "gmt");
+    long int theTime = parse_date( arg, "gmt" );
+    if (theTime>=0)
+    {
+        fgSetLong("/sim/startup/time-offset", theTime);
+        fgSetString("/sim/startup/time-offset-type", "gmt");
+    }
     return FG_OPTIONS_OK;
 }
 
index 5c5fd01a0033b269b6cfe08ba4fd88dcf828067c..f19761ef50ae280f9f868c0bf43325503b2abbd3 100644 (file)
@@ -302,12 +302,12 @@ void TimeManager::updateLocalTime()
 void TimeManager::initTimeOffset()
 {
 
-  int offset = fgGetInt("/sim/startup/time-offset");
+  long int offset = fgGetLong("/sim/startup/time-offset");
   string offset_type = fgGetString("/sim/startup/time-offset-type");
   setTimeOffset(offset_type, offset);
 }
 
-void TimeManager::setTimeOffset(const std::string& offset_type, int offset)
+void TimeManager::setTimeOffset(const std::string& offset_type, long int offset)
 {
   // Handle potential user specified time offsets
   int orig_warp = _warp->getIntValue();
index 7ee53ecb4e888dc3124cf2143a16bba9cfabbbf7..6f0d35acbbfa858e77a756e455a18b7b4785f755 100644 (file)
@@ -44,7 +44,7 @@ public:
 // SGPropertyChangeListener overrides
   virtual void valueChanged(SGPropertyNode *);
   
-  void setTimeOffset(const std::string& offset_type, int offset);
+  void setTimeOffset(const std::string& offset_type, long int offset);
 private:
   
   /**