diff --git a/include/osg/ArgumentParser b/include/osg/ArgumentParser index 4aba26e7c..5997565c2 100644 --- a/include/osg/ArgumentParser +++ b/include/osg/ArgumentParser @@ -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); + 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 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); - - - /** 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 diff --git a/src/osg/ArgumentParser.cpp b/src/osg/ArgumentParser.cpp index b0a39726a..a02748870 100644 --- a/src/osg/ArgumentParser.cpp +++ b/src/osg/ArgumentParser.cpp @@ -7,50 +7,21 @@ 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; -} + if (!str) return false; -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; @@ -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();