2003-02-19 00:36:42 +08:00
|
|
|
#include <osg/ArgumentParser>
|
2003-02-19 05:10:42 +08:00
|
|
|
#include <osg/ApplicationUsage>
|
2003-04-01 16:47:11 +08:00
|
|
|
#include <osg/Notify>
|
2003-02-19 00:36:42 +08:00
|
|
|
|
2003-02-19 19:32:15 +08:00
|
|
|
#include <set>
|
2003-04-01 16:47:11 +08:00
|
|
|
#include <iostream>
|
2003-02-19 19:32:15 +08:00
|
|
|
|
2003-02-19 00:36:42 +08:00
|
|
|
using namespace osg;
|
|
|
|
|
2003-02-19 05:10:42 +08:00
|
|
|
ArgumentParser::ArgumentParser(int* argc,char **argv):
|
|
|
|
_argc(argc),
|
|
|
|
_argv(argv),
|
|
|
|
_usage(ApplicationUsage::instance())
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2003-04-07 05:32:44 +08:00
|
|
|
std::string ArgumentParser::getApplicationName() const
|
2003-02-19 00:36:42 +08:00
|
|
|
{
|
2003-10-04 00:29:34 +08:00
|
|
|
if (_argc && *_argc>0 ) return std::string(_argv[0]);
|
2003-02-19 00:36:42 +08:00
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
int ArgumentParser::find(const std::string& str) const
|
|
|
|
{
|
|
|
|
for(int pos=1;pos<*_argc;++pos)
|
|
|
|
{
|
2003-02-19 19:32:15 +08:00
|
|
|
if (str==_argv[pos])
|
|
|
|
{
|
|
|
|
return pos;
|
|
|
|
}
|
2003-02-19 00:36:42 +08:00
|
|
|
}
|
|
|
|
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;
|
|
|
|
|
|
|
|
bool hadPlusMinus = false;
|
|
|
|
bool hadDecimalPlace = false;
|
|
|
|
bool hadExponent = false;
|
|
|
|
bool couldBeInt = true;
|
|
|
|
bool couldBeFloat = true;
|
|
|
|
int noZeroToNine = 0;
|
|
|
|
|
|
|
|
const char* ptr = _argv[pos];
|
|
|
|
|
|
|
|
// check if could be a hex number.
|
|
|
|
if (strncmp(ptr,"0x",2)==0)
|
|
|
|
{
|
|
|
|
// skip over leading 0x, and then go through rest of string
|
|
|
|
// checking to make sure all values are 0...9 or a..f.
|
|
|
|
ptr+=2;
|
|
|
|
while (
|
|
|
|
*ptr!=0 &&
|
|
|
|
((*ptr>='0' && *ptr<='9') ||
|
|
|
|
(*ptr>='a' && *ptr<='f') ||
|
|
|
|
(*ptr>='A' && *ptr<='F'))
|
|
|
|
)
|
|
|
|
{
|
|
|
|
++ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// got to end of string without failure, therefore must be a hex integer.
|
|
|
|
if (*ptr==0) return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
ptr = _argv[pos];
|
|
|
|
// check if a float or an int.
|
|
|
|
while (*ptr!=0 && couldBeFloat)
|
|
|
|
{
|
|
|
|
if (*ptr=='+' || *ptr=='-')
|
|
|
|
{
|
|
|
|
if (hadPlusMinus)
|
|
|
|
{
|
|
|
|
couldBeInt = false;
|
|
|
|
couldBeFloat = false;
|
|
|
|
} else hadPlusMinus = true;
|
|
|
|
}
|
|
|
|
else if (*ptr>='0' && *ptr<='9')
|
|
|
|
{
|
|
|
|
noZeroToNine++;
|
|
|
|
}
|
|
|
|
else if (*ptr=='.')
|
|
|
|
{
|
|
|
|
if (hadDecimalPlace)
|
|
|
|
{
|
|
|
|
couldBeInt = false;
|
|
|
|
couldBeFloat = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
hadDecimalPlace = true;
|
|
|
|
couldBeInt = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (*ptr=='e' || *ptr=='E')
|
|
|
|
{
|
|
|
|
if (hadExponent || noZeroToNine==0)
|
|
|
|
{
|
|
|
|
couldBeInt = false;
|
|
|
|
couldBeFloat = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
hadExponent = true;
|
|
|
|
couldBeInt = false;
|
|
|
|
hadDecimalPlace = false;
|
|
|
|
hadPlusMinus = false;
|
|
|
|
noZeroToNine=0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
couldBeInt = false;
|
|
|
|
couldBeFloat = false;
|
|
|
|
}
|
|
|
|
++ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (couldBeInt && noZeroToNine>0) return true;
|
|
|
|
if (couldBeFloat && noZeroToNine>0) return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ArgumentParser::containsOptions() const
|
|
|
|
{
|
|
|
|
for(int pos=1;pos<*_argc;++pos)
|
|
|
|
{
|
|
|
|
if (isOption(pos)) return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ArgumentParser::remove(int pos,int num)
|
|
|
|
{
|
|
|
|
if (num==0) return;
|
|
|
|
|
|
|
|
for(;pos+num<*_argc;++pos)
|
|
|
|
{
|
|
|
|
_argv[pos]=_argv[pos+num];
|
|
|
|
}
|
|
|
|
for(;pos<*_argc;++pos)
|
|
|
|
{
|
|
|
|
_argv[pos]=0;
|
|
|
|
}
|
|
|
|
*_argc-=num;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ArgumentParser::read(const std::string& str)
|
|
|
|
{
|
|
|
|
int pos=find(str);
|
|
|
|
if (pos<=0) return false;
|
|
|
|
remove(pos);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ArgumentParser::read(const std::string& str,std::string& value1)
|
|
|
|
{
|
|
|
|
int pos=find(str);
|
|
|
|
if (pos<=0) return false;
|
|
|
|
if (!isString(pos+1))
|
|
|
|
{
|
|
|
|
reportError("argument to `"+str+"` is missing");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
value1 = _argv[pos+1];
|
|
|
|
remove(pos,2);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ArgumentParser::read(const std::string& str,std::string& value1,std::string& value2)
|
|
|
|
{
|
|
|
|
int pos=find(str);
|
|
|
|
if (pos<=0) return false;
|
|
|
|
if (!isString(pos+1) || !isString(pos+2) )
|
|
|
|
{
|
|
|
|
reportError("argument to `"+str+"` is missing");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
value1 = _argv[pos+1];
|
|
|
|
value2 = _argv[pos+2];
|
|
|
|
remove(pos,3);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ArgumentParser::read(const std::string& str,std::string& value1,std::string& value2,std::string& value3)
|
|
|
|
{
|
|
|
|
int pos=find(str);
|
|
|
|
if (pos<=0) return false;
|
|
|
|
if (!isString(pos+1) || !isString(pos+2) || !isString(pos+3))
|
|
|
|
{
|
|
|
|
reportError("argument to `"+str+"` is missing");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
value1 = _argv[pos+1];
|
|
|
|
value2 = _argv[pos+2];
|
|
|
|
value3 = _argv[pos+3];
|
|
|
|
remove(pos,4);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool ArgumentParser::read(const std::string& str,float& value1)
|
|
|
|
{
|
|
|
|
int pos=find(str);
|
|
|
|
if (pos<=0) return false;
|
|
|
|
if (!isNumber(pos+1))
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2003-11-25 18:56:12 +08:00
|
|
|
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]);
|
|
|
|
remove(pos,5);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2003-02-19 00:36:42 +08:00
|
|
|
bool ArgumentParser::errors(ErrorSeverity severity) const
|
|
|
|
{
|
|
|
|
for(ErrorMessageMap::const_iterator itr=_errorMessageMap.begin();
|
|
|
|
itr!=_errorMessageMap.end();
|
|
|
|
++itr)
|
|
|
|
{
|
|
|
|
if (itr->second>=severity) return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ArgumentParser::reportError(const std::string& message,ErrorSeverity severity)
|
|
|
|
{
|
|
|
|
_errorMessageMap[message]=severity;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ArgumentParser::reportRemainingOptionsAsUnrecognized(ErrorSeverity severity)
|
|
|
|
{
|
2003-02-19 19:32:15 +08:00
|
|
|
std::set<std::string> options;
|
|
|
|
if (_usage)
|
|
|
|
{
|
|
|
|
// parse the usage options to get all the option that the application can potential handle.
|
|
|
|
for(ApplicationUsage::UsageMap::const_iterator itr=_usage->getCommandLineOptions().begin();
|
|
|
|
itr!=_usage->getCommandLineOptions().end();
|
|
|
|
++itr)
|
|
|
|
{
|
|
|
|
const std::string& option = itr->first;
|
2003-04-02 02:50:36 +08:00
|
|
|
std::string::size_type prevpos = 0, pos = 0;
|
2003-02-19 19:32:15 +08:00
|
|
|
while ((pos=option.find(' ',prevpos))!=std::string::npos)
|
|
|
|
{
|
2003-04-01 16:47:11 +08:00
|
|
|
if (option[prevpos]=='-')
|
|
|
|
{
|
2003-04-02 04:52:56 +08:00
|
|
|
options.insert(std::string(option,prevpos,pos-prevpos));
|
2003-04-01 16:47:11 +08:00
|
|
|
}
|
2003-02-19 19:32:15 +08:00
|
|
|
prevpos=pos+1;
|
|
|
|
}
|
2003-04-01 16:47:11 +08:00
|
|
|
if (option[prevpos]=='-')
|
|
|
|
{
|
|
|
|
|
2003-04-02 04:52:56 +08:00
|
|
|
options.insert(std::string(option,prevpos,std::string::npos));
|
2003-04-01 16:47:11 +08:00
|
|
|
}
|
2003-02-19 19:32:15 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2003-02-19 00:36:42 +08:00
|
|
|
for(int pos=1;pos<argc();++pos)
|
|
|
|
{
|
2003-02-19 19:32:15 +08:00
|
|
|
// if an option and havn't been previous querried for report as unrecognized.
|
|
|
|
if (isOption(pos) && options.find(_argv[pos])==options.end())
|
|
|
|
{
|
2003-11-25 19:06:39 +08:00
|
|
|
reportError(getApplicationName() +": unrecognized option "+_argv[pos],severity);
|
2003-02-19 19:32:15 +08:00
|
|
|
}
|
2003-02-19 00:36:42 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
void ArgumentParser::writeErrorMessages(std::ostream& output,ErrorSeverity severity)
|
|
|
|
{
|
|
|
|
for(ErrorMessageMap::iterator itr=_errorMessageMap.begin();
|
|
|
|
itr!=_errorMessageMap.end();
|
|
|
|
++itr)
|
|
|
|
{
|
|
|
|
if (itr->second>=severity)
|
|
|
|
{
|
2003-04-07 05:32:44 +08:00
|
|
|
output<< getApplicationName() << ": " << itr->first << std::endl;
|
2003-02-19 00:36:42 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|