From: Christian P. <cp...@us...> - 2005-01-20 19:56:42
|
Update of /cvsroot/pclasses/pclasses2/src/App In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv9042/src/App Modified Files: CmdLine.cpp Log Message: Finished advanced command line parsing. Index: CmdLine.cpp =================================================================== RCS file: /cvsroot/pclasses/pclasses2/src/App/CmdLine.cpp,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- CmdLine.cpp 20 Jan 2005 11:02:01 -0000 1.3 +++ CmdLine.cpp 20 Jan 2005 19:56:29 -0000 1.4 @@ -20,14 +20,19 @@ #include "pclasses/App/CmdLine.h" #include <sstream> +#include <iomanip> +#include <iostream> namespace P { namespace App { CmdLineOption::CmdLineOption(const std::string& shortOpt, - const std::string& longOpt, bool required) -: _shortOpt(shortOpt), _longOpt(longOpt), _required(required) + const std::string& longOpt, const std::string& helpText, + bool required, bool needValue) +: _isset(false), _shortOpt(shortOpt), _longOpt(longOpt), + _helpText(helpText), _required(required), + _needValue(needValue) { } @@ -45,61 +50,89 @@ return _longOpt; } +const std::string& CmdLineOption::helpText() const throw() +{ + return _helpText; +} + bool CmdLineOption::required() const throw() { return _required; } +bool CmdLineOption::isset() const throw() +{ + return _isset; +} + +bool CmdLineOption::needValue() const throw() +{ + return _needValue; +} CmdLineFlag::CmdLineFlag(const std::string& shortOpt, - const std::string& longOpt, bool defaultVal, bool required) -: CmdLineOption(shortOpt, longOpt, required), _defaultVal(defaultVal) + const std::string& longOpt, const std::string& helpText, + bool defaultVal, bool required) +: CmdLineOption(shortOpt, longOpt, helpText, required, false), + _defaultVal(defaultVal) { } + CmdLineFlag::~CmdLineFlag() { } +void CmdLineFlag::setValue(const std::string& val) +{ + _isset = true; +} -CmdLineValue::CmdLineValue(const std::string& shortOpt, - const std::string& longOpt, const std::string& defaultVal, bool required) -: CmdLineOption(shortOpt, longOpt, required), _defaultVal(defaultVal) +std::string CmdLineFlag::value() const throw() { + return std::string(_isset ? "1" : "0"); } -CmdLineValue::~CmdLineValue() + +CmdLineValue::CmdLineValue(const std::string& shortOpt, + const std::string& longOpt, const std::string& helpText, + const std::string& defaultVal) +: CmdLineOption(shortOpt, longOpt, helpText, false, true), + _defaultVal(defaultVal) { } +CmdLineValue::CmdLineValue(const std::string& shortOpt, + const std::string& longOpt, const std::string& helpText, + bool required) +: CmdLineOption(shortOpt, longOpt, helpText, required, true), + _defaultVal("") +{ +} -CmdLineParser::CmdLineParser(CmdLineOption* opts[]) -: _opts(opts) +CmdLineValue::~CmdLineValue() { } -CmdLineParser::~CmdLineParser() +void CmdLineValue::setValue(const std::string& val) { + _value = val; + _isset = true; } -bool CmdLineParser::parse(int argc, char* argv[]) +std::string CmdLineValue::value() const throw() { - _parsedOpts.clear(); + return _value; +} - std::ostringstream os; - for(int i = 1; i < argc; ++i) - { - os << argv[i]; - if(i+1 < argc) - os << ' '; - } - return parse(os.str()); +CmdLineParser::CmdLineParser(CmdLineOption* opts[]) +: _opts(opts) +{ } -void parseOptName(std::istream& is, std::string& optName) +CmdLineParser::~CmdLineParser() { - // break on '=' and ' ' } CmdLineOption* findOptShort(CmdLineOption* opts[], std::string& shortOpt) @@ -130,42 +163,126 @@ return 0; } -bool CmdLineParser::parse(const std::string& cmdline) +CmdLineError::CmdLineError(const std::string& what, const SourceInfo& si) +: RuntimeError(what, si) { - std::istringstream is(cmdline); +} - char ch; - while((is >> ch)) +CmdLineError::~CmdLineError() +{ +} + + +void CmdLineParser::parse(int argc, char* argv[]) throw(CmdLineError) +{ + _unnamedValues.clear(); + CmdLineOption* opt = 0; + + std::string optName, optVal; + std::string tmp; + + for(int i = 1; i < argc; ++i) { - if(ch == '-') - { - std::string optName; - CmdLineOption* opt = 0; + tmp = argv[i]; - is >> ch; + if(tmp.size() > 1 && tmp[0] == '-') + { + bool isLongOpt = false; - if(ch != '-') + // long option? + if(tmp.size() > 2 && tmp[1] == '-') { - is.unget(); - parseOptName(is, optName); - opt = findOptShort(_opts, optName); + isLongOpt = true; + tmp = tmp.substr(2, std::string::npos); } + // must be a short option ... else { - parseOptName(is, optName); - opt = findOptLong(_opts, optName); + tmp = tmp.substr(1, std::string::npos); } - // unknown option? + // split option=value string + // the value may also be processed later .. (that is in the next iteration + // of the loop) + std::string::size_type pos = tmp.find('='); + optName = tmp.substr(0, pos); + if(pos != std::string::npos) + optVal = tmp.substr(pos+1, std::string::npos); + + // find the option object .... + if(isLongOpt) + opt = findOptLong(_opts, optName); + else + opt = findOptShort(_opts, optName); + + // unknown option ... if(!opt) + throw CmdLineError("Unknown command line option: " + + std::string(argv[i]), P_SOURCEINFO); + + // do we have value for this option ....? + // it doesnt matter if the option needs a value or not... + // option values for flags are simply discarded + if(pos != std::string::npos) { - //@fixme throw CmdLineError() - return false; + opt->setValue(optVal); + opt = 0; + } + // option does not need a value... + else if(!opt->needValue()) + { + opt->setValue(std::string()); + opt = 0; + } + } + // option value ... + else + { + // the value is for the current option... + if(opt) + { + opt->setValue(tmp); + opt = 0; + } + // unnamed option value ... + else + { + _unnamedValues.push_back(tmp); } } } +} - return false; +const std::string& CmdLineParser::value(unsigned int index) const + throw(OutOfBounds) +{ + if(index < _unnamedValues.size()) + return _unnamedValues[index]; + + throw OutOfBounds("Value-index is out of bounds", P_SOURCEINFO); +} + +unsigned int CmdLineParser::valueCount() const throw() +{ + return _unnamedValues.size(); +} + +void CmdLineParser::parse(const std::string& cmdline) throw(CmdLineError) +{ + throw CmdLineError("Not implemented", P_SOURCEINFO); +} + +void CmdLineParser::dumpHelp(std::ostream& os) const +{ + int i = 0; + while(_opts[i]) + { + os << std::setw(10) << "-"+_opts[i]->shortName() << ' ' + << std::setw(20) << "--"+_opts[i]->longName() << " " + << _opts[i]->helpText() << std::endl; + + ++i; + } } |