Clean-up date/time option parser.
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
This commit is contained in:
parent
8f50e24f88
commit
acdf0dc469
3 changed files with 128 additions and 113 deletions
|
@ -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;
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
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);
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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:
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Reference in a new issue