Added ArgumentParser::Parameter class to make the argument parsing much more

flexible, and to simplifying the API.  The read(,,,) methods now take
Parameter objects as arguments, and this Parameter adapt what ever basic
type is passed in, so is able to transparently handle float, double, int,
unsigned int & strings.
This commit is contained in:
Robert Osfield 2004-03-19 22:03:09 +00:00
parent 28214337a3
commit 02f9ce48bc
2 changed files with 273 additions and 139 deletions

View File

@ -28,6 +28,58 @@ class ApplicationUsage;
class SG_EXPORT ArgumentParser
{
public:
class Parameter
{
public:
enum ParameterType
{
FLOAT_PARAMETER,
DOUBLE_PARAMETER,
INT_PARAMETER,
UNSIGNED_INT_PARAMETER,
STRING_PARAMETER,
};
union ValueUnion
{
float* _float;
double* _double;
int* _int;
unsigned int* _uint;
std::string* _string;
};
Parameter(float& value) { _type = FLOAT_PARAMETER; _value._float = &value; }
Parameter(double& value) { _type = DOUBLE_PARAMETER; _value._double = &value; }
Parameter(int& value) { _type = INT_PARAMETER; _value._int = &value; }
Parameter(unsigned int& value) { _type = UNSIGNED_INT_PARAMETER; _value._uint = &value; }
Parameter(std::string& value) { _type = STRING_PARAMETER; _value._string = &value; }
bool valid(const char* str) const;
bool assign(const char* str);
protected:
ParameterType _type;
ValueUnion _value;
};
/** return return true if specified string is an option in the form of -option or --option .*/
static bool isOption(const char* str);
/** return return true if string is any other string apart from an option.*/
static bool isString(const char* str);
/** return return true if specified parameter is an number.*/
static bool isNumber(const char* str);
public:
ArgumentParser(int* argc,char **argv);
void setApplicationUsage(ApplicationUsage* usage) { _usage = usage; }
@ -53,9 +105,6 @@ class SG_EXPORT ArgumentParser
* return -1 when no string is found.*/
int find(const std::string& str) const;
/** return true if specified argument matches string.*/
bool match(int pos, const std::string& str) const;
/** return return true if specified parameter is an option in the form of -option or --option .*/
bool isOption(int pos) const;
@ -70,45 +119,25 @@ class SG_EXPORT ArgumentParser
/** remove one or more arguments from the argv argument list, and decrement the argc respectively.*/
void remove(int pos,int num=1);
/** return true if specified argument matches string.*/
bool match(int pos, const std::string& str) const;
/** search for an occurance of a string in the argument list, on sucess
* remove that occurance from the list and return true, otherwise return false.*/
bool read(const std::string& str);
/** search for an occurance of a string in the argument list followed by a string,
* on sucess set the value string with the second parameters and then
* remove the two entries from the list and return true, otherwise return false.*/
bool read(const std::string& str,std::string& value1);
/** search for an occurance of a string in the argument list followed by a two strings,
* on sucess set the value strings with the second & third parameters and then
* remove the three entries from the list and return true, otherwise return false.*/
bool read(const std::string& str,std::string& value1,std::string& value2);
/** search for an occurance of a string in the argument list followed by a three strings,
* on sucess set the value strings with the second & third & fourth parameters and then
* remove the four entries from the list and return true, otherwise return false.*/
bool read(const std::string& str,std::string& value1,std::string& value2,std::string& value3);
bool read(const std::string& str, Parameter value1);
bool read(const std::string& str, Parameter value1, Parameter value2);
bool read(const std::string& str, Parameter value1, Parameter value2, Parameter value3);
bool read(const std::string& str, Parameter value1, Parameter value2, Parameter value3, Parameter value4);
/** search for an occurance of a string in the argument list followed by a numeric value,
* on sucess set the values with the second parameter and then
* remove the two entries from the list and return true, otherwise return false.*/
bool read(const std::string& str,float& value);
/** search for an occurance of a string in the argument list followed by two numeric values,
* on sucess set the values with the second & third parameters and then
* remove the three entries from the list and return true, otherwise return false.*/
bool read(const std::string& str,float& value1,float& value2);
/** search for an occurance of a string in the argument list followed by three numeric values,
* on sucess set the values with the second & third & fourth parameters and then
* remove the four entries from the list and return true, otherwise return false.*/
bool read(const std::string& str,float& value1,float& value2,float& value3);
/** search for an occurance of a string in the argument list followed by three numeric values,
* on sucess set the values with the second & third & fourth parameters and then
* remove the four entries from the list and return true, otherwise return false.*/
bool read(const std::string& str,float& value1,float& value2,float& value3,float& value4);
/** if the argument value at the position pos matches specified string, and subsequent
* paramters are also matched then set the paramter values and remove the from the list of arguments.*/
bool read(int pos, const std::string& str);
bool read(int pos, const std::string& str, Parameter value1);
bool read(int pos, const std::string& str, Parameter value1, Parameter value2);
bool read(int pos, const std::string& str, Parameter value1, Parameter value2, Parameter value3);
bool read(int pos, const std::string& str, Parameter value1, Parameter value2, Parameter value3, Parameter value4);
enum ErrorSeverity

View File

@ -7,49 +7,20 @@
using namespace osg;
ArgumentParser::ArgumentParser(int* argc,char **argv):
_argc(argc),
_argv(argv),
_usage(ApplicationUsage::instance())
bool ArgumentParser::isOption(const char* str)
{
return str && str[0]=='-';
}
std::string ArgumentParser::getApplicationName() const
bool ArgumentParser::isString(const char* str)
{
if (_argc && *_argc>0 ) return std::string(_argv[0]);
return "";
if (!str) return false;
return !isOption(str);
}
int ArgumentParser::find(const std::string& str) const
bool ArgumentParser::isNumber(const char* str)
{
for(int pos=1;pos<*_argc;++pos)
{
if (str==_argv[pos])
{
return pos;
}
}
return 0;
}
bool ArgumentParser::match(int pos, const std::string& str) const
{
return pos<*_argc && str==_argv[pos];
}
bool ArgumentParser::isOption(int pos) const
{
return (pos<*_argc && _argv[pos][0]=='-');
}
bool ArgumentParser::isString(int pos) const
{
return pos<*_argc && !isOption(pos);
}
bool ArgumentParser::isNumber(int pos) const
{
if (pos>=*_argc) return false;
if (!str) return false;
bool hadPlusMinus = false;
bool hadDecimalPlace = false;
@ -58,7 +29,7 @@ bool ArgumentParser::isNumber(int pos) const
bool couldBeFloat = true;
int noZeroToNine = 0;
const char* ptr = _argv[pos];
const char* ptr = str;
// check if could be a hex number.
if (strncmp(ptr,"0x",2)==0)
@ -80,7 +51,8 @@ bool ArgumentParser::isNumber(int pos) const
if (*ptr==0) return true;
}
ptr = _argv[pos];
ptr = str;
// check if a float or an int.
while (*ptr!=0 && couldBeFloat)
{
@ -140,6 +112,89 @@ bool ArgumentParser::isNumber(int pos) const
}
bool ArgumentParser::Parameter::valid(const char* str) const
{
switch(_type)
{
case Parameter::FLOAT_PARAMETER: return isNumber(str); break;
case Parameter::DOUBLE_PARAMETER: return isNumber(str); break;
case Parameter::INT_PARAMETER: return isNumber(str); break;
case Parameter::UNSIGNED_INT_PARAMETER: return isNumber(str); break;
case Parameter::STRING_PARAMETER: return isString(str); break;
}
return false;
}
bool ArgumentParser::Parameter::assign(const char* str)
{
if (valid(str))
{
switch(_type)
{
case Parameter::FLOAT_PARAMETER: *_value._float = atof(str); break;
case Parameter::DOUBLE_PARAMETER: *_value._double = atof(str); break;
case Parameter::INT_PARAMETER: *_value._int = atoi(str); break;
case Parameter::UNSIGNED_INT_PARAMETER: *_value._uint = atoi(str); break;
case Parameter::STRING_PARAMETER: *_value._string = str; break;
}
return true;
}
else
{
return false;
}
}
ArgumentParser::ArgumentParser(int* argc,char **argv):
_argc(argc),
_argv(argv),
_usage(ApplicationUsage::instance())
{
}
std::string ArgumentParser::getApplicationName() const
{
if (_argc && *_argc>0 ) return std::string(_argv[0]);
return "";
}
bool ArgumentParser::isOption(int pos) const
{
return pos<*_argc && isOption(_argv[pos]);
}
bool ArgumentParser::isString(int pos) const
{
return pos < *_argc && isString(_argv[pos]);
}
bool ArgumentParser::isNumber(int pos) const
{
return pos < *_argc && isNumber(_argv[pos]);
}
int ArgumentParser::find(const std::string& str) const
{
for(int pos=1;pos<*_argc;++pos)
{
if (str==_argv[pos])
{
return pos;
}
}
return 0;
}
bool ArgumentParser::match(int pos, const std::string& str) const
{
return pos<*_argc && str==_argv[pos];
}
bool ArgumentParser::containsOptions() const
{
for(int pos=1;pos<*_argc;++pos)
@ -173,114 +228,164 @@ bool ArgumentParser::read(const std::string& str)
return true;
}
bool ArgumentParser::read(const std::string& str,std::string& value1)
bool ArgumentParser::read(const std::string& str, Parameter value1)
{
int pos=find(str);
if (pos<=0) return false;
if (!isString(pos+1))
if (!value1.valid(_argv[pos+1]))
{
reportError("argument to `"+str+"` is missing");
return false;
}
value1 = _argv[pos+1];
value1.assign(_argv[pos+1]);
remove(pos,2);
return true;
}
bool ArgumentParser::read(const std::string& str,std::string& value1,std::string& value2)
bool ArgumentParser::read(const std::string& str, Parameter value1, Parameter value2)
{
int pos=find(str);
if (pos<=0) return false;
if (!isString(pos+1) || !isString(pos+2) )
if (!value1.valid(_argv[pos+1]) ||
!value2.valid(_argv[pos+2]))
{
reportError("argument to `"+str+"` is missing");
return false;
}
value1 = _argv[pos+1];
value2 = _argv[pos+2];
value1.assign(_argv[pos+1]);
value2.assign(_argv[pos+2]);
remove(pos,3);
return true;
}
bool ArgumentParser::read(const std::string& str,std::string& value1,std::string& value2,std::string& value3)
bool ArgumentParser::read(const std::string& str, Parameter value1, Parameter value2, Parameter value3)
{
int pos=find(str);
if (pos<=0) return false;
if (!isString(pos+1) || !isString(pos+2) || !isString(pos+3))
if (!value1.valid(_argv[pos+1]) ||
!value2.valid(_argv[pos+2]) ||
!value2.valid(_argv[pos+3]))
{
reportError("argument to `"+str+"` is missing");
return false;
}
value1 = _argv[pos+1];
value2 = _argv[pos+2];
value3 = _argv[pos+3];
value1.assign(_argv[pos+1]);
value2.assign(_argv[pos+2]);
value3.assign(_argv[pos+3]);
remove(pos,4);
return true;
}
bool ArgumentParser::read(const std::string& str,float& value1)
bool ArgumentParser::read(const std::string& str, Parameter value1, Parameter value2, Parameter value3, Parameter value4)
{
int pos=find(str);
if (pos<=0) return false;
if (!isNumber(pos+1))
if (!value1.valid(_argv[pos+1]) ||
!value2.valid(_argv[pos+2]) ||
!value2.valid(_argv[pos+3]) ||
!value3.valid(_argv[pos+4]))
{
reportError("argument to `"+str+"` is missing");
return false;
}
value1 = atof(_argv[pos+1]);
remove(pos,2);
return true;
}
bool ArgumentParser::read(const std::string& str,float& value1,float& value2)
{
int pos=find(str);
if (pos<=0) return false;
if (!isNumber(pos+1) || !isNumber(pos+2) )
{
reportError("argument to `"+str+"` is missing");
return false;
}
value1 = atof(_argv[pos+1]);
value2 = atof(_argv[pos+2]);
remove(pos,3);
return true;
}
bool ArgumentParser::read(const std::string& str,float& value1,float& value2,float& value3)
{
int pos=find(str);
if (pos<=0) return false;
if (!isNumber(pos+1) || !isNumber(pos+2) || !isNumber(pos+3))
{
reportError("argument to `"+str+"` is missing");
return false;
}
value1 = atof(_argv[pos+1]);
value2 = atof(_argv[pos+2]);
value3 = atof(_argv[pos+3]);
remove(pos,4);
return true;
}
bool ArgumentParser::read(const std::string& str,float& value1,float& value2,float& value3,float& value4)
{
int pos=find(str);
if (pos<=0) return false;
if (!isNumber(pos+1) || !isNumber(pos+2) || !isNumber(pos+3))
{
reportError("argument to `"+str+"` is missing");
return false;
}
value1 = atof(_argv[pos+1]);
value2 = atof(_argv[pos+2]);
value3 = atof(_argv[pos+3]);
value4 = atof(_argv[pos+4]);
value1.assign(_argv[pos+1]);
value2.assign(_argv[pos+2]);
value3.assign(_argv[pos+3]);
value4.assign(_argv[pos+4]);
remove(pos,5);
return true;
}
/** if the argument value at the psotion pos matches specified string, and subsequent
* paramters are also matched then set the paramter values and remove the from the list of arguments.*/
bool ArgumentParser::read(int pos, const std::string& str)
{
if (match(pos,str))
{
remove(pos,1);
return true;
}
else
{
return false;
}
}
bool ArgumentParser::read(int pos, const std::string& str, Parameter value1)
{
if (match(pos,str) &&
value1.valid(_argv[pos+1]))
{
value1.assign(_argv[pos+1]);
remove(pos,2);
return true;
}
else
{
return false;
}
}
bool ArgumentParser::read(int pos, const std::string& str, Parameter value1, Parameter value2)
{
if (match(pos,str) &&
value1.valid(_argv[pos+1]) &&
value2.valid(_argv[pos+2]))
{
value1.assign(_argv[pos+1]);
value2.assign(_argv[pos+2]);
remove(pos,3);
return true;
}
else
{
return false;
}
}
bool ArgumentParser::read(int pos, const std::string& str, Parameter value1, Parameter value2, Parameter value3)
{
if (match(pos,str) &&
value1.valid(_argv[pos+1]) &&
value2.valid(_argv[pos+2]) &&
value3.valid(_argv[pos+3]))
{
value1.assign(_argv[pos+1]);
value2.assign(_argv[pos+2]);
value3.assign(_argv[pos+3]);
remove(pos,4);
return true;
}
else
{
return false;
}
}
bool ArgumentParser::read(int pos, const std::string& str, Parameter value1, Parameter value2, Parameter value3, Parameter value4)
{
if (match(pos,str) &&
value1.valid(_argv[pos+1]) &&
value2.valid(_argv[pos+2]) &&
value3.valid(_argv[pos+3]) &&
value4.valid(_argv[pos+4]))
{
value1.assign(_argv[pos+1]);
value2.assign(_argv[pos+2]);
value3.assign(_argv[pos+3]);
value4.assign(_argv[pos+4]);
remove(pos,5);
return true;
}
else
{
return false;
}
}
bool ArgumentParser::errors(ErrorSeverity severity) const
{
for(ErrorMessageMap::const_iterator itr=_errorMessageMap.begin();